ContentProvider的作用
为了给不同应用提供内容访问,实现不同应用之间的跨进程数据访问。
ContentProvider
封装了数据的跨进程传输,我们可以直接使用 getContentResolver()
拿到 ContentResolver
进行增删改查即可。
ContentProvider
以一个或多个表(与在关系型数据库中的表类似)的形式将数据呈现给外部应用。 行表示提供程序收集的某种数据类型的实例,行中的每个列表示为实例收集的每条数据。
通过ContentProvider获取其他应用的数据
先来看看如何通过ContentProvider获取数据吧
系统应用已经提供了一些必要的ContentProvider,比如相册/通讯录等等
通过ContentProvider获取通讯录
1.首先是权限问题,包括动态权限申请
读取联系人权限
<uses-permission android:name="android.permission.READ_CONTACTS" />
导入动态权限申请库
implementation 'com.github.tbruyelle:rxpermissions:0.10.2'
动态申请权限
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val rxPermissions = RxPermissions(this) rxPermissions.request(Manifest.permission.READ_CONTACTS)
.subscribe { granted ->
if (granted) { // Always true pre-M
// I can control the camera now
isPre = true
} else {
// Oups permission denied
}
}
}
2.获取通讯录数据
fun getContact() {
//拿到 contentResolver
val contentResolver = this.getContentResolver()
//路径
val uri = Uri.parse("content://com.android.contacts/contacts")
//查询
val cursor = contentResolver.query(uri, null, null, null, null)
while (cursor.moveToNext()) {
// 获取联系人姓名
val sb = StringBuilder()
val contactId = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID))
val name = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME))
sb.append("contactId=").append(contactId).append(",name=").append(name)
//获取联系人手机号码
val phones = contentResolver.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,
ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = " + contactId, null, null)
while (phones.moveToNext()) {
val phone = phones.getString(phones.getColumnIndex("data1"))
sb.append(",phone=").append(phone)
}
textView.setText(textView.text.toString()+sb.toString()+"\n")
}
}
可以看到分三步骤:
-
this.getContentResolver()
拿到ContentResolver
对象
2.val uri = Uri.parse("content://com.android.contacts/contacts")
配置uri
3.使用ContentResolver
查询,得到游标对象
4.通过游标获取数据。
分析
可以看到其实只是通过一个资源定位uri,就能拿到通讯录的数据库数据。当然这个uri是应用暴露给其他应用调用的。所以如果我们需要自己的程序暴露数据给外部,也可以
通过ContentProvider给其他应用分享数据
-
设计数据存储
1.选择文件还是数据库
2.如果您想提供 Bitmap 或其他庞大的文件导向型数据,请将数据存储在一个文件中,然后间接提供这些数据,而不是直接将其存储在表中
3.使用二进制大型对象 (BLOB) 数据类型存储大小或结构会发生变化的数据。 例如使用 BLOB 列来存储 JSON -
创建 ContentProvider 子类,实现关键方法
1.ContentProvider 实例通过处理来自其他应用的请求来管理对结构化数据集的访问
2.所有形式的访问最终都会调用 ContentResolver,后者接着调用 ContentProvider 的具体方法来获取访问权限
3.注意文章开头提到的避免耗时操作和线程安全
4.尽管必须实现这些方法,它们的返回值并不重要,只要返回符合要求的数据类型即可,即使不执行任何其他操作 -
定义提供程序的授权字符串(authority)、内容 URI 以及列名称
1.对应前面设计的数据库表名和字段名
2.如果想让内容提供者应用处理 Intent,则还要定义 Intent 操作、Extra 数据以及标志
3.还要定义想要访问该数据的应用必须具备的权限 - 通过 ContentResolver 和 URI 进行增删改查
下面实践一个(由于给其他应用分享数据实质上就是跨进程数据通信,这里为了方便把ContentProvider放在其他进程即可)
网友评论