内容提供者ContentProvider和内容观察者ContentObserver的使用

ContentProvider 内容提供者

当应用继承ContentProvider类,并重写该类用于提供数据和存储数据的方法,就可以向其他应用共享其数据。虽然使用其他方法也可以对外共享数据,但数据访问方式会因数据存储的方式而不同,如:
采用文件方式对外共享数据,需要进行文件操作读写数据;
采用SharedPreferences共享数据,需要使用SharedPreferences API读写数据。而使用ContentProvider共享数据的好处是统一了数据访问方式。
Uri的结构

  • 1:schema,用来说明一个ContentProvider控制这些数据。 “content://”
  • 2:主机名或授权(Authority),它定义了是哪个ContentProvider提供这些数据。
  • 3:path路径,URI下的某一个Item。
  • 4:ID, 通常定义Uri时使用”#”号占位符代替, 使用时替换成对应的数字
    “content://com.itheima.provider/person/#” #表示数据id(#代表任意数字)
    “content://com.itheima.provider/person/来匹配任意文本

UriMatcher类使用介绍

用于匹配URI,相当于定义一些可以供其他应用访问的URI:比如增加,删除,查询等等操作的URI

ContentUris类使用介绍

ContentUris类用于获取Uri路径后面的ID部分,它有两个比较实用的方法:

  • withAppendedId(uri, id)用于为路径加上ID部分:

    Uri uri = Uri.parse("content://cn.itcast.provider.personprovider/ person")
    Uri resultUri = ContentUris.withAppendedId(uri, 10); 
    //生成后的Uri为:content://cn.itcast.provider.personprovider/person/10
    
  • parseId(uri)方法用于从路径中获取ID部分:

    Uri uri = Uri.parse("content://cn.itcast.provider.personprovider/person/10")
    long personid = ContentUris.parseId(uri);//获取的结果为:10
    
  • 另外Uri类中还有一个静态方法

    withAppendedPath(baseUri, pathSegment)也可以在某个路径上继续添加路径:
    Uri uri = Uri.parse("content://cn.itcast.provider.personprovider/person")
    Uri resultUri = Uri.withAppendedPath(uri, “update”);
    // 生成后的Uri为: content://cn.itcast.provider.personprovider/person/update
    

如何使用内容提供者:

android系统中有很多内容提供者,比如:短信通话记录联系人等等

开发中用的比较多的是调用别人提供好的内容提供者:
比如:想查询系统中所有的短信,或者删除一条短信, 
再如获取通话记录,删除通话记录等,都可以通过系统提供的内容提供者完成

以查询短信为例-调用步骤:

  • 1.获取要调用的uri:例如要查所有短信的uri是:content://sms/
  • 2.获取内容提供者访问对象
  • 3.开始查询,获取数据
  • 代码如下

    //1.得到uri对象
    Uri uri = Uri.parse("content://sms/");
    //2.获取内容提供者访问对象
    ContentResolver resolver = getContentResolver();
    //3.开始查询
    Cursor cursor = resolver.query(uri, new String[] { "body", "address","date", "type" }, null, null, null);
    //解析数据
    if (cursor != null && cursor.getCount() > 0) {
        listSmsInfo = new ArrayList<SmsInfoBean>();
        while (cursor.moveToNext()) {
            SmsInfoBean sms = new SmsInfoBean(cursor.getString(0),
                    cursor.getString(1), cursor.getLong(2),
                    cursor.getInt(3));
            listSmsInfo.add(sms);
        }
        cursor.close();
    }
    

项目中有如下需求:

  • 当某个特定的号码打电话过来,想立即挂断电话(由于挂断后,会产生一个未接记录)
    需要删除该记录,不让用户察觉有电话打过来,如何实现?

这就涉及到另一概念:内容观察者ContentObserver

利用内容观察者,我们可以观察某个内容提供者中的数据是否发生变化。

上面所提需求可以这样做:

  • 在通话记录的内容提供者上注册一个内容观察者,当发现数据发生变化时,通过内容提供者删除指定号码的通话记录

    //电话状态监听
    private class MyListener extends PhoneStateListener{
    
    @Override
    public void onCallStateChanged(int state, String incomingNumber) {
        switch (state) {
        case TelephonyManager.CALL_STATE_RINGING://零响状态。
            String result = dao.findMode(incomingNumber);
            if("1".equals(result)||"3".equals(result)){
                Log.i(TAG,"挂断电话。。。。");
                //观察通话记录的数据库,删除通话记录
                Uri uri = Uri.parse("content://call_log/calls/");
                ContentResolver resolver = getContentResolver();
                resolver.registerContentObserver(uri, true, new CallLogOberver(new Handler(),resolver,incomingNumber));
                endCall();
            }
            break;
        }
        super.onCallStateChanged(state, incomingNumber);
    }
    

    }

    //通话记录的内容观察者
    class CallLogOberver extends ContentObserver{
    private ContentResolver resolver;
    private String incomingNumber;
    public CallLogOberver(Handler handler,ContentResolver resolver,String number) {
        super(handler);
        this.resolver = resolver;
        this.incomingNumber = number;
    }
    
    /**
     * 当通话记录的数据库发生变化时回调
     */
    @Override
    public void onChange(boolean selfChange) {
        //通话记录的Uri
        Uri uri = Uri.parse("content://call_log/calls/");
        resolver.delete(uri, "number=?", new String[]{incomingNumber});
    }
    

    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值