一看就会系列Android之ContentProvider实现数据共享及注册监听



       当一个应用程序需要把自己的数据暴露给其他程序使用时,该应用程序就可以通过ContentPrivade来实现,ContentPrivade以某种Uri的形式对外提供数据,从而允许其他应用通过ContentResolver来访问或者修改数据。

如何完整的开发一个ContentProvider呢,步骤如下:
1. 定义一个继承ContentProvider基类的子类,并重写其他应用操作ContentProvider暴露数据的增删改查方法  ----  由此我们可以看出所谓的ContentProvider暴露数据的方式其实就是在自身中为其他应用提供操作自己数据的增删改查方法。
此处在ContentProvider子类中的增删改查方法只是重写,重写的意思就是方法参数只提供形参,真正的实参是通过ContentResolver进行“间接调用”时ContentResolver的增删改查方法所提供的参数。
2. 向Android系统注册这个网站,也就是在功能清单文件中注册这个ContentProvider,类似于注册activity,注册时需要为他设置一个Uri,
元素下进行如下配置:
   
Authorities:为该ContentProvider指定Uri
Exported:指定是否允许被其他应用访问,true代表允许
3. 通过上面的注册之后其他应用就可通过此Uri来操作ContentProvider所暴露的数据了,操作的本质就是调用ContentProvider提供的增删改查方法,另外不管是ContentProvider的增删改查方法还是ContentResolver的增删改查方法其中的第一个参数都为Uri,所以这里对Uri格式作如下强调:
ContentProvider要求Uri的格式如下:
Content://org.gpf.providers.dictprovider/words
Content://:这个是Android的ContentProvider规定的默认访问协议,就像上网的协议http://一样,不可更改。
org.gpf.providers.dictprovider:这个部分就是在功能清单文件中注册的ContentProvider的authorities属性值(见第二步)。
Words:资源部分(或者叫数据部分),这个部分可以动态改变
几种常见的Uri的代表含义:
Content://org.gpf.providers.dictprovider/words
代表:访问word数据表中全部数据
Content://org.gpf.providers.dictprovider/words/2
代表:访问word数据表中ID为2的记录
Content://org.gpf.providers.dictprovider/words/2/word
代表:访问word数据表中ID为2的记录的word字段
上面的Uri路径都只是字符串类型的,为了将其转成Uri,Uri类提供了Parse()静态方法,如下:
Uri  uri = Uri.parse(“Content://org.gpf.providers.dictprovider/words/2”);
使用ContentResolver操作数据的步骤:
1. 在activity中调用Context的getContentResolver()方法获取ContentResolver对象
2. 根据需要调用ContentResolver的增删改查方法来操作ContentProvider暴露的数据,如ContentResolver.insert(),同时在操作ContentProvider暴露数据时必须要了解该ContentProvider的Uri以及ContentProvider所操作的数据列的列名,这些对于自定义的ContentProvider是已知的,但对于系统提供的ContentProvider都需要查询相关文档来获得。
总结ContentResolver如何实现”间接调用,参数传递” ContentProvider的CRUD方法:
间接调用:ContentResolver对象调用具体的增删改查方法时,Android系统会根据这些方法的第一个Uri参数找到对应的ContentProvider,然后调用ContentProvider的具体实现来操作数据,即ContentResolver对象调用具体的增删改查方法时其实就是调用了Uri指定的ContentProvider中定义的增删改查方法。
参数传递:在间接调用的过程中,ContentResolver的增删改查方法的实参将根据指定的Uri传递给ContentProvider的增删改查方法的形参,所以又可以这样理解:
ContentProvider的增删改查方法作用是操作数据
ContentResolver的增删改查方法是提供数据完成间接调用时的数据传入
ContentProvider的onCreate()方法:
ContentProvider只有一个onCreate()生命周期的方法,当其他应用通过ContentResolver第一次访问该ContentProvider时,onCreate方法会被回调,此外onCreate()方法只会被回调一次。
使用ContentProvider操作数据的安全性:
通过以上分析我们知道,虽然其他应用可以通过ContentResolver来操作某一个ContentProvider,但是在具体执行CRUD操作时本质还是调用ContentProvider提供的方法,这样一来其他应用操作暴露数据时就必须服从ContentProvider开发人员编写的具体实现方法中的一些条件,即实现规则的制定依然属于ContentProvider方,如果是传统的开放权限方式操作数据那么ContentResolver端可以随心所欲的添加修改和删除ContentProvider端的所有数据,这样一来就显得很不安全,所以最新API推荐使用ContentProvider来实现数据共享。
Android系统提供的一些ContentProvider的Uri列举如下:
1. ContactsContract.Contacts.CONTENT_URI
:管理联系人的Uri
2.ContactsContract.CommonDataKinds.Phone.CONTENT_URI
:管理联系人电话的Uri
3.ContactsContract.CommonDataKinds.Email.CONTENT_URI
:管理联系人email的Uri
4.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
:存储在外部存储器(SD卡)上的音频文件
5.MediaStore.Audio.Media.INTERNAL_CONTENT_URI
:存储在手机内部存储器上的音频文件
6.MediaStore.Images.Media.EXTERNAL_CONTENT_URI
:存储在外部存储器(SD卡)上的图片文件
7.MediaStore.Images.Media.INTERNAL_CONTENT_URI
:存储在手机内部存储器上的图片文件
8.MediaStore.Video.Media.EXTERNAL_CONTENT_URI
:存储在外部存储器(SD卡)上的视频文件
9.MediaStore.Video.Media.INTERNAL_CONTENT_URI
:存储在手机内部存储器上的视频文件
------有了这些Uri,当我们要获取SD卡上的所有音频或者图片文件时就不用去便利SD上的所有文件了,可以直接使用ContentResolver即可获取到所有的信息。
监听ContentProvider的数据改变:
例如:A(微信)和B(联系人)两个应用实现了收据共享,现在新添加了一位联系人,当我们再打开微信时系统就会提示:有新用户添加。
要实现对ContentProvider数据改变的监听需利用ContentObserver:
使用步骤大体如下:
1.创建ContentObserver的子类,并重写onChange方法,该方法在ContentProvider数据发生变化时被触发。
2.使用ContentResolver对象来为指定Uri注册监听器,其实就是为指定的ContentProvider注册监听器,常用registerContentObserver(Uri uri,Boolean flag, ContentObserver conobs):
参数1:指定ContentProvider的Uri,注意是加协议的全写形式
参数2:如果设置为true,假如注册的Uri为content://abc,那么uri为content://abc/ayz, content://abc/aaa的数据改变时也会触发监听器,如果设置为false,假如注册的uri为content://abc,那么只有content://abc的数据发生改变时才会触发该监听器。
参数3:监听器的类实例
如下:
getContentResolver().registerContentObserver(Uri.parse(“content://abc”),true,new SmsObserver(new Handler()));
--------- SmsObserver就是ContentObserver的子类。

你可能感兴趣的:(Android)