Android 基础

来源:互联网 发布:乐高编程机器人难不难 编辑:程序博客网 时间:2024/06/05 16:52
    点击事件 1        屏幕点击事件  4    数据存储    4        手机内存的文件输入输出 5        手机存储空间的划分   7        SD卡的文件输入输出  8        文件读写权限  9        SharedPreferences的使用    10        xml文件的序列化器XmlSerializer 12        xml文件的解析器XmlPullParser  14        Json数据解析    16        SQLite数据库操作 17    数据显示    26        ListView显示数据    26        常见对话框合集 31    网络编程    36        流的工具方法  36        子线程更新UI的步骤  37            Handler使用示例代码:  38        简单的子线程更新UI的步骤(在Activity中)   40        HTTP请求  41            1.URL面向过程的请求方式  41            2.HttpClient面向对象的请求方式   44            3.开源框架的Http请求   46        菜单  47        文件上传开源框架    49        自定义控件SmartImageView网络图片加载器  50        综合案例-新闻客户端  56            示例代码    57        断点下载    70        断点下载开源框架 afinal-master  78    Activity    79        意图Intent    79            显式意图    80            隐式意图    80        页面间的数据传递    81            设置intent的数据 81            获取数据    82        隐式意图的应用 82        浏览器示例代码:    82        请求码和结果码 84        横竖屏切换的生命周期(ctrl+F11)    90        启动模式和任务栈    91    广播接收者   92        接收广播    92        代码注册广播接收者   94        发送广播    97            自定义无序广播 97            自定义有序广播 97    Service服务   98        本地服务    98        startService(intent)方式开启服务  99            案例-电话窃听器    99        进程的优先级  104        bind方式开启服务  105        混合调用服务的生命周期处理   109        远程服务    109        远程服务案例  109        利用通知栏提醒提升服务优先级  114        综合案例-音乐播放器  116    内容提供者   122        内容提供者编写的步骤  122        内容观察者   131    多媒体编程   132        加载大图片   132        图片处理    134        图片画画板   141        图片调色器   144        视频播放器   147        SoundPool   152        拍照  153        录像  154    传感器 154        光传感器    154        方向传感器   156    动画  157        帧动画 157        补间动画    159        补间动画XML配置   162        属性动画    168    Fragment    171

点击事件

  1. 内部类

    protected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    setContentView(R.layout.activity_main);    bt = (Button) findViewById(R.id.click);    bt.setOnClickListener(new MyListener());}private class MyListener implements OnClickListener{    @Override    public void onClick(View v) {        Toast.makeText(MainActivity.this, "我被點擊了", 0).show();    }}
  2. 匿名内部类

    protected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    setContentView(R.layout.activity_main);    bt = (Button) findViewById(R.id.click);    bt.setOnClickListener(new OnClickListener() {    @Override    public void onClick(View v) {        Toast.makeText(MainActivity.this, "我被點擊了", 0).show();    }    });}
  3. 让activity实现onclickListener接口

    public class MainActivity extends Activity implements OnClickListener{    private Button bt1;    private Button bt2;    private Button bt3;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        bt1 = (Button) findViewById(R.id.click1);        bt2 = (Button) findViewById(R.id.click2);        bt3 = (Button) findViewById(R.id.click3);        bt1.setOnClickListener(this);        bt2.setOnClickListener(this);        bt3.setOnClickListener(this);    }    @Override    public void onClick(View v) {        switch (v.getId()) {        case R.id.click1:            Toast.makeText(this, "按钮1", 0).show();            break;        case R.id.click2:            Toast.makeText(this, "按钮2", 0).show();            break;        case R.id.click3:            Toast.makeText(this, "按钮3", 0).show();            break;          }    }}
  4. 在布局xml文件里面绑定点击事件

    <Button    android:onClick="click"    android:layout_centerInParent="true"    android:layout_width="wrap_content"    android:layout_height="wrap_content"    android:text="点我" />public void click(View v){    Toast.makeText(this, "我被点击了", 0).show();}

屏幕点击事件

        @Override        public boolean onTouchEvent(MotionEvent event) {            if(event.getAction()==MotionEvent.ACTION_DOWN){                System.out.println("-------");                seekBar1.setVisibility(View.VISIBLE);                new Thread(){                    public void run() {                        SystemClock.sleep(3000);                        runOnUiThread(new Runnable() {                            @Override                            public void run() {                                seekBar1.setVisibility(View.INVISIBLE);                            }                        });                    };                }.start();            }            return super.onTouchEvent(event);        }

数据存储

手机内存的文件输入输出

  getFileDir(); 获取自己的文件夹 /data/data/包名/files  getCacheDir();               /data/data/包名/cache
@Overrideprotected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    setContentView(R.layout.activity_main);    //寻找这些控件    et_qqnumber = (EditText) findViewById(R.id.et_qqnumber);    et_password = (EditText) findViewById(R.id.et_password);    cb_remember = (CheckBox) findViewById(R.id.cb_remember);    restoreInfo();}/** * 登陆按钮的点击事件 * @param view */public void login(View view){    String qq = et_qqnumber.getText().toString().trim();    String password = et_password.getText().toString().trim();    if(TextUtils.isEmpty(qq)||TextUtils.isEmpty(password)){        Toast.makeText(this, "用户名和密码不能为空", 0).show();        return;    }else{        //判断是否需要记录用户名和密码        if(cb_remember.isChecked()){//被选中状态,需要记录用户名和密码            try {                File file = new File(this.getFilesDir(),"info.txt");                FileOutputStream fos = new FileOutputStream(file);                //10000##123456                String info = qq +"##"+password;                fos.write(info.getBytes());                fos.close();            } catch (Exception e) {                e.printStackTrace();            }        }        //登陆操作的. 模拟登陆,数据应该提交给服务器 由服务器比较是否正确        if("10000".equals(qq)&&"123456".equals(password)){            Toast.makeText(this, "登陆成功", 0).show();        }else{            Toast.makeText(this, "登陆失败", 0).show();        }    }}/** * 根据原来保存的文件信息,把qq号码和密码信息回显到界面 * getFilesDir()//获取应用程序files目录  /data/data/包名/files/   文件夹 */public  void restoreInfo(){    File file = new File(this.getFilesDir(),"info.txt");    if(file.exists()&&file.length()>0){        try {            FileInputStream fis = new FileInputStream(file);            BufferedReader br = new BufferedReader(new InputStreamReader(fis));            //10000##123456            String info = br.readLine();            String qq = info.split("##")[0];            String pwd = info.split("##")[1];            et_qqnumber.setText(qq);            et_password.setText(pwd);        } catch (Exception e) {            e.printStackTrace();        }    }}

手机存储空间的划分

@Overrideprotected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    setContentView(R.layout.activity_main);    File dataFile = Environment.getDataDirectory(); // 数据内部存储空间    File sdFile = Environment.getExternalStorageDirectory();// 外部存储空间    long datasize = dataFile.getTotalSpace();    long sdsize = sdFile.getTotalSpace();    TextView tv = (TextView) findViewById(R.id.tv);    tv.setText("内部存储:" + Formatter.formatFileSize(this, datasize) + "\n"            + "外部sd卡:" + Formatter.formatFileSize(this, sdsize));    // 三星  小米  魅族     // /mnt/sdcard    // /mnt/storage01    // /mnt/stoarge02    // /mnt/mount/stoarge01}

SD卡的文件输入输出

/** * 模拟向sd卡写一个视频文件.  * @param view */public void click(View view) {    // 检查的sd卡的状态    if (Environment.getExternalStorageState().equals(            Environment.MEDIA_MOUNTED)) {        File sdFile = Environment.getExternalStorageDirectory();// 外部存储空间        long sdsize = sdFile.getFreeSpace();        if (sdsize >5* 1024 * 1024) {            File file = new File(Environment.getExternalStorageDirectory(),                    System.currentTimeMillis()+"hlw.3gp");            try {                FileOutputStream fos = new FileOutputStream(file);                byte[] buffer = new byte[1024];                for (int i = 0; i < 5*1024; i++) {                    fos.write(buffer);                }                fos.close();            } catch (Exception e) {                e.printStackTrace();            }        }else{            Toast.makeText(this, "sd卡空间不足", 0).show();        }    } else {        Toast.makeText(this, "sd卡被拔出或者是不可用", 0).show();    }}

文件读写权限

@Overrideprotected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    setContentView(R.layout.activity_main);    try {        /*得到一个文件的输出流,文件的位置/data/data/包名/files/haha.txt        *File file = new File(getFilesDir(),"haha.txt");        *FileOutputStream fos = new FileOutputStream(file);*/        FileOutputStream fos = openFileOutput("readable.txt", MODE_WORLD_READABLE);        fos.write("dafa".getBytes());        fos.close();        fos = openFileOutput("writeable.txt", MODE_WORLD_WRITEABLE);        fos.write("dafa".getBytes());        fos.close();        fos = openFileOutput("public.txt", MODE_WORLD_WRITEABLE+MODE_WORLD_READABLE);        fos.write("dafa".getBytes());        fos.close();        fos = openFileOutput("private.txt", MODE_PRIVATE);        fos.write("dafa".getBytes());        fos.close();    } catch (Exception e) {        e.printStackTrace();    }}

SharedPreferences的使用

//1. 声明一个共享参数(存储数据方便的api)private SharedPreferences sp;@Overrideprotected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    setContentView(R.layout.activity_main);    //2. 通过上下文得到一个共享参数的实例对象    //类似 File f = new File("config");    sp = this.getSharedPreferences("config", MODE_PRIVATE);    //寻找这些控件    et_qqnumber = (EditText) findViewById(R.id.et_qqnumber);    et_password = (EditText) findViewById(R.id.et_password);    cb_remember = (CheckBox) findViewById(R.id.cb_remember);    restoreInfo();}/** * 登陆按钮的点击事件 * @param view */public void login(View view){    String qq = et_qqnumber.getText().toString().trim();    String password = et_password.getText().toString().trim();    if(TextUtils.isEmpty(qq)||TextUtils.isEmpty(password)){        Toast.makeText(this, "用户名和密码不能为空", 0).show();        return;    }else{        //判断是否需要记录用户名和密码        if(cb_remember.isChecked()){//被选中状态,需要记录用户名和密码            //TODO:记录密码            Editor editor = sp.edit();            editor.putString("qq", qq);            editor.putString("password", password);            editor.commit();//提交数据. 类似关闭流,事务        }        //登陆操作的. 模拟登陆,数据应该提交给服务器 由服务器比较是否正确        if("10000".equals(qq)&&"123456".equals(password)){            Toast.makeText(this, "登陆成功", 0).show();        }else{            Toast.makeText(this, "登陆失败", 0).show();        }    }}/** * 根据原来保存的文件信息,把qq号码和密码信息回显到界面 */public  void restoreInfo(){    //TODO:读取密码    String qq = sp.getString("qq", "");    String password = sp.getString("password", "");    et_qqnumber.setText(qq);    et_password.setText(password);}

xml文件的序列化器XmlSerializer

//  <头>//  <info>//      <student id='800001'>//          <name>张三</name>//          <age>18</age>//      </student>//  </info>//保存学生的信息public void save(View view){    String name = et_name.getText().toString().trim();    String age = et_age.getText().toString().trim();    String id = et_id.getText().toString().trim();    if(TextUtils.isEmpty(name)||TextUtils.isEmpty(age)||TextUtils.isEmpty(id)){        Toast.makeText(this, "信息不能为空", 0).show();        return;    }else{        //打算把数据存成xml文件.跨平台.        try {            //1.创建一个xml文件的序列化器            XmlSerializer serializer = Xml.newSerializer();            //2.设置文件的输出和编码方式            File file = new File(Environment.getExternalStorageDirectory(),"info.xml");            FileOutputStream os = new FileOutputStream(file);            serializer.setOutput(os, "utf-8");            //3.写xml文件的头            serializer.startDocument("utf-8", true);            //4.写info节点            serializer.startTag(null, "info");            //5.写student节点            serializer.startTag(null, "student");            //6.写属性            serializer.attribute(null, "id", id);            //7.写name            serializer.startTag(null, "name");            serializer.text(name);            serializer.endTag(null, "name");            //8.写age            serializer.startTag(null, "age");            serializer.text(age);            serializer.endTag(null, "age");            serializer.endTag(null, "student");            serializer.endTag(null, "info");            serializer.endDocument();//写文件的末尾            os.close();            Toast.makeText(this, "保存学生信息成功", 0).show();        } catch (Exception e) {            e.printStackTrace();            Toast.makeText(this, "保存学生信息失败", 0).show();        }    }}

xml文件的解析器XmlPullParser

