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

内容提供者的步骤

  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_URI
data表的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方法
    @Override
    public 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才能收到通知,观察者对象。

    @Override
    protected 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);
        }
    
    } 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值