Android知识点——内容提供者和内容观察者ContentProvider ContentResolver

来源:互联网 发布:java 断点 编译后 存在 编辑:程序博客网 时间:2024/05/21 10:05

内容提供者的步骤

  1. 有一个应用程序,带一个私有的数据库,需求是暴露这个私有的数据库。
  2. 写ContentProvider的一个子类
  3. 定义匹配规则
    • 定义匹配器 UriMatcher
    • 定义匹配规则 mUriMatcher.addURI("com.itheima.db", "info", SUCCESS);
    • 参数解释:1.主机名 2.path 3.成功校验码
  4. 根据业务需求实现增删改查的方法
  5. 在清单文件中声明内容提供者节点
    <application节点下 <provider android:name = "要暴露数据的应用程序包名" android:authorities = "主机名">

模板代码:

        public Cursor query(Uri uri, String[] projection, String selection,        String[] selectionArgs, String sortOrder) {        int code = mUriMatcher.match(uri);        if (code == SUCCESS) {        SQLiteDatabase db = helper.getReadableDatabase();        Cursor cursor = db.query("info", projection, selection,    selectionArgs, null, null, sortOrder);return cursor;}else{throw new IllegalArgumentException("uri 不匹配");                }

短信的内容提供者

路径uri /data/data/com.android.telephony/databases/mmssms.db * 备份 public class MainActivity extends Activity {

    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);    }    /**     * 备份短信按钮点击事件     *      * @param v     */    public void btnOnclick(View v) {        try {            // xml序列化器            XmlSerializer serializer = Xml.newSerializer();            File file = new File(Environment.getExternalStorageDirectory(),                    "backup.xml");            FileOutputStream fos = new FileOutputStream(file);            // 初始化序列化器            serializer.setOutput(fos, "utf-8");            serializer.startDocument("utf-8", true);            // 得到内容解析器            ContentResolver resolver = getContentResolver();            Uri uri = Uri.parse("content://sms/");            Cursor cursor = resolver.query(uri, new String[] { "address",                    "body", "type", "date" }, null, null, null);            serializer.startTag(null, "smss");            while (cursor.moveToNext()) {                serializer.startTag(null, "sms");                serializer.startTag(null, "address");                String address = cursor.getString(cursor                        .getColumnIndex("address"));                serializer.text(address);                serializer.endTag(null, "address");                serializer.startTag(null, "body");                String body = cursor.getString(cursor.getColumnIndex("body"));                serializer.text(body);                serializer.endTag(null, "body");                serializer.startTag(null, "type");                String type = cursor.getString(cursor.getColumnIndex("type"));                serializer.text(type);                serializer.endTag(null, "type");                serializer.startTag(null, "date");                long date = cursor.getLong(cursor.getColumnIndex("date"));                serializer.text(String.valueOf(date));                serializer.endTag(null, "date");                Date date2 = new java.sql.Date(date);                System.out.println(address + "!" + body + "!" + type + "!"                        + date2);                serializer.endTag(null, "sms");            }            cursor.close();            serializer.endDocument();            Toast.makeText(this, "备份完成", Toast.LENGTH_SHORT).show();        } catch (IOException e) {            e.printStackTrace();            Toast.makeText(this, "备份失败", Toast.LENGTH_SHORT).show();        }    }
  • 还原
    解析xml

联系人的内容提供者

联系人的数据uri
data/data/com.android.providers.contacts/databases/contacts2.db 应用场景: 微信,支付宝

重要的三张表

  • data表 保存联系人的数据 表中 rwacontactid表示联系人id
  • rawcontacts表 保存联系人的id contactid
  • mimetypes表 保存联系人数据的类型

如何获取联系人

raw_contacts表的Uri:RawContacts.CONTENT_URIdata表的Uri:Data.CONTENT_URI
  1. 查询raw_contacts表,把联系人的id取出来
  2. 根据联系人的id,查询data表,把这个id的数据取出来
  3. 根据mimetype区分数据的类型

Android删除一个联系人后并不是将联系人删除而是将联系人的contact_id设置为null 此时注意程序会报空

添加联系人

  1. 添加raw_contacts表,添加一条联系人的id
  2. 操作data表,插入联系人的数据,每个联系人数据都对应一列 rawcontactid

内容观察者

观察内容的作用,当被观察的内容发生改变时会发出通知表示内容改变 
在某个需要被观察的项目中 getContent().getContentResolver().notifycation(uri,observer);
在观察者中 getContentResolver().registerContentObserver(uri,是否完全匹配,观察者);

实现步骤:

  1. 继承ContentObserver
  2. 实现默认构造方法
  3. 重写onChange()方法
    class MyObserver extends ContentObserver{

    public MyObserver(Handler handler) {    super(handler);    // TODO Auto-generated constructor stub}//数据改变时,收到通知时,调用onChange方法@Overridepublic void onChange(boolean selfChange) {    // TODO Auto-generated method stub    super.onChange(selfChange);}

    发送数据改变的方法:

    //参数1:注册内容提供者的uri 参数2:内容观察者对象  getContext().getContentResolver().notifyChange(Uri,Observer)

    这里要注意:发送数据改变通知的uri,也就是主机名,要和内容提供者中定义的uri相同,也就是哪个uri发送的就用哪个uri来注册

使用方法

  1. 获取内容观察者对象
  2. 注册内容观察者registerContentObserver(),参数:1.要观察的主机名 2.是否精确匹配,true只要以指定的uri开头的数据改变,都能收到通知。如果是false就必须是精确匹配uri才能收到通知,观察者对象。

    @Overrideprotected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    setContentView(R.layout.activity_main);    // content://com.itheima.db/info/103    Uri uri = Uri.parse("content://com.itheima.db/info/");    getContentResolver().registerContentObserver(uri, true, new MyObserver(new Handler()));}private class MyObserver extends ContentObserver{    public MyObserver(Handler handler) {//handler 是一个消息处理器。        super(handler);    }    @Override    public void onChange(boolean selfChange) {        System.out.println("哈哈数据库的内容变化了");        super.onChange(selfChange);    }} 
0 0
原创粉丝点击