private void readXmlInfo(File file){    try {        //1.初始化解析器        XmlPullParser parser = Xml.newPullParser();        //2.设置解析器的参数        InputStream inputStream = new FileInputStream(file);        parser.setInput(inputStream, "utf-8");        int type = parser.getEventType();        StringBuilder sb = new StringBuilder();        while(type!=XmlPullParser.END_DOCUMENT){            switch (type) {            case XmlPullParser.START_TAG:                if("name".equals(parser.getName())){                    //这是name节点                    String name = parser.nextText();                    sb.append("--name:"+name);                }else if("num".equals(parser.getName())){                    //这是name节点                    String num = parser.nextText();                    sb.append("--num:"+num);                }else if("sex".equals(parser.getName())){                    //这是name节点                    String sex = parser.nextText();                    sb.append("--sex:"+sex);                }                break;            }            type =  parser.next();//让解析器解析下一个元素        }        inputStream.close();        String text = sb.toString();    } catch (Exception e) {        e.printStackTrace();    }}

Json数据解析

JSONObject

            json数据            __GetZoneResult_ = {                mts:'1351234',                province:'重庆',                catName:'中国移动',                telString:'13512345678',                areaVid:'29404',                ispVid:'3236139',                carrier:'重庆移动'            }            String json = StreamTools.readStream(is).replace("__GetZoneResult_ = ", "");            JSONObject jsonObject = new JSONObject(json);            final String catName = jsonObject.getString("catName");            final String province = jsonObject.getString("province");            showToastInAnyThread( "运营商:"+catName+"\n归属地:"+province);

JSONARRY

            //jsonData的数据格式:            String jsonData = "[{ "id": "27JpL~jd99w9nM01c000qc", "version": "abc" },{ "id": "27JpL~j6UGE0LX00s001AH", "version": "bbc" },{ "id": "27JpL~j7YkM0LX01c000gt", "version": "Wa_" }]";            JSONArray arr = new JSONArray(jsonData);              for (int i = 0; i < arr.length(); i++) {                 JSONObject temp = (JSONObject) arr.get(i);                  String id = temp.getString("id");                  String version = temp.getString("version");            }

SQLite数据库操作

  1. MyDBOpenHelper创建数据库

    MyDBOpenHelper.java

    /** * 数据库创建的帮助类 类似File类 * @author Administrator */public class MyDBOpenHelper extends SQLiteOpenHelper {    /**     * @param context 上下文     * @param version     */    public MyDBOpenHelper(Context context) {        //第二个参数数据库的名称        //第三个参数null代表的是默认的游标工厂        //第四个参数 是数据库的版本号  数据库只能升级,不能降级,版本号只能变大不能变小        super(context, "itheima.db", null, 2);     }    //Called when the database is created for the first time.    //当数据库第一次被创建的时候调用的方法,适合在这个方法里面把数据库的表结构定义出来.    @Override    public void onCreate(SQLiteDatabase db) {        System.out.println("oncreate 数据库被创建了. 哈哈哈哈,嘎嘎嘎------------");        //执行sql语句        db.execSQL("create table contactinfo (id integer primary key autoincrement, name varchar(20), phone varchar(20))");    }    //Called when the database needs to be upgraded.    //当数据库更新的时候调用的方法    @Override    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {        System.out.println("onUpgrade 数据库被更新了. oldVersion:"+oldVersion+"--------newVersion:"+newVersion+"----");        db.execSQL("alter table contactinfo add account varchar(20)");    }}
  2. ContactInfoDao数据库的DAO

    ContactInfoDao.java

    /*** 联系人数据库表的访问类*/public class ContactInfoDao {    /**     * 数据库打开的帮助类     */    private MyDBOpenHelper helper;    /**     * 在构造方法里面完成 必须要用的类的初始化     * @param context     */    public ContactInfoDao(Context context) {        helper = new MyDBOpenHelper(context);    }    /**     * 添加一条记录     * @param name 联系人姓名     * @param phone 联系人电话     * @return 返回的是添加后在数据库的行号  -1代表添加失败     */    public long add(String name, String phone){        SQLiteDatabase db = helper.getWritableDatabase();        //db.execSQL("insert into contactinfo (name,phone) values (?,?)", new Object[]{name,phone});        ContentValues values = new ContentValues();        values.put("name", name);        values.put("phone", phone);        //内部是组拼sql语句实现的.        long rowid = db.insert("contactinfo", null, values);        //记得释放数据库资源        db.close();        return rowid;    }    /**     * 根据姓名删除一条记录     * @param name 要删除的联系人的姓名     * @return 返回0代表的是没有删除任何的记录 返回整数int值代表删除了几条数据     */    public int delete(String name){        //判断这个数据是否存在.        SQLiteDatabase db = helper.getWritableDatabase();        //db.execSQL("delete from contactinfo where name=?", new Object[]{name});        int rowcount = db.delete("contactinfo", "name=?", new String[]{name});        db.close();        //再从数据库里面查询一遍,看name是否还在        return rowcount;    }    /**     * 修改联系人电话号码     * @param newphone 新的电话号码     * @param name 要修改的联系人姓名     * @return 0代表一行也没有更新成功, >0 整数代表的是更新了多少行记录     */    public int update(String newphone , String name){        SQLiteDatabase db = helper.getWritableDatabase();        //db.execSQL("update contactinfo set phone =? where name=?", new Object[]{newphone,name});        ContentValues values = new ContentValues();        values.put("phone", newphone);        int rowcount =  db.update("contactinfo", values, "name=?", new String[]{name});        db.close();        return rowcount;    }    /**     * 查询联系人的电话号码     * @param name 要查询的联系人     * @return 电话号码     */    public String getPhoneNumber(String name){        String phone = null;        SQLiteDatabase db = helper.getReadableDatabase();        //Cursor  cursor = db.rawQuery("select phone from contactinfo where name=?", new String[]{name});        Cursor  cursor =  db.query("contactinfo", new String[]{"phone"}, "name=?", new String[]{name}, null, null, null);        if(cursor.moveToNext()){//如果光标可以移动到下一位,代表就是查询到了数据            phone = cursor.getString(0);        }        cursor.close();//关闭掉游标,释放资源        db.close();//关闭数据库,释放资源        return phone;    }}

    数据库的事务操作

    // 数据库的事务, 保证一组sql语句 要么同时执行成功 ,要么同时执行失败public void deteleAll() {// 删除数据库全部的记录.    SQLiteDatabase db = helper.getWritableDatabase();    db.beginTransaction();// 开启事务    try {        Cursor cursor = db.query("info", new String[] { "studentid" },                null, null, null, null, null);        while (cursor.moveToNext()) {            String studentid = cursor.getString(0);            db.delete("info", "studentid=?", new String[] { studentid });            //throw new RuntimeException("--");        }        cursor.close();        db.setTransactionSuccessful();//设置事务执行成功.必须要这一行代码执行,数据才会被提交    } finally {        db.endTransaction();//根据db设置的事务标记 来去确定事务是否被提交        db.close();    }}
  3. MainActivity数据库的应用类

    MainActivity.java

    public class MainActivity extends Activity {    private EditText et_name;    private EditText et_phone;    private ContactInfoDao dao;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        et_name = (EditText) findViewById(R.id.et_name);        et_phone = (EditText) findViewById(R.id.et_phone);        dao = new ContactInfoDao(this);    }    /**     * 添加一条联系人的信息     * @param view     */    public void add(View view) {        String name = et_name.getText().toString().trim();        String phone = et_phone.getText().toString().trim();        if (TextUtils.isEmpty(name) || TextUtils.isEmpty(phone)) {            Toast.makeText(this, "不能为空", 0).show();            return;        } else {            long id = dao.add(name, phone);            if (id == -1) {                Toast.makeText(this, "添加失败", 0).show();            } else {                Toast.makeText(this, "添加成功,在数据库的第:"+id+"行", 0).show();            }        }    }    /**     * 删除一条记录     * @param view     */    public void delete(View view) {        String name = et_name.getText().toString().trim();        if (TextUtils.isEmpty(name)) {            Toast.makeText(this, "姓名不能为空", 0).show();            return;        } else {            int count = dao.delete(name);            if(count==0){                Toast.makeText(this, "删除失败,没有记录", 0).show();            }else{                Toast.makeText(this, "删除成功,删除了"+count+"条记录", 0).show();            }        }    }    /**     * 修改联系人的号码     * @param view     */    public void update(View view) {        String name = et_name.getText().toString().trim();        String phone = et_phone.getText().toString().trim();        if (TextUtils.isEmpty(name) || TextUtils.isEmpty(phone)) {            Toast.makeText(this, "不能为空", 0).show();            return;        } else {            int count = dao.update(phone, name);            if(count==0){                Toast.makeText(this, "更新失败,没有记录", 0).show();            }else{                Toast.makeText(this, "更新成功,更新了"+count+"条记录", 0).show();            }        }    }    /**     * 查询     * @param view     */    public void query(View view) {        String name = et_name.getText().toString().trim();        if (TextUtils.isEmpty(name)) {            Toast.makeText(this, "姓名不能为空", 0).show();            return;        } else {            String result = dao.getPhoneNumber(name);            Toast.makeText(this, "号码:" + result, 0).show();        }    }}

数据显示

ListView显示数据

  1. 在布局文件里面声明listview

    <ListView    android:layout_width="match_parent"    android:layout_height="match_parent"    android:id="@+id/lv" />
  2. 自定义item.xml布局
  3. 设置listview的数据适配器(controller)

    public class MainActivity extends Activity {    private EditText et_name;    private EditText et_phone;    private ListView lv;    /**     * 学生信息的dao     */    private StudentDao dao;    /**     * 所有的学生信息     */    private List<StudentInfo> infos;    /**     * 全局的数据适配器     */    private StudentAdapter adapter;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        requestWindowFeature(Window.FEATURE_NO_TITLE);        setContentView(R.layout.activity_main);        et_name = (EditText) findViewById(R.id.et_name);        et_phone = (EditText) findViewById(R.id.et_phone);        lv = (ListView) findViewById(R.id.lv);        dao = new StudentDao(this);        infos = dao.findAll();        // controll 控制器        // 设置listview的数据适配器控制器        adapter = new StudentAdapter();        lv.setAdapter(adapter);    }    /**     * 添加一个信息到数据库     * @param view     */    public void add(View view){        String name = et_name.getText().toString().trim();        String phone = et_phone.getText().toString().trim();        if(TextUtils.isEmpty(name)||TextUtils.isEmpty(phone)){            Toast.makeText(this, "数据不能为空", 0).show();            return ;        }        long result = dao.add(name, phone);        if(result>0){            Toast.makeText(this, "添加成功", 0).show();            infos = dao.findAll();            adapter.notifyDataSetChanged();//-->从新调用getcount 调用getview        }else{            Toast.makeText(this, "添加失败", 0).show();        }    }    private class StudentAdapter extends BaseAdapter{        @Override        public int getCount() {            return infos.size();        }        @Override        public View getView(final int position, View convertView, ViewGroup parent) {            System.out.println("position"+position);            //布局填充器            View view = View.inflate(MainActivity.this, R.layout.item, null);            TextView tv_id = (TextView) view.findViewById(R.id.tv_id);            TextView tv_name = (TextView) view.findViewById(R.id.tv_name);            TextView tv_phone = (TextView) view.findViewById(R.id.tv_phone);            ImageView iv_delete = (ImageView) view.findViewById(R.id.iv_delete);            iv_delete.setOnClickListener(new OnClickListener() {                @Override                public void onClick(View v) {                    AlertDialog.Builder builder = new Builder(MainActivity.this);                    builder.setTitle("提醒");                    builder.setMessage("是否确定删除?");                    builder.setPositiveButton("确定删除", new DialogInterface.OnClickListener() {                        @Override                        public void onClick(DialogInterface dialog, int which) {                            // 获取该位置组件id,并删除                            int result = dao.delete(infos.get(position).getId());                            Toast.makeText(MainActivity.this, "删除了"+result+"个记录", 0).show();                            // 重新查询                            infos = dao.findAll();                            adapter.notifyDataSetChanged();                        }                    });                    builder.setNegativeButton("取消", null);                    builder.create().show();                }            });            // 修改对应值            tv_id.setText(infos.get(position).getId());            tv_name.setText(infos.get(position).getName());            tv_phone.setText(infos.get(position).getPhone());            return view;        }        @Override        public Object getItem(int position) {            return null;        }        @Override        public long getItemId(int position) {            return 0;        }    }}

常见对话框合集

/** * 弹出确定取消对话框 * @param view */public void click01(View view) {    // 工厂设计模式. 得到创建对话框的工厂    AlertDialog.Builder builder = new Builder(this);    // 设置标题    builder.setTitle("警告,请三思:");    // 设置描述信息    builder.setMessage("若练此功,必先自宫,是否继续?");    // 设置确定和取消按钮    builder.setPositiveButton("是", new OnClickListener() {        @Override        public void onClick(DialogInterface dialog, int which) {            Toast.makeText(getApplicationContext(), "啊....,即便自宫,也不一定成功", 0).show();        }    });    builder.setNegativeButton("否", new OnClickListener() {        @Override        public void onClick(DialogInterface dialog, int which) {            Toast.makeText(getApplicationContext(), "如果不自宫,一定不成功", 0).show();        }    });    // AlertDialog dialog = builder.create();    // dialog.show();    builder.show();}/** * 单选对话框 * @param view */public void click02(View view) {    // 工厂设计模式. 得到创建对话框的工厂    AlertDialog.Builder builder = new Builder(this);    //设置标题    builder.setTitle("请选择您的性别");    //设置选项    final String[] items = {"男","女","中间"};    builder.setSingleChoiceItems(items, -1, new OnClickListener() {        @Override        public void onClick(DialogInterface dialog, int which) {            Toast.makeText(getApplicationContext(), "您的性别为:"+items[which], 0).show();            dialog.dismiss();        }    });    builder.show();}/** * 多选对话框 * @param view */public void click03(View view) {    // 工厂设计模式. 得到创建对话框的工厂    AlertDialog.Builder builder = new Builder(this);    //设置标题    builder.setTitle("请选择您爱吃的水果");    //设置选项    final String[] items = {"苹果","梨","香蕉","菠萝","煎饼果子"};    final boolean[] checked={true,false,true,false,true};    builder.setMultiChoiceItems(items, checked,  new OnMultiChoiceClickListener() {        @Override        public void onClick(DialogInterface dialog, int which, boolean isChecked) {            Toast.makeText(getApplicationContext(), items[which]+isChecked, 0).show();            checked[which] = isChecked;        }    });    builder.setPositiveButton("提交", new OnClickListener() {        @Override        public void onClick(DialogInterface dialog, int which) {            StringBuffer sb = new StringBuffer();            for(int i=0;i<checked.length;i++){                if(checked[i]){                    sb.append(items[i]+" ");                }            }            Toast.makeText(getApplicationContext(), "您喜欢的水果有:"+sb.toString(), 0).show();        }    });    builder.show();}/** * 进度对话框 * @param view */public void click04(View view){    final ProgressDialog pd = new ProgressDialog(this);    pd.setTitle("请稍后:");    pd.setMessage("正在拼命加载中....");    pd.show();    new Thread(){        public void run() {            try {                Thread.sleep(30000);            } catch (InterruptedException e) {                e.printStackTrace();            }            pd.dismiss();        };    }.start();}/** * 带具体进度的对话框 * @param view */public void click05(View view){    final ProgressDialog pd = new ProgressDialog(this);    pd.setTitle("请稍后:");    //设置进度样式    pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);    pd.setMessage("正在拼命加载中....");    //设置进度条的最大值    pd.setMax(100);    pd.show();    new Thread(){        public void run() {            try {                for(int i=0;i<=100;i++){                    Thread.sleep(300);                    pd.setProgress(i);                }            } catch (InterruptedException e) {                e.printStackTrace();            }            pd.dismiss();        };    }.start();}

网络编程

流的工具方法

    /**     * 流的一个工具类     * @author Administrator     *     */    public class StreamUtils {        /**         * 读取流的数据返回一个字符串         * @param is 获取的流         * @return 字符串 解析失败返回null;         */        public static String readStread(InputStream is){            try {                ByteArrayOutputStream baos = new ByteArrayOutputStream();                byte[] buffer = new byte[1024];                int len = 0;                while(( len = is.read(buffer))!=-1){                    baos.write(buffer, 0, len);                }                is.close();                String result = baos.toString();                //智能识别网页编码                if(result.contains("gb2312")){                    return baos.toString("gb2312");                }else{                    return result;                }            } catch (Exception e) {                e.printStackTrace();                return null;            }        }

子线程更新UI的步骤

runOnUiThread(new Runnable() {});

  1. 创建一个消息处理器Handler(一定要在主线程new出来)

    private Handler handler = new Handler() {};
  2. 在子线程利用handler发送消息给主线程的消息队列

    handler.sendMessage(msg);
  3. 在主线程的消息处理器里面,处理这个消息

    public void handleMessage(Message msg) {}
  4. 特殊情况 传递数据

    Message.obj 携带数据

Handler使用示例代码:

public class MainActivity extends Activity {    private TextView tv;    /**     * 1.创建一个消息处理器,类似工厂里面的老板,运行在主线程里面.     */    private Handler handler = new Handler() {        // 3.loop调用的用来处理消息的方法,运行在主线程        public void handleMessage(Message msg) {            //区分消息类型            switch(msg.what){                case ?:                    break;            }            int i = (Integer) msg.obj;            tv.setText("当前进度:"+i+"%");        };    };    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        tv = (TextView) findViewById(R.id.tv);    }    public void click(View view) {        new Thread() {            public void run() {                // tv.setText("hahahah"); 子线程不可以直接更新ui                // 2.通过消息处理器 把一个消息发送到 消息队列                for (int i = 0; i < 100; i++) {                    Message msg = new Message();                    //Message msg = Message.obtain(); 消息池                    //消息携带的数据                    msg.obj = i;                    //msg.what = ? 消息类型                    handler.sendMessage(msg);                    try {                        Thread.sleep(1000);                    } catch (InterruptedException e) {                        e.printStackTrace();                    }                }            };        }.start();    }}

简单的子线程更新UI的步骤(在Activity中)

/** * 显示土司 * @param text */public void showToastInAnyThread(final String text){    runOnUiThread(new Runnable() {        @Override        public void run() {//运行在主线程,内部做了处理            Toast.makeText(MainActivity.this, text, 0).show();        }    });}

HTTP请求

1.URL面向过程的请求方式

GET请求

    // 采用http的get请求,提交数据到服务器        new Thread() {            public void run() {                try {                    Thread.sleep(5000);                    //统一码表                    String path = "http://192.168.1.109:8080/web/LoginServlet?username="                            + URLEncoder.encode(qq) + "&password=" + URLEncoder.encode(password);                     // 1.得到服务器资源的路径                    URL url = new URL(path);                    // 2.通过这个路径打开浏览器的连接.                    HttpURLConnection conn = (HttpURLConnection) url.openConnection();// ftp || http || https || rtsp                    // 3.设置请求方式为get请求                    conn.setRequestMethod("GET");// 注意get只能用大写 不支持小写                    conn.setConnectTimeout(5000);                    conn.setReadTimeout(10000);                    // 为了有一个更好的用户ui提醒,获取服务器的返回状态码                    int code = conn.getResponseCode();// 200 ok 404资源没有找到 503                    if(code == 200){                        // 4.获取服务器的返回的流                        InputStream is = conn.getInputStream();                        String result = StreamUtils.readStread(is);                        Message msg = Message.obtain();                        msg.what = GET_SERVER_RESOPONSE;                        msg.obj = result;                        handler.sendMessage(msg);                    }else {                        Message msg = Message.obtain();                        msg.what = ERROR;                        handler.sendMessage(msg);                    }                } catch (Exception e) {                    e.printStackTrace();                    Message msg = Message.obtain();                    msg.what = ERROR;                    handler.sendMessage(msg);                }            };        }.start();

POST请求

    // POST请求数据应该提交给服务器 由服务器比较是否正确        new Thread() {            public void run() {                try {                    // 1.指定提交数据的路径,post的方式不需要组拼任何的参数                    String path = "http://192.168.1.109:8080/web/LoginServlet";                    URL url = new URL(path);                    HttpURLConnection conn = (HttpURLConnection) url.openConnection();                    //2.指定请求方式为post                    conn.setRequestMethod("POST");                    //3.设置http协议的请求头                    conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");//设置发送的数据为表单类型                    //username=abc&password=123                    //统一码表                    String data = "username="+URLEncoder.encode(qq, "utf-8")+"&password="+URLEncoder.encode(password);                    conn.setRequestProperty("Content-Length", String.valueOf(data.length()));//告诉服务器发送的数据的长度                    //post的请求是把数据以流的方式写给了服务器                    //指定请求的输出模式                    conn.setDoOutput(true);//运行当前的应用程序给服务器写数据                    conn.getOutputStream().write(data.getBytes());                    int code = conn.getResponseCode();                    if(code == 200){                        InputStream is = conn.getInputStream();                        final String result = StreamTools.readStream(is);                        showToastInAnyThread(result);                    }else{                        showToastInAnyThread("请求失败");                    }                } catch (Exception e) {                    e.printStackTrace();                    showToastInAnyThread("请求失败");                }            };        }.start();

2.HttpClient面向对象的请求方式

GET请求

        // 提交数据到服务器,采用http的get请求        new Thread() {            public void run() {                try {                    Thread.sleep(2000);                    String path = "http://192.168.1.109:8080/web/LoginServlet?username="                            + URLEncoder.encode(qq) + "&password=" + URLEncoder.encode(password);                    //1.打开浏览器                    HttpClient client = new DefaultHttpClient();                    //2.输入数据                    HttpGet httpGet = new HttpGet(path);                    //3.敲回车                    HttpResponse  httpResponse = client.execute(httpGet);                    int code = httpResponse.getStatusLine().getStatusCode();                    if(code == 200){                        InputStream is = httpResponse.getEntity().getContent();                        String result = StreamUtils.readStread(is);                        Message msg = Message.obtain();                        msg.what = GET_SERVER_RESOPONSE;                        msg.obj = result;                        handler.sendMessage(msg);                    }else {                        Message msg = Message.obtain();                        msg.what = ERROR;                        handler.sendMessage(msg);                    }                } catch (Exception e) {                    e.printStackTrace();                    Message msg = Message.obtain();                    msg.what = ERROR;                    handler.sendMessage(msg);                }            };        }.start();

POST请求

        // 数据应该提交给服务器 由服务器比较是否正确        new Thread() {            public void run() {                try {                    String path = "http://192.168.1.109:8080/web/LoginServlet";                    //1.打开浏览器                    HttpClient client = new DefaultHttpClient();                    //2.设置数据                    HttpPost httpPost = new HttpPost(path);                    //ctrl+shift+o                    List<NameValuePair> parameters = new ArrayList<NameValuePair>();                    // SimpleXXX DefaultXXX BaseXXX BasicXXX                    parameters.add(new BasicNameValuePair("username", qq));                    parameters.add(new BasicNameValuePair("password", password));                    httpPost.setEntity(new UrlEncodedFormEntity(parameters,"utf-8"));                    //3.发送请求                    HttpResponse response = client.execute(httpPost);                    int code = response.getStatusLine().getStatusCode();                    if(code == 200){                        InputStream is = response.getEntity().getContent();                        final String result = StreamTools.readStream(is);                        showToastInAnyThread(result);                    }else{                        showToastInAnyThread("请求失败");                    }                } catch (Exception e) {                    e.printStackTrace();                    showToastInAnyThread("请求失败");                }            };        }.start();

3.开源框架的Http请求

开源框架 android-async-http-master

POST请求

        // 1.打开浏览器. 支持异步的浏览器 自动在后台开启线程 发送网络请求        AsyncHttpClient client = new AsyncHttpClient();        String url = "http://192.168.1.109:8080/web/LoginServlet";        //2.设置请求参数        RequestParams params = new RequestParams();        params.put("username", qq);        params.put("password", password);        //3.发送请求        client.post(url, params, new AsyncHttpResponseHandler() {            @Override            public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) {                Toast.makeText(getApplicationContext(), new String(responseBody), 0).show();            }            @Override            public void onFailure(int statusCode, Header[] headers,                    byte[] responseBody, Throwable error) {                Toast.makeText(getApplicationContext(), "请求失败", 0).show();            }        });

菜单

/** * 创建菜单 */@Overridepublic boolean onCreateOptionsMenu(Menu menu) {    getMenuInflater().inflate(R.menu.activity_main, menu);    return true;}/** * 当选项的菜单被点击的时候调用的方法 */@Overridepublic boolean onOptionsItemSelected(MenuItem item) {    switch (item.getItemId()) {    case R.id.item_deteleall:        dao.deteleAll();        Toast.makeText(this, "删除全部成功", 0).show();        lv.setAdapter(new MyAdapter());        break;    case R.id.item_save:        Toast.makeText(this, "上传到云服务器", 0).show();        //data/data/包名/databases/student.db        uploadDBToServer();        break;    case R.id.item_aaa:        Toast.makeText(this, "aaa", 0).show();        break;    case R.id.item_bbb:        Toast.makeText(this, "bbb", 0).show();        break;    }    return super.onOptionsItemSelected(item);}

文件上传开源框架

开源框架 android-async-http-master

/** * 上传数据到服务器 */private void uploadDBToServer() {    try {        AsyncHttpClient client = new AsyncHttpClient();        String url = "http://192.168.1.109:8080/web/UploadServlet";        RequestParams params = new RequestParams();        params.put("file", new File("/data/data/"+getPackageName()+"/databases/student.db")); // Upload a File        client.post(url, params, new AsyncHttpResponseHandler() {            @Override            public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) {                Toast.makeText(getApplicationContext(), "上传成功", 0).show();            }            @Override            public void onFailure(int statusCode, Header[] headers,                    byte[] responseBody, Throwable error) {                Toast.makeText(getApplicationContext(), "上传失败", 0).show();            }            @Override            public void onProgress(int bytesWritten, int totalSize) {                System.out.println(bytesWritten+"/"+totalSize);                super.onProgress(bytesWritten, totalSize);            }        });    } catch (Exception e) {        // TODO Auto-generated catch block        e.printStackTrace();    }

自定义控件SmartImageView网络图片加载器

开源框架 android-smart-image-view-master

  1. 自定义SmartImageView类继承ImageView

    SmartImageView.java

    public class SmartImageView extends ImageView {    protected static final int SUCCESS = 1;    protected static final int ERROR = 2;    private Handler handler = new Handler(){        public void handleMessage(android.os.Message msg) {            switch (msg.what) {            case SUCCESS:                Bitmap bitmap = (Bitmap) msg.obj;                setImageBitmap(bitmap);                break;            case ERROR:                int resId = (Integer) msg.obj;                setImageResource(resId);                break;            }        };    };    public SmartImageView(Context context, AttributeSet attrs, int defStyle) {        super(context, attrs, defStyle);    }    public SmartImageView(Context context, AttributeSet attrs) {        super(context, attrs);    }    public SmartImageView(Context context) {        super(context);    }    /**     * 设置一个网络图片      * @param path 图片的网址     */    public void setImageUrl(final String path){        //加载网络图片        new Thread(){            public void run() {                try {                    URL url = new URL(path);                    Thread.sleep(5000);                    HttpURLConnection conn = (HttpURLConnection) url.openConnection();                    conn.setRequestMethod("GET");                    InputStream is = conn.getInputStream();                    Bitmap bitmap = BitmapFactory.decodeStream(is);                    Message msg = Message.obtain();                    msg.obj = bitmap;                    handler.sendMessage(msg);                } catch (Exception e) {                    e.printStackTrace();                }            };        }.start();    }    /**     * 设置一个网络图片      * @param path 图片的网址     * @param errorimage 如果加载失败显示什么图片,在r文件中的id     */    public void setImageUrl(final String path,final int errorimage){        //加载网络图片        new Thread(){            public void run() {                try {                    URL url = new URL(path);                    Thread.sleep(5000);                    HttpURLConnection conn = (HttpURLConnection) url.openConnection();                    conn.setRequestMethod("GET");                    if(conn.getResponseCode()==200){                        InputStream is = conn.getInputStream();                        Bitmap bitmap = BitmapFactory.decodeStream(is);                        Message msg = Message.obtain();                        msg.obj = bitmap;                        msg.what = SUCCESS;                        handler.sendMessage(msg);                    }else{                        Message msg = Message.obtain();                        msg.what = ERROR;                        msg.obj = errorimage;                        handler.sendMessage(msg);                    }                } catch (Exception e) {                    Message msg = Message.obtain();                    msg.what = ERROR;                    msg.obj = errorimage;                    handler.sendMessage(msg);                    e.printStackTrace();                }            };        }.start();    }    /**     * 设置一个网络图片      * @param path 图片的网址     * @param loadingimg 加载中的图片     * @param errorimage 如果加载失败显示什么图片,在r文件中的id     */    public void setImageUrl(final String path,final int loadingimg, final int errorimage){        setImageResource(loadingimg);        //加载网络图片        new Thread(){            public void run() {                try {                    URL url = new URL(path);                    Thread.sleep(5000);                    HttpURLConnection conn = (HttpURLConnection) url.openConnection();                    conn.setRequestMethod("GET");                    if(conn.getResponseCode()==200){                        InputStream is = conn.getInputStream();                        Bitmap bitmap = BitmapFactory.decodeStream(is);                        Message msg = Message.obtain();                        msg.obj = bitmap;                        msg.what = SUCCESS;                        handler.sendMessage(msg);                    }else{                        Message msg = Message.obtain();                        msg.what = ERROR;                        msg.obj = errorimage;                        handler.sendMessage(msg);                    }                } catch (Exception e) {                    Message msg = Message.obtain();                    msg.what = ERROR;                    msg.obj = errorimage;                    handler.sendMessage(msg);                    e.printStackTrace();                }            };        }.start();    }}
  2. 编写布局,使用自定义控件

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    tools:context=".MainActivity" >    <com.itheima.myimageview.SmartImageView        android:id="@+id/siv"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_centerHorizontal="true"        android:layout_centerVertical="true"       /></RelativeLayout>
  3. 在MainActivity中找到自定义控件,调用SmartImageView中的方法

    public class MainActivity extends Activity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        SmartImageView siv = (SmartImageView) findViewById(R.id.siv);        siv.setImageUrl("http://192.168.1.109:8080/img/a.jpg", R.drawable.loading, R.drawable.error);    }}

综合案例-新闻客户端

示例代码

  1. 编辑布局

    activity_main.xml

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity" >    <ListView        android:id="@+id/lv_news"        android:layout_width="match_parent"        android:layout_height="match_parent" />    <LinearLayout        android:visibility="invisible"        android:id="@+id/ll_loading"        android:layout_width="match_parent"        android:layout_height="match_parent"        android:gravity="center"        android:orientation="vertical" >        <ProgressBar            android:layout_width="wrap_content"            android:layout_height="wrap_content" />        <TextView            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:text="正在拼命加载中..." />    </LinearLayout>

  2. 获取数据,展示数据

    MainActivity.java

        public class MainActivity extends Activity {        protected static final int LOAD_ERROR = 2;        protected static final int SHOW_NEWS = 1;        private ListView lv_news;        private LinearLayout ll_loading;        //如何内部的代码都可以访问        private List<NewsItem> newsItems;        private Handler handler = new Handler() {            public void handleMessage(android.os.Message msg) {                //把正在加载的界面隐藏起来                ll_loading.setVisibility(View.INVISIBLE);                switch (msg.what) {                case LOAD_ERROR:                    Toast.makeText(getApplicationContext(), "获取数据失败", 0).show();                    break;                case SHOW_NEWS:                    Toast.makeText(getApplicationContext(), "加载数据成功,显示listview", 0).show();                    lv_news.setAdapter(new MyNewsAdapter());                    break;                }            };        };        @Override        protected void onCreate(Bundle savedInstanceState) {            super.onCreate(savedInstanceState);            setContentView(R.layout.activity_main);            ll_loading = (LinearLayout) findViewById(R.id.ll_loading);            lv_news = (ListView) findViewById(R.id.lv_news);            // 设置新闻的数据.            // 连接服务器 获取服务器上的最新的新闻信息            loadNewsInfo();        }        /**         * 获取新闻信息         */        private void loadNewsInfo() {            //把正在加载界面给显示出来            ll_loading.setVisibility(View.VISIBLE);            // 联网,子线程            new Thread() {                public void run() {                    try {                        Thread.sleep(5000);                        URL url = new URL("http://192.168.1.109:8080/news.xml");                        HttpURLConnection conn = (HttpURLConnection) url                                .openConnection();                        conn.setRequestMethod("GET");                        // 设置连接超时时间                        conn.setConnectTimeout(5000);                        // 设置一个读取超时时间                        conn.setReadTimeout(20000);                        int code = conn.getResponseCode();                        if (code == 200) {                            // 请求成功                            InputStream is = conn.getInputStream();// 代表的是服务器返回的流                                                                    // 里面是xml数据                            newsItems = NewsInfoParser.getAllNewsInfos(is);                            // 更新界面,把新闻显示到ui上.                            Message msg = Message.obtain();                            msg.what = SHOW_NEWS;                            handler.sendMessage(msg);                        } else {                            // 请求失败                            Message msg = Message.obtain();                            msg.what = LOAD_ERROR;                            handler.sendMessage(msg);                        }                    } catch (Exception e) {                        e.printStackTrace();                        // 请求失败                        Message msg = Message.obtain();                        msg.what = LOAD_ERROR;                        handler.sendMessage(msg);                    }                };            }.start();        }        private class MyNewsAdapter extends BaseAdapter{            @Override            public int getCount() {                return newsItems.size();            }            @Override            public View getView(int position, View convertView, ViewGroup parent) {                //LayoutInflater 布局打气筒, 把xml资源文件转成view                View view = View.inflate(getApplicationContext(), R.layout.news_item, null);                SmartImageView iv = (SmartImageView) view.findViewById(R.id.iv_img);                TextView tv_title = (TextView) view.findViewById(R.id.tv_title);                TextView tv_desc = (TextView) view.findViewById(R.id.tv_desc);                TextView tv_type = (TextView) view.findViewById(R.id.tv_type);                NewsItem newsItem = newsItems.get(position);                iv.setImageUrl(newsItem.getImagePath());                tv_title.setText(newsItem.getTitle());                tv_desc.setText(newsItem.getDesc());                String type = newsItem.getType();// 1.新闻 2专题 3直播                if("1".equals(type)){                    tv_type.setText("评论:"+newsItem.getCommentCount());                    tv_type.setBackgroundColor(Color.TRANSPARENT);                    tv_type.setTextColor(Color.BLACK);                }else if("2".equals(type)){                    tv_type.setText("专题");                    tv_type.setBackgroundColor(Color.RED);                    tv_type.setTextColor(Color.WHITE);                }else if("3".equals(type)){                    tv_type.setText("直播");                    tv_type.setBackgroundColor(Color.BLUE);                    tv_type.setTextColor(Color.WHITE);                }                return view;            }            @Override            public Object getItem(int position) {                return null;            }            @Override            public long getItemId(int position) {                return 0;            }        }    }
  3. 业务bean

    NewsItem.java

    /** * 新闻信息 */public class NewsItem {    //新闻标题    private String title;    //新闻描述    private String desc;    //图片路径    private String imagePath;    //新闻类型    private String type;    //新闻的评论个数    private int commentCount;    public String getTitle() {        return title;    }    public void setTitle(String title) {        this.title = title;    }    public String getDesc() {        return desc;    }    public void setDesc(String desc) {        this.desc = desc;    }    public String getImagePath() {        return imagePath;    }    public void setImagePath(String imagePath) {        this.imagePath = imagePath;    }    public String getType() {        return type;    }    public void setType(String type) {        this.type = type;    }    public int getCommentCount() {        return commentCount;    }    public void setCommentCount(int commentCount) {        this.commentCount = commentCount;    }}
  4. 业务类,解析XML NewsInfoParser

    XML数据格式

    news.xml

        <?xml version="1.0" encoding="UTF-8" ?>     <channel>        <item>          <title>国家</title>           <description>国家</description>          <image>http://192.168.1.109:8080/img/a.jpg</image>          <type>1</type>          <comment>163</comment>         </item>          <item>          <title>国家2</title>           <description>国家2</description>          <image>http://192.168.1.109:8080/img/b.jpg</image>          <type>2</type>         </item>         <item>          <title>国家3</title>           <description>国家3</description>          <image>http://192.168.1.109:8080/img/c.jpg</image>          <type>3</type>         </item>         <item>          <title>国家4</title>           <description>国家3</description>          <image>http://192.168.1.109:8080/img/d.jpg</image>          <type>1</type>          <comment>763</comment>         </item>    </channel>

    NewsInfoParser

        /**     * 业务类, 用来解析新闻的信息     * @author Administrator     */    public class NewsInfoParser {    /**     * 解析xml文件的流 获取全部的新闻信息     * @param is 从服务器获取的xml文件的输入流     * @return     */    public static List<NewsItem> getAllNewsInfos(InputStream is) throws Exception {        List<NewsItem> newsItems = null;// 新闻对象的集合        NewsItem newsItem = null;// 某一个新闻对象        // 1.获取xml文件的解析器        XmlPullParser parser = Xml.newPullParser();        // 2.初始化xml文件的解析器        parser.setInput(is, "utf-8");        // 3.解析xml文件        int type = parser.getEventType();        while (type != XmlPullParser.END_DOCUMENT) {            switch (type) {            case XmlPullParser.START_TAG:                if ("channel".equals(parser.getName())) {                    // 说明解析到了 最根部的标签节点                    newsItems = new ArrayList<NewsItem>();                } else if ("item".equals(parser.getName())) {                    newsItem = new NewsItem();                } else if ("title".equals(parser.getName())) {                    newsItem.setTitle(parser.nextText());                } else if ("description".equals(parser.getName())) {                    newsItem.setDesc(parser.nextText());                } else if ("image".equals(parser.getName())) {                    newsItem.setImagePath(parser.nextText());                } else if ("type".equals(parser.getName())) {                    newsItem.setType(parser.nextText());                } else if ("comment".equals(parser.getName())) {                    String countstr = parser.nextText();                    if (TextUtils.isDigitsOnly(countstr)) {                        newsItem.setCommentCount(Integer.parseInt(countstr));                    }                }                break;            case XmlPullParser.END_TAG:                //判断如果是走到了一个item的结束标签.说明一个item的数据已经准备好了.添加到集合                if("item".equals(parser.getName())){                    newsItems.add(newsItem);//把当前的新闻对象加入到集合里面                }                break;            }            type = parser.next();        }        return newsItems;    }}
  5. 条目布局 news_item

    news_item.xml

    <?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="wrap_content" >    <com.itheima.newsclient.SmartImageView        android:id="@+id/iv_img"        android:layout_width="72dip"        android:layout_height="53dip"        android:layout_marginLeft="3dip"        android:layout_centerVertical="true"        android:src="@drawable/b" />    <TextView        android:id="@+id/tv_title"        android:singleLine="true"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_marginLeft="3dip"        android:layout_marginTop="5dip"        android:layout_toRightOf="@id/iv_img"        android:text="我是新闻的标题"        android:textColor="#000000"        android:textSize="18sp" />    <TextView        android:id="@+id/tv_desc"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_below="@id/tv_title"        android:layout_marginLeft="3dip"        android:layout_marginTop="2dip"        android:layout_toRightOf="@id/iv_img"        android:lines="2"        android:text="我是新闻的描述,不拉不拉不不拉不拉不不拉不拉不不拉不拉不不拉不拉不不拉不拉不不拉不拉不不拉不拉不不拉不拉不不拉不拉不"        android:textColor="#99000000"        android:textSize="12sp" />      <TextView        android:id="@+id/tv_type"        android:text="专题"        android:background="#ff0000"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_below="@id/tv_desc"        android:layout_alignParentRight="true"        android:textColor="#99000000"        android:textSize="10sp" />    </RelativeLayout>

断点下载

        public class MainActivity extends Activity {            private EditText et_path;            private EditText et_thread_count;            private String path;            // 总的线程的个数            private int totalThreadCount;            /**             * 正在运行的线程的数量             */            private int runningThreadCount;            private LinearLayout ll_container;            private List<ProgressBar> pbs;            @Override            protected void onCreate(Bundle savedInstanceState) {                super.onCreate(savedInstanceState);                setContentView(R.layout.activity_main);                et_path = (EditText) findViewById(R.id.et_path);                et_thread_count = (EditText) findViewById(R.id.et_threadcount);                ll_container = (LinearLayout) findViewById(R.id.ll_container);            }            public void download(View view) {                path = et_path.getText().toString().trim();                String str_count = et_thread_count.getText().toString().trim();                totalThreadCount = Integer.parseInt(str_count);                ll_container.removeAllViews();//删除旧的                pbs = new ArrayList<ProgressBar>();                for(int i= 0;i<totalThreadCount;i++){                    //有几个线程 就创建几个进度条                    ProgressBar pb = (ProgressBar) View.inflate(this, R.layout.pb, null);                    ll_container.addView(pb);                    pbs.add(pb);                }                new Thread() {                    public void run() {                        try {                            // 推荐大家使用exe文件作为下载测试的文件                            URL url = new URL(path);                            HttpURLConnection conn = (HttpURLConnection) url                                    .openConnection();                            conn.setRequestMethod("GET");                            int code = conn.getResponseCode();                            if (code == 200) {                                int length = conn.getContentLength();                                System.out.println("服务器文件的长度为:" + length);                                RandomAccessFile raf = new RandomAccessFile(                                        Environment.getExternalStorageDirectory().getAbsolutePath()+"/"+getDownLoadFileName(path), "rw");                                // 在本地创建一个空文件大小和服务器的文件大小保持一致                                raf.setLength(length);                                raf.close();                                int blocksize = length / totalThreadCount;// 把服务器的资源等分成3份                                                                            // 每一份的大小                                System.out.println("每一份:" + blocksize);                                runningThreadCount = totalThreadCount;                                for (int threadid = 0; threadid < totalThreadCount; threadid++) {                                    int startPosition = threadid * blocksize;                                    int endPosition = (threadid + 1) * blocksize - 1;                                    if (threadid == (totalThreadCount - 1)) {                                        endPosition = length - 1;                                    }                                    System.out.println("线程理论:" + threadid + "下载的范围:"                                            + startPosition + "~~" + endPosition);                                    // 开启子线程,让每个子线程下载对应位置的数据..                                    new DownloadThread(threadid, startPosition, endPosition)                                            .start();                                }                            }                        } catch (Exception e) {                            e.printStackTrace();                        }                    };                }.start();            }            public class DownloadThread extends Thread {                /**                 * 线程id                 */                private int threadid;                /**                 * 当前线程下载的开始位置                 */                private int startPosition;                /**                 * 当前线程下载的结束位置                 */                private int endPosition;                /**                 * 当前线程下载的进度的总大小                 */                private int threadTotal;                /**                 * 上一次下载的总大小                 */                private int lastdownloadTotalSize;                public DownloadThread(int threadid, int startPosition, int endPosition) {                    this.threadid = threadid;                    this.startPosition = startPosition;                    this.endPosition = endPosition;                    threadTotal = endPosition - startPosition;                    pbs.get(threadid).setMax(threadTotal);//设置当前线程的进度条的总大小                }                @Override                public void run() {                    System.out.println("线程:" + threadid + "开始工作了");                    // 让当前线程下载自己对应范围的数据                    try {                        // 判断是否已经下载过一部分的数据.                        File finfo = new File(Environment.getExternalStorageDirectory().getAbsolutePath()+"/"+totalThreadCount                                + getDownLoadFileName(path) + threadid + ".txt");                        if (finfo.exists() && finfo.length() > 0) {                            FileInputStream fis = new FileInputStream(finfo);                            BufferedReader br = new BufferedReader(                                    new InputStreamReader(fis));                            String lastposition = br.readLine();                            // 这个线程上一次下载的大小                            int intlastposition = Integer.parseInt(lastposition);                            lastdownloadTotalSize = intlastposition - startPosition;                            startPosition = intlastposition;                            fis.close();                        }                        URL url = new URL(path);                        HttpURLConnection conn = (HttpURLConnection) url                                .openConnection();                        conn.setRequestMethod("GET");                        System.out.println("线程真实下载开始和结束:" + threadid + "下载的范围:"                                + startPosition + "~~" + endPosition);                        conn.setRequestProperty("Range", "bytes=" + startPosition + "-"                                + endPosition);                        // 从服务器下载资源.                        int code = conn.getResponseCode(); // 206 请求部分数据成功                        if (code == 206) {                            InputStream is = conn.getInputStream();                            RandomAccessFile raf = new RandomAccessFile(Environment.getExternalStorageDirectory().getAbsolutePath()+"/"+                                    getDownLoadFileName(path), "rw");                            // ★ 非常重要指定文件写的开始位置                            raf.seek(startPosition);                            byte[] buffer = new byte[1024];                            int len = -1;                            int total = 0;// 当前线程这一次下载了多少的数据                            while ((len = is.read(buffer)) != -1) {                                raf.write(buffer, 0, len);                                // 把当前下载的位置记录下来.                                total += len;                                RandomAccessFile inforaf = new RandomAccessFile(Environment.getExternalStorageDirectory().getAbsolutePath()+"/"+                                        totalThreadCount + getDownLoadFileName(path)                                                + threadid + ".txt", "rwd");// 每一次更新                                                                            // 数据都被同步到底层硬盘                                // 存当前线程已经下载到了哪个位置                                inforaf.write(String.valueOf(startPosition + total)                                        .getBytes());                                inforaf.close();                                pbs.get(threadid).setProgress(total+lastdownloadTotalSize);                            }                            is.close();                            raf.close();                            System.out.println("线程:" + threadid + "下载完毕了...");                        }                    } catch (Exception e) {                        e.printStackTrace();                    } finally {                        synchronized (MainActivity.this) {                            runningThreadCount--;                            if (runningThreadCount <= 0) {                                System.out.println("多线程下载完毕.");                                for (int i = 0; i < totalThreadCount; i++) {                                    File f = new File(Environment.getExternalStorageDirectory().getAbsolutePath()+"/"+totalThreadCount                                            + getDownLoadFileName(path) + i + ".txt");                                    System.out.println(f.delete());                                }                            }                        }                    }                }            }            /**             * 根据路径获取文件名             *              * @param path             * @return             */            public String getDownLoadFileName(String path) {                return path.substring(path.lastIndexOf("/") + 1);            }        }

断点下载开源框架 afinal-master

afinal_0.5.1_bin

            public void download(View view) {                path = et_path.getText().toString().trim();                if (TextUtils.isEmpty(path) && !path.startsWith("http://")) {                    Toast.makeText(this, "下载路径不合法", 0).show();                    return;                }                FinalHttp fh = new FinalHttp();                  fh.download(path, "/mnt/sdcard/haha.exe", true, new AjaxCallBack<File>() {                    @Override                    public void onLoading(long count, long current) {                        pb.setMax((int) count);                        pb.setProgress((int) current);                        super.onLoading(count, current);                    }                    @Override                    public void onSuccess(File t) {                        Toast.makeText(MainActivity.this, "下载成功", 0).show();                        super.onSuccess(t);                    }                    @Override                    public void onFailure(Throwable t, int errorNo, String strMsg) {                        System.out.println(strMsg);                        super.onFailure(t, errorNo, strMsg);                    }                });            }

Activity

意图Intent

AndroidManifest.xml

    <activity        android:name="com.itheima.intent.SecondActivity"        android:label="@string/title_activity_second" >        <intent-filter >            <action android:name="com.itheima.intent.open02"/>            //1. 设置数据的类型            <data android:mimeType="text/plain"></data>            //2. 设置数据的格式            <data android:scheme="http"                  android:host="www.itheima.com"                  android:port="8080"                  android:path="/java"                ></data>            <category android:name="android.intent.category.DEFAULT"/>        </intent-filter>    </activity></application>

显式意图

方式一:

        /**         * 显式意图点击按钮开启第二个界面         * 激活自己应用程序的里面的界面         * @param view         */        public void click01(View view) {            Intent intent = new Intent(this,SecondActivity.class);            startActivity(intent);        }

方式二:

        Intent intent = new Intent();        intent.setClassName("com.itheima.intent",            "com.itheima.intent.SecondActivity");//类名必须是全路径        startActivity(intent);

隐式意图

        /**         * 隐式意图点击按钮开启第二个界面         * 开启更加灵活,精准,并且可以携带匹配的数据         * @param view         */        public void click02(View view) {            Intent intent = new Intent();            intent.setAction("com.itheima.intent.open02");            //1. 设置数据的类型            intent.setType("text/plain");            //2. 设置数据的格式            intent.setData(Uri.parse("http://www.itheima.com:8080/java"));            intent.addCategory("android.intent.category.DEFAULT");            startActivity(intent);        }

页面间的数据传递

设置intent的数据

MainActivity.java

    //声明一个意图对象    Intent intent = new Intent();    //Serializable  序列化到硬盘 自己实现的序列化的类    //Parcelable 序列化到内存 bitmap    intent.putExtra("name", name);//传递是 字符串    intent.putExtra("key",value);//传递是int类型的数据    //使用Bundle传递一个map集合    Bundle extras = new Bundle();    extras.putChar(key, value)    intent.putExtras(extras);

获取数据

SecondActivity.java

    Intent intent = getIntent();//获取激活当前页面的意图对象    intent.getStringExtra();    intent.getIntExtra();    intent.getDoubleExtra();    ...    intent.getExtras();

隐式意图的应用

浏览器示例代码:

activity_main.xml

    <WebView    android:layout_below="@id/et_path"    android:id="@+id/wv"    android:layout_width="fill_parent"    android:layout_height="fill_parent" />

MainActivity.java

    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        requestWindowFeature(Window.FEATURE_NO_TITLE);        setContentView(R.layout.activity_main);        et_path = (EditText) findViewById(R.id.et_path);        iv_go = (ImageView) findViewById(R.id.iv_go);        wv = (WebView) findViewById(R.id.wv);        Intent intent = getIntent();        if (intent != null) {            if (intent.getData() != null) {                //获取其他应用传递的数据                //intent.setData(Uri.parse("http://xxxx.com"));                String path = intent.getData().toString();                wv.loadUrl(path);                et_path.setText(path);            }        }        iv_go.setOnClickListener(new OnClickListener() {            @Override            public void onClick(View v) {                String path = et_path.getText().toString().trim();                wv.loadUrl(path);            }        });    }

AndroidManifest.xml

        <activity            android:name="com.itheima.superbrowser.MainActivity"            android:label="@string/app_name" >            <intent-filter>                <action android:name="android.intent.action.MAIN" />                <category android:name="android.intent.category.LAUNCHER" />            </intent-filter>            <!-- 分拣系统,匹配当前的Activity可以用来打开网页 -->            <intent-filter>                <action android:name="android.intent.action.VIEW" />                <category android:name="android.intent.category.DEFAULT" />                <category android:name="android.intent.category.BROWSABLE" />                <data android:scheme="http" />                <data android:scheme="https" />                <data android:scheme="about" />                <data android:scheme="javascript" />            </intent-filter>        </activity>

请求码和结果码

AndroidManifest.xml

        <application            android:allowBackup="true"            android:icon="@drawable/ic_launcher"            android:label="@string/app_name"            android:theme="@style/AppTheme" >            <activity                android:name="com.itheima.request_result_code.MainActivity"                android:label="@string/app_name" >                <intent-filter>                    <action android:name="android.intent.action.MAIN" />                    <category android:name="android.intent.category.LAUNCHER" />                </intent-filter>            </activity>            <activity                android:name="com.itheima.request_result_code.ChooseSexActivity"                android:label="请选择性别"                android:theme="@android:style/Theme.Dialog" >            </activity>            <activity                android:name="com.itheima.request_result_code.ChooseHeadActivity"                android:label="请选择头像"                android:theme="@android:style/Theme.Dialog" >            </activity>        </application>

MainActivity.java

        public class MainActivity extends Activity {            public static final int CHOOSE_SEX = 1;            public static final int CHOOSE_IMAGE = 2;            private TextView tv_sex;            private ImageView iv_head;            @Override            protected void onCreate(Bundle savedInstanceState) {                super.onCreate(savedInstanceState);                setContentView(R.layout.activity_main);                tv_sex = (TextView) findViewById(R.id.tv_sex);                iv_head = (ImageView) findViewById(R.id.iv_head);            }            /**             * 选择性别             * @param view             */            public void openSexChooseActivity(View view) {                // 显式意图                Intent intent = new Intent(this, ChooseSexActivity.class);                startActivityForResult(intent, CHOOSE_SEX);            }            /**             * 选择头像             * @param view             */            public void openHeadImageChooseActivity(View view) {                // 显式意图                Intent intent = new Intent(this, ChooseHeadActivity.class);                startActivityForResult(intent, CHOOSE_IMAGE);            }            @Override            protected void onActivityResult(int requestCode, int resultCode, Intent data) {                if (data != null) {                    if(resultCode==CHOOSE_SEX){                        String sex = data.getStringExtra("sex");                        tv_sex.setText("您选择的性别为:" + sex);                    }else if(resultCode==CHOOSE_IMAGE){                        //返回图片资源                        Bitmap bitmap = data.getParcelableExtra("headbitmap");                        iv_head.setImageBitmap(bitmap);                    }                }                super.onActivityResult(requestCode, resultCode, data);            }        }

ChooseHeadActivity.java

        @Override        public void onClick(View v) {            Intent data = new Intent();            switch (v.getId()) {            case R.id.iv_e0:                data.putExtra("headbitmap", BitmapFactory.decodeResource(getResources(), R.drawable.e0));                break;            case R.id.iv_e1:                data.putExtra("headbitmap", BitmapFactory.decodeResource(getResources(), R.drawable.e1));                break;            case R.id.iv_e2:                data.putExtra("headbitmap", BitmapFactory.decodeResource(getResources(), R.drawable.e2));                break;            case R.id.iv_e3:                data.putExtra("headbitmap", BitmapFactory.decodeResource(getResources(), R.drawable.e3));                break;            }            setResult(MainActivity.CHOOSE_IMAGE, data);            finish();        }

ChooseSexActivity.java

        /**        *lv.setAdapter(new ArrayAdapter<T>(context, resource, objects));        */        public class ChooseSexActivity extends Activity {            private ListView lv;            String[] objects = {"男","女","未知"};            @Override            protected void onCreate(Bundle savedInstanceState) {                super.onCreate(savedInstanceState);                setContentView(R.layout.activity_choose);                lv = (ListView) findViewById(R.id.lv);                  //使用ArrayAdapter                lv.setAdapter(new ArrayAdapter<String>(this, R.layout.item_textview, objects));                lv.setOnItemClickListener(new OnItemClickListener() {                    @Override                    public void onItemClick(AdapterView<?> parent, View view,                            int position, long id) {                        String sex = objects[position];                         Intent data = new Intent();                         data.putExtra("sex", sex);//把数据设置到意图对象里面                         setResult(MainActivity.CHOOSE_SEX, data);                         finish();//关闭当前的界面  ★一定记得关闭界面,数据才会被返回                    }                });            }        }        /**        *lv.setAdapter(new SimpleAdapter(context, data, resource, from, to));        */        public class ContactListActivity extends Activity {            private ListView lv;            @Override            protected void onCreate(Bundle savedInstanceState) {                super.onCreate(savedInstanceState);                setContentView(R.layout.activity_listcontact);                lv = (ListView) findViewById(R.id.lv);                List<Map<String, String>> data = new ArrayList<Map<String,String>>();                for(int i=0;i<10;i++){                    Map<String, String> map = new HashMap<String, String>();                    map.put("name", "张三"+i);                    map.put("phone", "1000"+i);                    data.add(map);                }                lv.setAdapter(new SimpleAdapter(this, data, R.layout.item_contact, new String[]{"name","phone"},                         new int[]{R.id.tv_name,R.id.tv_phone}));                lv.setOnItemClickListener(new OnItemClickListener() {                    @Override                    public void onItemClick(AdapterView<?> parent, View view,                            int position, long id) {                        String number = "1000"+position;                        Intent data = new Intent();                        data.putExtra("number", number);                        setResult(MainActivity.GET_PHONE, data);                        finish();                    }                });            }        }

横竖屏切换的生命周期(ctrl+F11)

AndroidManifest.xml

  • 屏幕朝向

  • android:screenOrientation=”landscape” 横屏
    android:screenOrientation=”portrait” 竖屏
  • 忽略屏幕切换

    android:configChanges="orientation|keyboardHidden|screenSize" 方向/键盘/屏幕大小

启动模式和任务栈

AndroidManifest.xml

    android:launchMode="standard|singletop|singleTask|singleInstance"

* standard 默认的启动模式,标准模式(01,02)

01,01,02,02,01,02

  • singletop 单一顶部模式(02顶部不启动)

    01,01,02,01,02

    • 案例: 浏览器的书签
    • 目的: 避免奇怪的用户体验(避免被恶意程序开启多次)
  • singleTask 单一任务栈(一个任务栈02唯一)

    01,02,01,01,01,01

    01,02

    • 案例: 浏览器的BrowserActivity,应用程序的主界面
    • 目的: Activity非常笨重(内存开销非常大)
  • singleInstance 单一实例(独占任务栈02唯一)

    01,01,01,01,01

    02

    • 案例: 有道词典的快速取词,电话呼叫InCallScreen
    • 目的: 操作系统中唯一存在

广播接收者

广播接收者的代码是运行在主线程

    System.out.println(Thread.currentThread().getName());//当前线程名称

接收广播

MyBroadcastReceiver.java

        /**         * 1.买个收音机,继承BroadcastReceiver,         * 从写onReceive方法,用来接收消息的.         */        public class MyBroadcastReceiver extends BroadcastReceiver {            @Override            public void onReceive(Context arg0, Intent arg1) {                //打电话广播                  System.out.println("有新的电话别打出来了....");                String number = getResultData();// 获取当前的结果数据, 数据就是外拨的电话号码                SharedPreferences sp = context.getSharedPreferences("config",                        Context.MODE_PRIVATE);                //有序广播                //abortBroadcast();//无效的.                //setResultData(null);//使外拨电话为null                if (number.startsWith("0")) {                    setResultData(sp.getString("ipnumber", "") + number);                }                //收短信广播                Object[] objs  = (Object[]) intent.getExtras().get("pdus");//pdu 短信二进制数据报文                for(Object obj:objs){                    SmsMessage smsMessage = SmsMessage.createFromPdu((byte[]) obj);                    String sender = smsMessage.getOriginatingAddress();                    String body = smsMessage.getMessageBody();                    System.out.println("sender:"+sender);                    System.out.println("body:"+body);                    abortBroadcast();//拦截广播跟清单文件的android:priority="1000"参数配合使用                }            }        }

AndroidManifest.xml

    <uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>     <!-- 2.装配电池 -->    <receiver android:name="com.itheima.receiverdemo.MyBroadcastReceiver" >        <!-- 3.调频道 fm934,监听的是新的外拨电话 -->        <intent-filter android:priority="1000">//优先级            <!-- 打电话的广播接收者,有序广播-->            <action android:name="android.intent.action.NEW_OUTGOING_CALL"/>            <!-- SD卡的广播接收者-->            <action android:name="android.intent.action.MEDIA_UNMOUNTED"/>            <action android:name="android.intent.action.MEDIA_MOUNTED"/>            <data android:scheme="file"/>            <!-- 短信的广播接收者,有序广播-->            <action android:name="android.provider.Telephony.SMS_RECEIVED"/>            //卸载            <action android:name="android.intent.action.PACKAGE_REMOVED"/>            //安装            <action android:name="android.intent.action.PACKAGE_ADDED"/>            <data android:scheme="package"/>        </intent-filter>    </receiver>

代码注册广播接收者

  • 广播事件产生的很频繁,屏幕锁屏, 屏幕解锁, 电量变化,这些广播事件在清单文件中注册就不可用

MainActivity.java

        public class MainActivity extends Activity {            private ScreenStatusReceiver receiver;            @Override            protected void onCreate(Bundle savedInstanceState) {                super.onCreate(savedInstanceState);                setContentView(R.layout.activity_main);                receiver = new ScreenStatusReceiver();                IntentFilter filter = new IntentFilter();                filter.addAction("android.intent.action.SCREEN_OFF");                filter.addAction("android.intent.action.SCREEN_ON");                getApplicationContext().registerReceiver(receiver, filter);        //      Intent intent = new Intent(this,TestService.class);        //      startService(intent);            }            @Override            protected void onDestroy() {                //this.unregisterReceiver(receiver);                super.onDestroy();            }        }

ScreenStatusReceiver.java

        public class ScreenStatusReceiver extends BroadcastReceiver {            @Override            public void onReceive(Context context, Intent intent) {                String action = intent.getAction();                if("android.intent.action.SCREEN_ON".equals(action)){                    Toast.makeText(context, "屏幕解锁了", 0).show();                    System.out.println("屏幕解锁了");                }else if("android.intent.action.SCREEN_OFF".equals(action)){                    Toast.makeText(context, "屏幕被锁定了", 0).show();                    System.out.println("屏幕被锁定了");                }             }        }

TestService.java

        public class TestService extends Service {            private ScreenStatusReceiver receiver;            @Override            public IBinder onBind(Intent intent) {                return null;            }            @Override            public void onCreate() {                receiver = new ScreenStatusReceiver();                IntentFilter filter = new IntentFilter();                filter.addAction("android.intent.action.SCREEN_OFF");                filter.addAction("android.intent.action.SCREEN_ON");                this.registerReceiver(receiver, filter);                super.onCreate();            }            @Override            public void onStart(Intent intent, int startId) {                super.onStart(intent, startId);            }            @Override            public void onDestroy() {                unregisterReceiver(receiver);                super.onDestroy();            }        }       

发送广播

自定义无序广播

MainActivity.java

        /**         * 对外发送无序广播         */        public void click(View view){            Intent intent = new Intent();            intent.setAction("com.itheima.cctv.XXMLZY");            intent.putExtra("money", "5毛");            sendBroadcast(intent);        }

自定义有序广播

MainActivity.java (com.itheima.sendredheaddoc)

        /**         * 中央发送一个红头文件,文件是一级一级向下传达的.         *          * @param view         */        public void click(View view) {            Intent intent = new Intent();            intent.setAction("com.itheima.redheaddoc.BTNM");            //intent 意图. 自定义广播的意图            //receiverPermission            //resultReceiver 内线,作为最后一个接受广播消息的人            //scheduler 写null            //initialCode 初始化的编码 1号文件            NeiXianReceiver receiver = new NeiXianReceiver();            sendOrderedBroadcast(intent, null, receiver,                    null, 1, "给每个农民补贴10000块钱", null);        }

NeiXianReceiver.java (com.itheima.sendredheaddoc)

        public class NeiXianReceiver extends BroadcastReceiver {            @Override            public void onReceive(Context context, Intent intent) {                System.out.println("我是卧底:我在村里面获取到了消息:"+getResultData());            }        }

Service服务

本地服务

startService(intent)方式开启服务

案例-电话窃听器

PhoneStatusService.java

    /**     * 服务和Activity都拥有相同的父类, context上下文     * 长期后台运行,没有界面的组件,监视用户电话的通话状态.     *     */    public class PhoneStatusService extends Service {        /**         * 电话管理器 系统底层提供给我们的一个服务         */        private TelephonyManager  tm;        /**         * 声明一个录音机         */        private MediaRecorder mediaRecorder;        @Override        public IBinder onBind(Intent intent) {            return null;        }        //服务被创建        @Override        public void onCreate() {            System.out.println("服务被创建了");            //获取android系统里面内置的服务,长期后台运行,没有界面            tm = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);            //监听系统电话呼叫的状态,第一个参数是一个监听器对象            tm.listen(new MyPhoneListener(), PhoneStateListener.LISTEN_CALL_STATE);            super.onCreate();        }        //服务被销毁        @Override        public void onDestroy() {            System.out.println("服务被销毁了.");            super.onDestroy();        }        private class MyPhoneListener extends PhoneStateListener{            //当呼叫状态变化调用的方法            //state 电话的状态            //incomingNumber 来电号码            @Override            public void onCallStateChanged(int state, String incomingNumber) {                super.onCallStateChanged(state, incomingNumber);                switch (state) {                case TelephonyManager.CALL_STATE_IDLE://当前手机处于空闲状态,没有接打电话                    System.out.println("手机处于空闲状态");                    if(mediaRecorder!=null){                        mediaRecorder.stop();                        mediaRecorder.release();                        mediaRecorder = null;                        System.out.println("窃听完毕,上传音频文件到服务器");                    }                    break;                case TelephonyManager.CALL_STATE_RINGING://响铃状态,有人给手机打电话                    System.out.println("手机处于零响状态,准备一个录音机");                    break;                case TelephonyManager.CALL_STATE_OFFHOOK://接通电话                    System.out.println("手机处于通话状态,开启录音机录音");                    startMediaRecorder(incomingNumber);                    break;                }            }        }        /**         * 开启一个录音机 获取用户的声音         * @param incomingNumber 来电电话号码         */        public void startMediaRecorder(String incomingNumber) {            try {                //1.实例化录音机                mediaRecorder = new MediaRecorder();                //2.设置声音采集的音源                mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);//模拟器只支持mic                //3.设置输出文件的格式                mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.AMR_NB);//模拟器 写默认的格式                //4.设置输出的文件名称                mediaRecorder.setOutputFile("mnt/sdcard/temp.3gp");                //5.指定音频的编码方式                mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);                //6.准备开始录音                mediaRecorder.prepare();                //7.开始录音                mediaRecorder.start();            } catch (Exception e) {                e.printStackTrace();            }        }    }

AndroidManifest.xml

    <application        android:allowBackup="true"        android:icon="@drawable/ic_launcher"        android:label="@string/app_name"        android:theme="@style/AppTheme" >        <activity            android:name="com.itheima.phonelistener.MainActivity"            android:label="@string/app_name"            android:theme="@android:style/Theme.Translucent.NoTitleBar.Fullscreen" >            <intent-filter>                <action android:name="android.intent.action.MAIN" />                <category android:name="android.intent.category.LAUNCHER" />            </intent-filter>        </activity>        <service android:name="com.itheima.phonelistener.PhoneStatusService" >        </service>        <receiver android:name="com.itheima.phonelistener.BootCompleteReceiver" >            <intent-filter >                <action android:name="android.intent.action.BOOT_COMPLETED"/>            </intent-filter>        </receiver>    </application>

BootCompleteReceiver.java开机启动的广播接收者

    public class BootCompleteReceiver extends BroadcastReceiver {        @Override        public void onReceive(Context context, Intent intent) {            System.out.println("手机启动完毕了....");            Intent i = new Intent(context,PhoneStatusService.class);            context.startService(i);        }    }

进程的优先级

  • Android系统会尽量的长期保持每一个进程不被回收.
    The Android system tries to maintain an application process for as long as possible

    importance hierarchy 进程的优先级

    1. Foreground process 前台进程

      用户在操作的应用程序所在的进程就是前台进程

    2. Visible process 可见进程

      用户仍然可以看到界面,但是里面的按钮点击不了了.

    3. Service process 服务进程

      进程里面有一个服务正处于运行状态

    4. Background process 后台进程

      如果一个应用程序没有服务处于运行状态,界面最小化. onstop();

    5. Empty process

      应用程序没有任何活动的组件.没有服务,Activity也ondestroy了

bind方式开启服务

MainActivity.java

        public class MainActivity extends Activity {            IService myBinder;            @Override            protected void onCreate(Bundle savedInstanceState) {                super.onCreate(savedInstanceState);                setContentView(R.layout.activity_main);            }            /**             * 绑定服务,获取服务里面的小蜜,间接的调用服务里面的方法。             * @param view             */            public void bind(View view){                Intent intent = new Intent(this,DemoService.class);                //intent 意图                //conn 服务的通讯频道                //1 服务如果在绑定的时候不存在,会自动创建                System.out.println("1.采用bind的方式开启服务");                bindService(intent, new MyConn(), BIND_AUTO_CREATE);            }            /**             * 服务连接成功的通讯频道             */            private class MyConn implements ServiceConnection{                //当服务被成功连接的时候调用的方法                @Override                public void onServiceConnected(ComponentName name, IBinder service) {                    System.out.println("3. 得到了服务的一个连接,通讯频道,获取到服务内部的小蜜");                    myBinder = (IService) service;                    System.out.println("4.把ibinder强制类型转化成小蜜 MyBinder");                }                //当服务失去连接的时候调用的方法                @Override                public void onServiceDisconnected(ComponentName name) {                }            }            /**             * 调用服务里面的方法。             * @param view             */            public void call(View view){                System.out.println("5.利用mybinder间接的调用服务的方法");                myBinder.callMethodInService(600);            }        }

DemoService.java

        public class DemoService extends Service {            /**             * 在服务被绑定的时候调用的方法             * IBinder 服务内部的小蜜              */            @Override            public IBinder onBind(Intent intent) {                System.out.println("2. 服务如果成功绑定会执行onbind,返回服务内部的小蜜 mybinder");                return new MyBinder();            }            /**             * 服务内部的小蜜,可以调用服务的方法             */            private class MyBinder extends Binder implements IService{                /**                 * 调用服务的方法。                 * @param money 钱                 */                public void callMethodInService(int money){                    if(money>500){                        methodInService();                    }else{                        Toast.makeText(DemoService.this, "这点钱还想办事呀?", 0).show();                    }                }                public void 打麻将(){                    Toast.makeText(DemoService.this, "一起打麻将", 0).show();                }                public void 洗桑拿(){                    Toast.makeText(DemoService.this, "一起洗桑拿", 0).show();                }            }            /**             * 服务里面的方法             */            public void methodInService(){                Toast.makeText(this, "哈哈,我是服务的方法,被你调用了。", 0).show();            }            @Override            public void onCreate() {                System.out.println("服务被创建了");                super.onCreate();            }            @Override            public void onDestroy() {                System.out.println("服务被销毁了。");                super.onDestroy();            }        }

IService.java

        /**         * 定义的接口,暴露一个给钱办事的方法。         */        public interface IService {            public void callMethodInService(int money);        }

混合调用服务的生命周期处理

  • 为了保证服务长期的运行,又想调用服务的方法.
  • 一般步骤

    startService() 保证服务长期后台运行


bindService() 绑定服务 ,调用服务的方法

unbindservice() 解绑服务,不需要再去调用方法了

stopService() 停止服务

远程服务

  • IPC
    inter process communication 进程间通讯
  • AIDL
    android interface definition language 安卓接口定义语言,绑定远程服务的写法

远程服务案例

  • 支付宝APP

    AndroidManifest.xml

    <service android:name="com.itheima.alipay.AlipayService" >    <intent-filter >        <action android:name="com.itheima.alipay"/>    </intent-filter></service>

    AlipayService.java

    public class AlipayService extends Service {    private class MyBinder extends IService.Stub{        @Override        public int callSafePay(String username, String password, float money,long timestamp) {            return safePay(username, password, money, timestamp);        }    }    @Override    public IBinder onBind(Intent intent) {        return new MyBinder();    }    @Override    public void onCreate() {        System.out.println("支付宝服务被创建了");        super.onCreate();    }    @Override    public void onDestroy() {        System.out.println("支付宝服务被销毁了");        super.onDestroy();    }    /**     * 安全支付的服务     * @param username 用户名     * @param password 密码     * @param money 钱     * @param timestamp 时间戳     * @return 200 支付成功 404银行卡余额不足 505支付超过限额  408支付超时服务器无响应 300用户名密码错误     */    public int safePay(String username,String password,float money,long timestamp){        System.out.println("加密username");        System.out.println("加密password");        System.out.println("提交数据到支付宝的服务器");        if(money>5000){            return 505;//支付超过了限额        }        if("zhangsan".equals(username)&&"123".equals(password)){            return 200;        }else{            return 300;        }    }}

    IService.java → IService.aidl (com.itheima.alipay)

    interface IService {    int callSafePay(String username,String password,float money,long timestamp);}
  • 捕鱼达人APP

    IService.java → IService.aidl (com.itheima.alipay)

    interface IService {    int callSafePay(String username,String password,float money,long timestamp);}

    MainActivity.java

    public class MainActivity extends Activity {    private MyConn conn;    private IService  iService;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        Intent intent = new Intent();        //采用隐式意图        intent.setAction("com.itheima.alipay");        conn = new MyConn();        bindService(intent, conn, BIND_AUTO_CREATE);    }    private class MyConn implements ServiceConnection{        @Override        public void onServiceConnected(ComponentName name, IBinder service) {            System.out.println("成功绑定到远程alipay服务上");            iService = IService.Stub.asInterface(service);            }        @Override        public void onServiceDisconnected(ComponentName name) {        }    }    /**     * 调用远程服务的方法,支付2块钱.     * @param view     */    public void click(View view){        try {            //200 支付成功 404银行卡余额不足 505支付超过限额  408支付超时服务器无响应 300用户名密码错误            int resultcode = iService.callSafePay("zhangsan", "123", 2.00f, System.currentTimeMillis());            switch (resultcode) {            case 200:                Toast.makeText(this, "支付成功", 0).show();                break;            case 404:                Toast.makeText(this, "银行卡余额不足", 0).show();                break;            case 300:                Toast.makeText(this, "用户名密码错误", 0).show();                break;            }        } catch (Exception e) {            e.printStackTrace();        }    }}

利用通知栏提醒提升服务优先级

MainActivity.java

        public class MainActivity extends Activity {            private NotificationManager nm;            @Override            protected void onCreate(Bundle savedInstanceState) {                super.onCreate(savedInstanceState);                setContentView(R.layout.activity_main);                nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);            }            public void click(View view){                //链式调用.        //       Notification noti = new Notification.Builder(this)        //         .setContentTitle("我是通知的标题栏")        //         .setContentText("我是通知栏的内容")        //         .setSmallIcon(R.drawable.ic_launcher)        //         .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher))        //         .build();         //      nm.notify(0, noti);                //向下兼容的写法                Notification noti = new  Notification(R.drawable.ic_launcher, "通知到来了", System.currentTimeMillis());                noti.flags = Notification.FLAG_NO_CLEAR;                //设置点击后开启的事件                //PendingIntent 进程间通讯用的可以序列号的类,适合做进程间的通讯.行为是由另外的一个应用程序执行                Intent intent = new Intent();                intent.setAction(Intent.ACTION_CALL);                intent.setData(Uri.parse("tel://110"));                PendingIntent contentIntent = PendingIntent.getActivity(this, 0, intent,  Intent.FLAG_ACTIVITY_NEW_TASK);                noti.setLatestEventInfo(this, "我是大标题", "我是描述的文本", contentIntent);                nm.notify(0, noti);            }        }

TestService.java

    public class TestService extends Service {        @Override        public IBinder onBind(Intent intent) {            return null;        }        @Override        public void onCreate() {            //变成了 前台 进程 优先级最高. 不会被系统回收.            startForeground(0, notification);            super.onCreate();        }        @Override        public void onDestroy() {            // TODO Auto-generated method stub            super.onDestroy();        }    }

综合案例-音乐播放器

MainActivity.java

    public class MainActivity extends Activity {        private MyConn conn;        private IMusicService iMusicService;        private MusicService musicService;        private EditText et_path;        @Override        protected void onCreate(Bundle savedInstanceState) {            super.onCreate(savedInstanceState);            setContentView(R.layout.activity_main);            et_path = (EditText) findViewById(R.id.et_path);            //保证服务长期后台运行。            Intent intent = new Intent(this,MusicService.class);            startService(intent);            //调用服务的方法。            conn = new MyConn();            bindService(intent, conn, BIND_AUTO_CREATE);        }        private class MyConn implements ServiceConnection{            @Override            public void onServiceConnected(ComponentName name, IBinder service) {                iMusicService = (IMusicService) service;                musicService = iMusicService.callGetMusicService();            }            @Override            public void onServiceDisconnected(ComponentName name) {            }        }        public void play(View view){            String path = et_path.getText().toString().trim();            if(TextUtils.isEmpty(path)){                Toast.makeText(this, "路径不合法", 0).show();                return;            }            musicService.setMusic(path);            boolean result = musicService.play();            if(!result){                Toast.makeText(this, "播放失败,请检查路径,或者音乐文件是否合法", 0).show();            }        }        public void pause(View view){            musicService.pause();        }        public void resume(View view){            musicService.resume();        }        public void stop(View view){            musicService.stop();        }        @Override        protected void onDestroy() {            unbindService(conn);            super.onDestroy();        }    }

IMusicService.java接口返回服务的对象

    public interface IMusicService {        /**         * 调用获取服务的引用         * @return         */        public MusicService callGetMusicService();    }

MusicService.java

    public class MusicService extends Service {        /**         * 要播放的音乐文件的路径         */        private String path;        private MediaPlayer mediaPlayer;        /**         * 音乐播放的状态         */        private int PLAYING_STATUS;        private int STOP = 0;        private int PLAYING = 1;        private int PAUSE = 2;        @Override        public IBinder onBind(Intent intent) {            return new MyBinder();        }        private class MyBinder extends Binder implements IMusicService {            @Override            public MusicService callGetMusicService() {                return getMusicService();            }        }        /**         * 返回服务的对象         * @return         */        public MusicService getMusicService() {            return this;        }        @Override        public void onCreate() {            System.out.println("服务被创建了。");            super.onCreate();        }        @Override        public void onDestroy() {            System.out.println("服务被销毁了。");            super.onDestroy();        }        /**         * 设置要播放的音乐         * @param path         *            音乐文件的路径         */        public void setMusic(String path) {            this.path = path;        }        /**         * 播放音乐,播放之前请设置音乐的路径         */        public boolean play() {            if (mediaPlayer != null && mediaPlayer.isPlaying()) {                mediaPlayer.stop();                mediaPlayer.release();                mediaPlayer = null;            }            try {                if (path == null) {                    return false;                }                mediaPlayer = new MediaPlayer();                mediaPlayer.reset();                mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);                mediaPlayer.setDataSource(path);                mediaPlayer.prepare();                mediaPlayer.start();                PLAYING_STATUS = PLAYING;                return true;            } catch (Exception e) {                e.printStackTrace();                return false;            }        }        /**         * 暂停音乐         */        public void pause() {            if (mediaPlayer != null && mediaPlayer.isPlaying()) {                mediaPlayer.pause();                PLAYING_STATUS = PAUSE;            }        }        /**         * 继续开始         */        public void resume() {            if (mediaPlayer != null && PLAYING_STATUS == PAUSE) {                mediaPlayer.start();                PLAYING_STATUS = PLAYING;            }        }        public void stop() {            if (mediaPlayer != null && mediaPlayer.isPlaying()) {                mediaPlayer.stop();                mediaPlayer.release();                mediaPlayer = null;                PLAYING_STATUS = STOP;            }        }    }

内容提供者

内容提供者编写的步骤

  • 数据库APP

    AndroidManifest.xml

    <provider android:name="com.itheima.db.MyDBContentProvider"    android:authorities="com.itheima.db" ></provider>

    MyDBContentProvider.xml

    /** * 私有数据库的内容提供者,把自己数据库的内容提供给别的应用程序 在内容提供者的模板代码里面就默认定义了增删改查的方法. * 可以实现全部的方法,也可以实现部分的方法 */public class MyDBContentProvider extends ContentProvider {    private MyDBOpenHelper helper;    private static final int CONTACT_INFO_ALL = 1;    private static final int CONTACT_INFO_SINGLE = 2;    /**     * 定义一个uri路径的匹配器, 检查uri是否合法.如果路径不合法匹配失败返回 -1,相当于保安     */    private static UriMatcher mUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);    // 训练我们的保安,让他识别对应的路径    static {        // authority 主机名 路径的前缀        mUriMatcher.addURI("com.itheima.db", "contactinfo", CONTACT_INFO_ALL);        mUriMatcher.addURI("com.itheima.db", "contactinfo/#",                CONTACT_INFO_SINGLE);        // content://com.itheima.db/contactinfo -->1    }    /**     * 当内容提供者开始创建的时候调用的方法     */    @Override    public boolean onCreate() {        helper = new MyDBOpenHelper(getContext());// activity.this                                                    // getApplicationContext()                                                    // getContext()//模拟的假的上下文        return true;// 表示内容提供者成功加载    }    /**     * @param uri     *            查询的路径     * @param projection     *            查询数据库某个表那些列的内容     * @param selection     *            选择条件     * @param selectionArgs     *            选择条件的参数     * @param sortOrder     *            按什么方式排序 desc     */    @Override    public Cursor query(Uri uri, String[] projection, String selection,            String[] selectionArgs, String sortOrder) {        // 判断请求是否合法.        int code = mUriMatcher.match(uri);        if (code == CONTACT_INFO_ALL) {            // 得到一个可读的数据库            SQLiteDatabase db = helper.getReadableDatabase();            return db.query("contactinfo", projection, selection,                    selectionArgs, null, null, sortOrder);        } else if (code == CONTACT_INFO_SINGLE) {            //// content://com.itheima.db/contactinfo/3            String path = uri.toString();            SQLiteDatabase db = helper.getReadableDatabase();            return db.query("contactinfo", projection, "id=?",                    new String[]{path.substring(path.lastIndexOf("/")+1)}, null, null, sortOrder);        } else {            // 匹配失败            throw new IllegalArgumentException("暗号对错了,拖出去打一顿");        }    }    /**     * 告诉调用者数据的类型是一条 还是一组     */    @Override    public String getType(Uri uri) {        int code = mUriMatcher.match(uri);        if (code == CONTACT_INFO_ALL) {            return "vnd.android.cursor.dir/contanct";        } else if (code == CONTACT_INFO_SINGLE) {            return "vnd.android.cursor.item/contanct";        } else {            // 匹配失败            throw new IllegalArgumentException("错误的数据类型");        }    }    @Override    public Uri insert(Uri uri, ContentValues values) {        // 判断请求是否合法.        int code = mUriMatcher.match(uri);        if (code == CONTACT_INFO_ALL) {            // 得到一个可写的数据库            SQLiteDatabase db = helper.getWritableDatabase();            long row = db.insert("contactinfo", null, values);            db.close();            // content://com.itheima.db/contactinfo/103            return Uri.parse("content://com.itheima.db/contactinfo/" + row);        } else {            // 匹配失败            throw new IllegalArgumentException("暗号对错了,拖出去打一顿");        }    }    @Override    public int delete(Uri uri, String selection, String[] selectionArgs) {        // 判断请求是否合法.        int code = mUriMatcher.match(uri);        if (code == CONTACT_INFO_ALL) {            // 得到一个可写的数据库            SQLiteDatabase db = helper.getWritableDatabase();            int count = db.delete("contactinfo", selection, selectionArgs);            db.close();            return count;        } else {            // 匹配失败            throw new IllegalArgumentException("暗号对错了,拖出去打一顿");        }    }    @Override    public int update(Uri uri, ContentValues values, String selection,            String[] selectionArgs) {        // 判断请求是否合法.        int code = mUriMatcher.match(uri);        if (code == CONTACT_INFO_ALL) {            // 得到一个可写的数据库            SQLiteDatabase db = helper.getWritableDatabase();            int count = db.update("contactinfo", values, selection,                    selectionArgs);            db.close();            return count;        } else {            // 匹配失败            throw new IllegalArgumentException("暗号对错了,拖出去打一顿");        }    }}
  • 通过后门读取数据APP

    public class MainActivity extends Activity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);    }    /**     * 查询数据     * @param view     */    public void read(View view) {        // 通过后门读取数据库应用私有的数据库信息        // 1. 获取内容提供者的解析器        ContentResolver resolver = getContentResolver();        // 2.利用解析器获取私有的数据库        Uri uri = Uri.parse("content://com.itheima.db/contactinfo/33");        String type = resolver.getType(uri);// vnd.android.cursor.item 只有一条记录        // vnd.android.cursor.dir/ 多条数据        if (type.startsWith("vnd.android.cursor.dir")) {            System.out.println("一组数据");            Cursor cursor = resolver.query(uri, null, null, null, null);            while (cursor.moveToNext()) {                String id = cursor.getString(0);                String name = cursor.getString(1);                String phone = cursor.getString(2);                System.out.println("id:" + id + "--name:" + name + "--phone:"                        + phone);            }            cursor.close();        }else if(type.startsWith("vnd.android.cursor.item")){            System.out.println("一条数据");            Cursor cursor = resolver.query(uri, null, null, null, null);            cursor.moveToFirst();            String id = cursor.getString(0);            String name = cursor.getString(1);            String phone = cursor.getString(2);            System.out.println("id:" + id + "--name:" + name + "--phone:"                    + phone);            cursor.close();        }    }    /**     * 添加数据     * @param view     */    public void insert(View view) {        // 1. 获取内容提供者的解析器        ContentResolver resolver = getContentResolver();        // 2.利用解析器获取私有的数据库        Uri uri = Uri.parse("content://com.itheima.db/contactinfo");        ContentValues values = new ContentValues();        values.put("name", "李四");        values.put("phone", "9999999");        Uri result = resolver.insert(uri, values);        Toast.makeText(this, result.toString(), 1).show();    }    /**     * 删除数据     * @param view     */    public void delete(View view) {        // 1. 获取内容提供者的解析器        ContentResolver resolver = getContentResolver();        // 2.利用解析器获取私有的数据库        Uri uri = Uri.parse("content://com.itheima.db/contactinfo");        int count = resolver.delete(uri, "name=?", new String[] { "李四" });        Toast.makeText(this, "删除了" + count + "条记录", 0).show();    }    /**     * 修改数据     * @param view     */    public void update(View view) {        // 1. 获取内容提供者的解析器        ContentResolver resolver = getContentResolver();        // 2.利用解析器获取私有的数据库        Uri uri = Uri.parse("content://com.itheima.db/contactinfo");        ContentValues values = new ContentValues();        values.put("phone", "66666");        int count = resolver.update(uri, values, "name=?",                new String[] { "李四" });        Toast.makeText(this, "修改了" + count + "条记录", 0).show();    }}

内容观察者

BankInfoProvider.java 在内容提供者里面设置数据变化的消息notifyChange

    getContext().getContentResolver().notifyChange(uri, null);

MainActivity.java 设置内容观察者

    public class MainActivity extends Activity {        @Override        protected void onCreate(Bundle savedInstanceState) {            super.onCreate(savedInstanceState);            setContentView(R.layout.activity_main);            getContentResolver().registerContentObserver(Uri.parse("content://sms"), true, new MyObserver(new Handler()));        }        private class MyObserver extends ContentObserver{            public MyObserver(Handler handler) {                super(handler);            }            @Override            public void onChange(boolean selfChange) {                super.onChange(selfChange);                System.out.println("短信的数据库变化了。");                //查询数据库。            }        }    }

多媒体编程

加载大图片

    public class MainActivity extends Activity {        private ImageView iv;        @Override        protected void onCreate(Bundle savedInstanceState) {            super.onCreate(savedInstanceState);            setContentView(R.layout.activity_main);            iv = (ImageView) findViewById(R.id.iv);        }        public void click(View view) {            // 这种方式把所有的像素点都加载内存,vm虚拟机扛不住.            // Bitmap bitmap = BitmapFactory.decodeFile("mnt/sdcard/hh.jpg");            // iv.setImageBitmap(bitmap);            // 用户识别的出来的图形,受到设备的分辨率的限制.            // 只要我们显示的图形比手机的分辨率高,或者跟手机分辨率一致,用户就看不出来图形的质量的缩放了.            BitmapFactory.Options opts = new Options();// 解码图片的配置选项            opts.inJustDecodeBounds = true;// 不去真实的解析bitmap,而是查询bitmap的宽高信息            BitmapFactory.decodeFile("mnt/sdcard/hh.jpg", opts);            int width = opts.outWidth;            int height = opts.outHeight;            System.out.println("图片宽度width:" + width);            System.out.println("图片高度height:" + height);            // 得到手机屏幕的宽高            WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);            int screenWidth = wm.getDefaultDisplay().getWidth();            int screenHeight = wm.getDefaultDisplay().getHeight();            System.out.println("屏幕宽度width:" + screenWidth);            System.out.println("屏幕高度height:" + screenHeight);            int dx = width / screenWidth;            int dy = height / screenHeight;            int scale = 1;            if (dx > dy && dy > 1) {                scale = dx;            }            if (dy > dx && dx > 1) {                scale = dy;            }            System.out.println(scale);            //缩放的方式把图片加载到手机内存            opts.inSampleSize = scale;            opts.inJustDecodeBounds = false;// 真实的解析bitmap            Bitmap bitmap = BitmapFactory.decodeFile("mnt/sdcard/hh.jpg", opts);            iv.setImageBitmap(bitmap);        }    }

图片处理

    public class MainActivity extends Activity {        private ImageView iv;        @Override        protected void onCreate(Bundle savedInstanceState) {            super.onCreate(savedInstanceState);            setContentView(R.layout.activity_main);            iv = (ImageView) findViewById(R.id.iv);        }        public void turnBig(View view) {            Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.meinv);            Matrix matrix = new Matrix();            matrix.setScale(2, 2);            //1.买一张纸            Bitmap newBitmap = Bitmap.createBitmap(bitmap.getWidth()*2, bitmap.getHeight()*2, bitmap.getConfig());            //2.买个画板            Canvas canvas = new Canvas(newBitmap);            //3.临摹作画            Paint paint = new Paint();            paint.setColor(Color.BLACK);            canvas.drawBitmap(bitmap, matrix, paint);            iv.setImageBitmap(newBitmap);        }        public void turnSmall(View view) {            Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.meinv);            Matrix matrix = new Matrix();            matrix.setScale(0.5f, 0.5f);            //1.买一张纸            Bitmap newBitmap = Bitmap.createBitmap(bitmap.getWidth()/2, bitmap.getHeight()/2, bitmap.getConfig());            //2.买个画板            Canvas canvas = new Canvas(newBitmap);            //3.临摹作画            Paint paint = new Paint();            paint.setColor(Color.BLACK);            canvas.drawBitmap(bitmap, matrix, paint);            iv.setImageBitmap(newBitmap);        }        //左移        public void turnleft(View view) {            Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.meinv);            Matrix matrix = new Matrix();            dx --;            matrix.setTranslate(dx, 0);            //1.买一张纸            Bitmap newBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), bitmap.getConfig());            //2.买个画板            Canvas canvas = new Canvas(newBitmap);            //3.临摹作画            Paint paint = new Paint();            canvas.drawColor(Color.WHITE);            paint.setColor(Color.BLACK);            canvas.drawBitmap(bitmap, matrix, paint);            iv.setImageBitmap(newBitmap);        }        //右移        public void turnRight(View view) {            Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.meinv);            Matrix matrix = new Matrix();            dx ++;            matrix.setTranslate(dx, 0);            //1.买一张纸            Bitmap newBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), bitmap.getConfig());            //2.买个画板            Canvas canvas = new Canvas(newBitmap);            //3.临摹作画            Paint paint = new Paint();            canvas.drawColor(Color.WHITE);            paint.setColor(Color.BLACK);            canvas.drawBitmap(bitmap, matrix, paint);            iv.setImageBitmap(newBitmap);        }        //逆时针 倒转        public void turnleft(View view) {            Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.meinv);            Matrix matrix = new Matrix();            degrees--;            matrix.setRotate(degrees, bitmap.getWidth(), bitmap.getHeight());            matrix.postTranslate(100, 100);            //1.买一张纸            Bitmap newBitmap = Bitmap.createBitmap(bitmap.getWidth()*2, bitmap.getHeight()*2, bitmap.getConfig());            //2.买个画板            Canvas canvas = new Canvas(newBitmap);            //3.临摹作画            Paint paint = new Paint();            canvas.drawColor(Color.WHITE);            paint.setColor(Color.WHITE);            paint.setAntiAlias(true);//锯齿消除            canvas.drawBitmap(bitmap, matrix, paint);            iv.setImageBitmap(newBitmap);        }        //顺时针 正转        public void turnRight(View view) {            new Thread(){                public void run() {                    while(true){                        Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.meinv);                        Matrix matrix = new Matrix();                        degrees++;                        matrix.setRotate(degrees, bitmap.getWidth(), bitmap.getHeight());                        matrix.postTranslate(30, 30);                        //1.买一张纸                        final Bitmap newBitmap = Bitmap.createBitmap((int)(bitmap.getWidth()*1.5), (int)(bitmap.getHeight()*1.5), bitmap.getConfig());                        //2.买个画板                        Canvas canvas = new Canvas(newBitmap);                        //3.临摹作画                        Paint paint = new Paint();                        canvas.drawColor(Color.WHITE);                        paint.setAntiAlias(true);//锯齿消除                        paint.setColor(Color.WHITE);                        canvas.drawBitmap(bitmap, matrix, paint);                        runOnUiThread(new Runnable() {                            @Override                            public void run() {                                iv.setImageBitmap(newBitmap);                            }                        });                        try {                            Thread.sleep(20);                        } catch (InterruptedException e) {                            e.printStackTrace();                        }                    }                };            }.start();        }        //倒影        public void click01(View view) {            Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.meinv);            Matrix matrix = new Matrix();            matrix.setScale(1, -1);            matrix.postTranslate(0, bitmap.getHeight());            //1.买一张纸            Bitmap newBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), bitmap.getConfig());            //2.买个画板            Canvas canvas = new Canvas(newBitmap);            //3.临摹作画            Paint paint = new Paint();            canvas.drawColor(Color.WHITE);            paint.setColor(Color.BLACK);            canvas.drawBitmap(bitmap, matrix, paint);            iv.setImageBitmap(newBitmap);        }        //镜面        public void click02(View view) {            Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.meinv);            Matrix matrix = new Matrix();            matrix.setScale(-1, 1);            matrix.postTranslate(bitmap.getWidth(),0);            //1.买一张纸            Bitmap newBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), bitmap.getConfig());            //2.买个画板            Canvas canvas = new Canvas(newBitmap);            //3.临摹作画            Paint paint = new Paint();            canvas.drawColor(Color.WHITE);            paint.setColor(Color.BLACK);            canvas.drawBitmap(bitmap, matrix, paint);            iv.setImageBitmap(newBitmap);        }    }

图片画画板

    public class MainActivity extends Activity implements OnClickListener {        private ImageView iv;        private Canvas canvas;        private Paint paint;        private Bitmap bitmap;        private TextView tv_red;        private TextView tv_green;        private TextView tv_blue;        @Override        protected void onCreate(Bundle savedInstanceState) {            super.onCreate(savedInstanceState);            setContentView(R.layout.activity_main);            iv = (ImageView) findViewById(R.id.iv);            tv_red = (TextView) findViewById(R.id.tv_red);            tv_green = (TextView) findViewById(R.id.tv_green);            tv_blue = (TextView) findViewById(R.id.tv_blue);            tv_blue.setOnClickListener(this);            tv_green.setOnClickListener(this);            tv_red.setOnClickListener(this);            int width = getWindowManager().getDefaultDisplay().getWidth();            int height = getWindowManager().getDefaultDisplay().getHeight();            // 1.创建一个纸            bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); // 2.买个画板            canvas = new Canvas(bitmap); // 3.作画            canvas.drawColor(Color.WHITE);            paint = new Paint();            paint.setColor(Color.BLACK);            paint.setStrokeWidth(20);            iv.setOnTouchListener(new OnTouchListener() {                int startX;                int startY;                @Override                public boolean onTouch(View v, MotionEvent event) {                    switch (event.getAction()) {                    case MotionEvent.ACTION_DOWN:// 手指按下屏幕                        System.out.println("摸到");                        startX = (int) event.getRawX();                        startY = (int) event.getRawY();                        break;                    case MotionEvent.ACTION_MOVE:// 手指在屏幕上移动                        System.out.println("移动");                        int endX = (int) event.getRawX();                        int endY = (int) event.getRawY();                        canvas.drawLine(startX, startY, endX, endY, paint);                        // 重新初始化线的开始位置                        startX = (int) event.getRawX();                        startY = (int) event.getRawY();                        iv.setImageBitmap(bitmap);                        break;                    case MotionEvent.ACTION_UP:// 手指立刻屏幕之前调用的方法                        System.out.println("放手");                        break;                    }                    return true;                }            });        }        @Override        public void onClick(View v) {            switch (v.getId()) {            case R.id.tv_blue:                paint.setColor(Color.BLUE);                Toast.makeText(this, "蓝色", 0).show();                break;            case R.id.tv_red:                paint.setColor(Color.RED);                Toast.makeText(this, "红色", 0).show();                break;            case R.id.tv_green:                paint.setColor(Color.GREEN);                Toast.makeText(this, "绿色", 0).show();                break;            }        }        public void saveImage(View view){            try {                File file = new File(Environment.getExternalStorageDirectory(),System.currentTimeMillis()+".jpg");                FileOutputStream stream = new FileOutputStream(file);                bitmap.compress(CompressFormat.JPEG, 100, stream);                stream.close();                Toast.makeText(this, "保存成功", 0).show();                //模拟一个sd卡被插入的事件                Intent intent = new Intent();                intent.setAction(Intent.ACTION_MEDIA_MOUNTED);                intent.setData(Uri.fromFile(Environment.getExternalStorageDirectory()));                sendBroadcast(intent);            } catch (Exception e) {                e.printStackTrace();                Toast.makeText(this, "保存失败,请检查sd的状态", 0).show();            }        }    }

图片调色器

activity_main.xml

     <LinearLayout        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:gravity="center_vertical"        android:orientation="horizontal" >        <TextView            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:text="青" />        <SeekBar            android:max="255"            android:id="@+id/sb_red"            android:progress="128"            android:layout_width="0dip"            android:layout_height="wrap_content"            android:layout_weight="1" />        <TextView            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:text="红" />    </LinearLayout>

MainActivity.java

    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        iv = (ImageView) findViewById(R.id.iv);        sb_red = (SeekBar) findViewById(R.id.sb_red);        sb_green = (SeekBar) findViewById(R.id.sb_green);        sb_blue = (SeekBar) findViewById(R.id.sb_blue);        sb_alpha = (SeekBar) findViewById(R.id.sb_alpha);        bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.pre19);        newBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), bitmap.getConfig());        canvas = new Canvas(newBitmap);        paint = new Paint();        cm = new ColorMatrix();        cm.set(new float[] {            1, 0, 0, 0, 0,            0, 1, 0, 0, 0,            0, 0, 1, 0, 0,            0, 0, 0, 1, 0        });        paint.setColorFilter(new ColorMatrixColorFilter(cm));        canvas.drawBitmap(bitmap, new Matrix(), paint);        sb_red.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {            //拖动停止的时候调用的方法            @Override            public void onStopTrackingTouch(SeekBar seekBar) {                int progress = seekBar.getProgress();                float fred = progress/128.0f;                cm.set(new float[] {//RGBα                        fred, 0, 0, 0, 0,                        0, 1, 0, 0, 0,                        0, 0, 1, 0, 0,                        0, 0, 0, 1, 0                    });                paint.setColorFilter(new ColorMatrixColorFilter(cm));                canvas.drawBitmap(bitmap, new Matrix(), paint);                iv.setImageBitmap(newBitmap);            }            //当开始拖动的时候调用的方法            @Override            public void onStartTrackingTouch(SeekBar seekBar) {                // TODO Auto-generated method stub            }            //当拖动过程中调用的方法            @Override            public void onProgressChanged(SeekBar seekBar, int progress,                    boolean fromUser) {            }        });

视频播放器

    public class MainActivity extends Activity {        private SurfaceView sv;        private MediaPlayer mediaplayer;        private SharedPreferences sp;        private SeekBar seekBar1;        private Timer timer ;        private TimerTask task;        private ProgressBar pb;        @Override        protected void onCreate(Bundle savedInstanceState) {            super.onCreate(savedInstanceState);            setContentView(R.layout.activity_main);            seekBar1 = (SeekBar) findViewById(R.id.seekBar1);            pb = (ProgressBar) findViewById(R.id.pb);            seekBar1.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {                @Override                public void onStopTrackingTouch(SeekBar seekBar) {                    if(mediaplayer!=null&&mediaplayer.isPlaying()){                        mediaplayer.seekTo(seekBar.getProgress());                    }                }                @Override                public void onStartTrackingTouch(SeekBar seekBar) {                }                @Override                public void onProgressChanged(SeekBar seekBar, int progress,                        boolean fromUser) {                }            });            sv = (SurfaceView) findViewById(R.id.sv);            sp = getSharedPreferences("config", 0);            sv.getHolder().addCallback(new Callback() {                @Override                public void surfaceDestroyed(SurfaceHolder holder) {                    System.out.println("SurfaceView被销毁了");                    if(mediaplayer!=null&&mediaplayer.isPlaying()){                        int position = mediaplayer.getCurrentPosition();                        Editor editor = sp.edit();                        editor.putInt("position", position);                        editor.commit();                        mediaplayer.stop();                        mediaplayer.release();                        mediaplayer = null;                        timer.cancel();                        task.cancel();                        timer = null;                        task = null;                    }                }                @Override                public void surfaceCreated(SurfaceHolder holder) {                    System.out.println("SurfaceView被创建了");                    try {                        mediaplayer = new MediaPlayer();                        mediaplayer.setAudioStreamType(AudioManager.STREAM_MUSIC);                        //设置缩放比例                        //mediaplayer.setVideoScalingMode(MediaPlayer.VIDEO_SCALING_MODE_SCALE_TO_FIT);                        mediaplayer.setDataSource("http://192.168.1.109:8080/cc.MP4");                        //播放视频必须设置播放的容器,通过sv得到他的holder                        mediaplayer.setDisplay(sv.getHolder());                        //mediaplayer.prepare(); // might take long! (for buffering, etc)                        mediaplayer.prepareAsync();//异步的准备,开子线程                        mediaplayer.setOnCompletionListener(new OnCompletionListener() {                            @Override                            public void onCompletion(MediaPlayer mp) {                                Editor editor = sp.edit();                                editor.putInt("position", 0);                                editor.commit();                            }                        });                        mediaplayer.setOnPreparedListener(new OnPreparedListener() {                            //准备完毕了                            @Override                            public void onPrepared(MediaPlayer mp) {                                pb.setVisibility(View.INVISIBLE);                                mediaplayer.start();                                int position = sp.getInt("position", 0);                                mediaplayer.seekTo(position);                                timer = new Timer();                                task = new TimerTask() {                                    @Override                                    public void run() {                                        int max = mediaplayer.getDuration();                                        int progress = mediaplayer.getCurrentPosition();                                        seekBar1.setMax(max);                                        seekBar1.setProgress(progress);                                    }                                };                                timer.schedule(task, 0, 500);                            }                        });                    } catch (Exception e) {                        e.printStackTrace();                    }                }                @Override                public void surfaceChanged(SurfaceHolder holder, int format, int width,                        int height) {                }            });        }        @Override        public boolean onTouchEvent(MotionEvent event) {            if(event.getAction()==MotionEvent.ACTION_DOWN){                System.out.println("-------");                seekBar1.setVisibility(View.VISIBLE);                new Thread(){                    public void run() {                        SystemClock.sleep(3000);                        runOnUiThread(new Runnable() {                            @Override                            public void run() {                                seekBar1.setVisibility(View.INVISIBLE);                            }                        });                    };                }.start();            }            return super.onTouchEvent(event);        }    }

SoundPool

    public class MainActivity extends Activity {        private SoundPool soundPool;//声音池        int soundid ;        @Override        protected void onCreate(Bundle savedInstanceState) {            super.onCreate(savedInstanceState);            setContentView(R.layout.activity_main);            soundPool = new SoundPool(5, AudioManager.STREAM_MUSIC, 0);            soundid = soundPool.load(this, R.raw.alarm, 1);        }        public void click(View view){            soundPool.play(soundid, 1.0f, 1.0f, 0, 0, 1.0f);        }    }

拍照

    public void click(View view) {        Intent intent = new Intent();        intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE);        file= new File(Environment.getExternalStorageDirectory(),System.currentTimeMillis()+".jpg");        intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(file)); // set the image file        // start the image capture Intent        startActivityForResult(intent, 0);    }    @Override    protected void onActivityResult(int requestCode, int resultCode, Intent data) {        Toast.makeText(this, "照片存储在:"+file.getAbsolutePath(), 0).show();        super.onActivityResult(requestCode, resultCode, data);        System.out.println(file.getAbsolutePath());    }

录像

    public void click(View view) {        Intent intent = new Intent();        intent.setAction(MediaStore.ACTION_VIDEO_CAPTURE);        file= new File(Environment.getExternalStorageDirectory(),System.currentTimeMillis()+".3gp");        intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(file)); // set the image file        // start the image capture Intent        startActivityForResult(intent, 0);    }    @Override    protected void onActivityResult(int requestCode, int resultCode, Intent data) {        Toast.makeText(this, "视频存储在:"+file.getAbsolutePath(), 0).show();        super.onActivityResult(requestCode, resultCode, data);        System.out.println(file.getAbsolutePath());    }

传感器

光传感器

    public class MainActivity extends Activity {        private SensorManager mSensorManager;        private MyListener listener;        @Override        protected void onCreate(Bundle savedInstanceState) {            super.onCreate(savedInstanceState);            setContentView(R.layout.activity_main);            listener = new MyListener();            //获取传感器的服务            mSensorManager =  (SensorManager) getSystemService(SENSOR_SERVICE);            //得到光传感器            Sensor sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);            mSensorManager.registerListener(listener, sensor, SensorManager.SENSOR_DELAY_NORMAL);        }           private class MyListener implements SensorEventListener{            //当精确度变化的时候调用的方法            @Override            public void onAccuracyChanged(Sensor sensor, int accuracy) {            }            //当传感器发现数据变化的时候调用的方法            @Override            public void onSensorChanged(SensorEvent event) {                float light = event.values[0];                System.out.println("当前光线强度:"+light);            }        }        @Override        protected void onDestroy() {            mSensorManager.unregisterListener(listener);            listener = null;            super.onDestroy();        }    }

方向传感器

    public class MainActivity extends Activity {        private SensorManager mSensorManager;        private MyListener listener;        @Override        protected void onCreate(Bundle savedInstanceState) {            super.onCreate(savedInstanceState);            setContentView(R.layout.activity_main);            listener = new MyListener();            //获取传感器的服务            mSensorManager =  (SensorManager) getSystemService(SENSOR_SERVICE);            //得到方向传感器            Sensor sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);            mSensorManager.registerListener(listener, sensor, SensorManager.SENSOR_DELAY_NORMAL);        }           private class MyListener implements SensorEventListener{            //当精确度变化的时候调用的方法            @Override            public void onAccuracyChanged(Sensor sensor, int accuracy) {            }            //当传感器发现数据变化的时候调用的方法            @Override            public void onSensorChanged(SensorEvent event) {                //0=North, 90=East, 180=South, 270=West                 float angle = event.values[0];                System.out.println("angle:"+angle);            }        }        @Override        protected void onDestroy() {            mSensorManager.unregisterListener(listener);            listener = null;            super.onDestroy();        }    }

动画

帧动画

res->drawable

  • 1.gif
  • 2.gif
  • 3.gif
  • animation-list.xml

    <animation-list xmlns:android="http://schemas.android.com/apk/res/android"     android:oneshot="true">    <item        android:drawable="@drawable/1"        android:duration="100"/>    <item        android:drawable="@drawable/2"        android:duration="100"/>    <item        android:drawable="@drawable/3"        android:duration="100"/></animation-list>
  • activity_main.xml

    <ImageView    android:id="@+id/iv"    android:layout_width="wrap_content"    android:layout_height="wrap_content"    />
  • MainActivity.java

    public class MainActivity extends Activity {    private ImageView iv;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        iv = (ImageView) findViewById(R.id.iv);        iv.setBackgroundResource(R.drawable.girl_ainm);        AnimationDrawable anim = (AnimationDrawable) iv.getBackground();        anim.start();    }}

补间动画

    public class MainActivity extends Activity {        private ImageView iv;        @Override        protected void onCreate(Bundle savedInstanceState) {            super.onCreate(savedInstanceState);            setContentView(R.layout.activity_main);            iv = (ImageView) findViewById(R.id.iv);        }        /**         * 透明度变化的动画         * @param view         */        public void alpha(View view) {            // 完全透明0.0f->完全不透明1.0f            AlphaAnimation aa = new AlphaAnimation(0.0f, 1.0f);            // 动画播放2秒            aa.setDuration(2000);            aa.setRepeatCount(2);            aa.setRepeatMode(Animation.REVERSE);            iv.startAnimation(aa);        }        /**         * 缩放动画         * @param view         */        public void scale(View view) {            ScaleAnimation sa = new ScaleAnimation(0.0f, 2.0f, 0.0f, 2.0f,                    Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,                    0.5f);            sa.setDuration(2000);            sa.setRepeatCount(2);            sa.setRepeatMode(Animation.REVERSE);            iv.startAnimation(sa);        }        /**         * 位移动画         * @param view         */        public void Trans(View view) {            TranslateAnimation ta = new TranslateAnimation(                    Animation.RELATIVE_TO_SELF, -0.5f, Animation.RELATIVE_TO_SELF, 0.5f,                    Animation.RELATIVE_TO_SELF, -0.5f, Animation.RELATIVE_TO_SELF, 0.5f);            ta.setDuration(2000);            ta.setRepeatCount(2);            ta.setRepeatMode(Animation.REVERSE);            iv.startAnimation(ta);        }        /**         * 旋转动画         * @param view         */        public void rotate(View view) {            RotateAnimation ra = new RotateAnimation(0, 360, Animation.RELATIVE_TO_SELF,                    0.5f, Animation.RELATIVE_TO_SELF, 0.5f);            ra.setDuration(2000);            ra.setRepeatCount(2);            ra.setRepeatMode(Animation.REVERSE);            iv.startAnimation(ra);        }        public void set(View view){            AnimationSet set = new AnimationSet(false);            TranslateAnimation ta = new TranslateAnimation(                    Animation.RELATIVE_TO_SELF, -0.5f, Animation.RELATIVE_TO_SELF, 0.5f,                    Animation.RELATIVE_TO_SELF, -0.5f, Animation.RELATIVE_TO_SELF, 0.5f);            ta.setDuration(2000);            ta.setRepeatCount(2);            ta.setRepeatMode(Animation.REVERSE);            RotateAnimation ra = new RotateAnimation(0, 360, Animation.RELATIVE_TO_SELF,                    0.5f, Animation.RELATIVE_TO_SELF, 0.5f);            ra.setDuration(2000);            ra.setRepeatCount(2);            ra.setRepeatMode(Animation.REVERSE);            ScaleAnimation sa = new ScaleAnimation(0.0f, 2.0f, 0.0f, 2.0f,                    Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,                    0.5f);            sa.setDuration(2000);            sa.setRepeatCount(2);            sa.setRepeatMode(Animation.REVERSE);            set.addAnimation(sa);            set.addAnimation(ta);            set.addAnimation(ra);            iv.startAnimation(set);        }    }

补间动画XML配置

res->anim

  • alpha.xml

        <alpha xmlns:android="http://schemas.android.com/apk/res/android"        android:fromAlpha="0"        android:toAlpha="1.0"        android:duration="2000"        android:repeatCount="2"        android:repeatMode="reverse" >    </alpha>
  • rotate.xml

        <rotate xmlns:android="http://schemas.android.com/apk/res/android"        android:fromDegrees="0"        android:toDegrees="360"        android:duration="2000"        android:repeatCount="2"        android:repeatMode="reverse"        android:pivotX="50%p"        android:pivotY="50%p" >    </rotate>
  • scale.xml

        <scale xmlns:android="http://schemas.android.com/apk/res/android"        android:duration="2000"        android:fromXScale="0.0"        android:fromYScale="0.0"        android:pivotX="50%"        android:pivotY="50%"        android:repeatCount="2"        android:repeatMode="reverse"        android:toXScale="2.0"        android:toYScale="2.0" >    </scale>
  • trans.xml

        <translate xmlns:android="http://schemas.android.com/apk/res/android"        android:duration="2000"        android:fromXDelta="-50%p"        android:fromYDelta="-50%p"        android:repeatCount="2"        android:repeatMode="reverse"        android:toXDelta="50%p"        android:fillAfter="true"        android:toYDelta="50%p" >    </translate>
  • set.xml

        <set>        <rotate            xmlns:android="http://schemas.android.com/apk/res/android"            android:duration="2000"            android:fromDegrees="0"            android:pivotX="50%"            android:pivotY="50%"            android:repeatCount="2"            android:repeatMode="reverse"            android:toDegrees="360" >        </rotate>        <scale            xmlns:android="http://schemas.android.com/apk/res/android"            android:duration="2000"            android:fromXScale="0.0"            android:fromYScale="0.0"            android:pivotX="50%"            android:pivotY="50%"            android:repeatCount="2"            android:repeatMode="reverse"            android:toXScale="2.0"            android:toYScale="2.0" >        </scale>        <translate            xmlns:android="http://schemas.android.com/apk/res/android"            android:duration="2000"            android:fromXDelta="-50%"            android:fromYDelta="-50%"            android:repeatCount="2"            android:repeatMode="reverse"            android:toXDelta="50%"            android:toYDelta="50%" >        </translate>    </set>
  • MainActivity.java

        public class MainActivity extends Activity {        private ImageView iv;        @Override        protected void onCreate(Bundle savedInstanceState) {            super.onCreate(savedInstanceState);            setContentView(R.layout.activity_main);            iv = (ImageView) findViewById(R.id.iv);        }        /**         * 透明度变化的动画         * @param view         */        public void alpha(View view) {            Animation aa = AnimationUtils.loadAnimation(this, R.anim.alpha);            iv.startAnimation(aa);        }        /**         * 缩放动画         * @param view         */        public void scale(View view) {            Animation sa = AnimationUtils.loadAnimation(this, R.anim.scale);            iv.startAnimation(sa);        }        /**         * 位移动画         * @param view         */        public void Trans(View view) {            Animation ta = AnimationUtils.loadAnimation(this, R.anim.trans);            iv.startAnimation(ta);        }        /**         * 旋转动画         * @param view         */        public void rotate(View view) {            Animation ra = AnimationUtils.loadAnimation(this, R.anim.rotate);            iv.startAnimation(ra);        }        public void set(View view){            Animation set = AnimationUtils.loadAnimation(this, R.anim.set);            iv.startAnimation(set);        }    }

属性动画

    public class MainActivity extends Activity {        private ImageView iv;        @Override        protected void onCreate(Bundle savedInstanceState) {            super.onCreate(savedInstanceState);            setContentView(R.layout.activity_main);            iv = (ImageView) findViewById(R.id.iv);        }        /**         * 透明度         * @param view         */        public void alpha(View view){    //      iv.setAlpha(alpha);    //      iv.getAlpha()            ObjectAnimator oa = ObjectAnimator.ofFloat(iv, "alpha", 0.0f,0.2f,0.4f,0.6f,0.8f,1.0f);            oa.setDuration(4000);            oa.setRepeatMode(ObjectAnimator.REVERSE);            oa.setRepeatCount(ObjectAnimator.INFINITE);            oa.start();        }        /**         * 旋转动画         * @param view         */        public void rotate(View view){            //iv.setRotationY(rotationY)            ObjectAnimator oa = ObjectAnimator.ofFloat(iv, "rotationX", 0.0f,30f,60.0f,90f);            oa.setDuration(2000);            oa.setRepeatMode(ObjectAnimator.REVERSE);            oa.setRepeatCount(ObjectAnimator.INFINITE);            oa.start();        }        /**         * 缩放         * @param view         */        public void scale(View view){            //iv.setScaleX()            ObjectAnimator oa = ObjectAnimator.ofFloat(iv, "scaleY", 0.0f,0.2f,0.5f,2.0f);            oa.setDuration(2000);            oa.setRepeatMode(ObjectAnimator.REVERSE);            oa.setRepeatCount(ObjectAnimator.INFINITE);            oa.start();        }        /**         * 位移         * @param view         */        public void trans(View view){            //iv.setScaleX()            //iv.setTranslationX()            ObjectAnimator oa = ObjectAnimator.ofFloat(iv, "translationX", 0.0f,30f,60f,200f);            oa.setDuration(2000);            oa.setRepeatMode(ObjectAnimator.REVERSE);            oa.setRepeatCount(ObjectAnimator.INFINITE);            oa.start();        }        public void set(View view){            System.out.println("---");            //动画的集合            AnimatorSet set = new AnimatorSet();            ObjectAnimator oa = ObjectAnimator.ofFloat(iv, "rotation", 0.0f,30f,60.0f,90f);            oa.setDuration(4000);            ObjectAnimator oa2 = ObjectAnimator.ofFloat(iv, "translationX", 0.0f,10f,20,40f,60f,100f,200f,600f);            oa2.setDuration(2000);            //set.playSequentially(oa,oa2);            set.playTogether(oa,oa2);            set.start();        }    }

Fragment

res->layout

  • activity_main.xml

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical"    tools:context=".MainActivity" >    <FrameLayout        android:id="@+id/fl_container"        android:layout_width="fill_parent"        android:layout_weight="1"        android:layout_height="0dip" >    </FrameLayout>    <LinearLayout        android:layout_width="fill_parent"        android:layout_height="wrap_content"        android:background="#22000000"        android:orientation="horizontal" >        <Button            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:onClick="setting01"            android:text="蓝牙设置" />        <Button            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:onClick="setting02"            android:text="声音设置" />        <Button            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:onClick="setting03"            android:text="显示设置" />    </LinearLayout></LinearLayout>
  • blue_tooth_layout.xml

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical" >    <TextView        android:id="@+id/textView1"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:text="我是蓝牙设置" /></LinearLayout>
  • show_layout.xml

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical" >    <TextView        android:id="@+id/textView1"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:text="我是显示设置" /></LinearLayout>
  • sound_layout.xml

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical" >    <TextView        android:id="@+id/textView1"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:text="我是声音设置" /></LinearLayout>

    src->fragement

  • MainActivity.java

    public class MainActivity extends Activity {    private FragmentManager fm;    BlueToothFragment f1;    SoundFragment f2;    ShowFragment f3;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        fm = getFragmentManager();        initFragment();        //事务的概念        FragmentTransaction ft = fm.beginTransaction();        ft.replace(R.id.fl_container, f1);        ft.commit();//保证了 要么同时成功,要么同时失败    }    private void initFragment() {        f1 = new BlueToothFragment();        f2 = new SoundFragment();        f3 = new ShowFragment();    }    //蓝牙    public void setting01(View view) {        //事务的概念        FragmentTransaction ft = fm.beginTransaction();        ft.replace(R.id.fl_container, f1);        ft.commit();//保证了 要么同时成功,要么同时失败    }    //声音    public void setting02(View view) {        //事务的概念        FragmentTransaction ft = fm.beginTransaction();        ft.replace(R.id.fl_container, f2);        ft.commit();//保证了 要么同时成功,要么同时失败    }    //显示    public void setting03(View view) {        //事务的概念        FragmentTransaction ft = fm.beginTransaction();        ft.replace(R.id.fl_container, f3);        ft.commit();//保证了 要么同时成功,要么同时失败    }}
  • BlueToothFragment.java

    public class BlueToothFragment extends Fragment {    //显示Fragment的ui的    @Override    public View onCreateView(LayoutInflater inflater, ViewGroup container,            Bundle savedInstanceState) {        return inflater.inflate(R.layout.blue_tooth_layout, null);    }}
  • ShowFragment.java

    public class ShowFragment extends Fragment {    //显示Fragment的ui的    @Override    public View onCreateView(LayoutInflater inflater, ViewGroup container,            Bundle savedInstanceState) {        return inflater.inflate(R.layout.show_layout, null);    }}
  • SoundFragment.java

    public class SoundFragment extends Fragment {    //显示Fragment的ui的    @Override    public View onCreateView(LayoutInflater inflater, ViewGroup container,            Bundle savedInstanceState) {        return inflater.inflate(R.layout.sound_layout, null);    }}

接口回调

  • 不同模块之间传值需要用接口回调

    ToolBarUtil.java

     public class ToolBarUtil {    private List<TextView> mTextViews = new ArrayList<TextView>();    public void createToolBar(LinearLayout container, String[] toolBarTitleArr, int[] iconArr) {        for (int i = 0; i < toolBarTitleArr.length; i++) {            TextView tv = (TextView) View.inflate(container.getContext(), R.layout.inflate_toolbar_btn, null);            tv.setText(toolBarTitleArr[i]);            // 动态修改textView里面的drawableTop属性            tv.setCompoundDrawablesWithIntrinsicBounds(0, iconArr[i], 0, 0);            int width = 0;            int height = LinearLayout.LayoutParams.MATCH_PARENT;            LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(width, height);            //设置weight属性            params.weight = 1;            container.addView(tv, params);            //保存textView到集合中            mTextViews.add(tv);            //设置点击事件            final int finalI = i;            tv.setOnClickListener(new View.OnClickListener() {                @Override                public void onClick(View v) {                    //不同模块之间传值需要用接口回调                    //3.需要传值的地方.用接口对象调用接口方法,position = finalI                    mOnToolBarClickListener.onToolBarClick(finalI);                }            });        }    }    public void changeColor(int position) {        //还原所有的颜色        for (TextView tv : mTextViews) {            tv.setSelected(false);        }        mTextViews.get(position).setSelected(true);//通过设置selected属性,控制为选中效果    }    //1.创建接口和接口方法    public  interface  OnToolBarClickListener{        void onToolBarClick(int position);    }    //2.定义接口变量    OnToolBarClickListener mOnToolBarClickListener;    //4.暴露一个公共的方法    public void setOnToolBarClickListener(OnToolBarClickListener onToolBarClickListener) {        mOnToolBarClickListener = onToolBarClickListener;    }}

    MainActivity.java

    //为mToolBarUtil设置setOnToolBarClickListener监听mToolBarUtil.setOnToolBarClickListener(new ToolBarUtil.OnToolBarClickListener() {    @Override    //position = finalI    public void onToolBarClick(int position) {        mMainViewpager.setCurrentItem(position);    }});
0 0
原创粉丝点击