美文网首页
Android四大组件----ContentProvider详解

Android四大组件----ContentProvider详解

作者: 善笃有余劫 | 来源:发表于2018-07-23 21:18 被阅读12次

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")
        }
    }

可以看到分三步骤:

  1. this.getContentResolver()拿到ContentResolver对象
    2.val uri = Uri.parse("content://com.android.contacts/contacts")配置uri
    3.使用ContentResolver查询,得到游标对象
    4.通过游标获取数据。

分析

可以看到其实只是通过一个资源定位uri,就能拿到通讯录的数据库数据。当然这个uri是应用暴露给其他应用调用的。所以如果我们需要自己的程序暴露数据给外部,也可以

通过ContentProvider给其他应用分享数据

ContentProvider 的使用分为以下 4 步

  1. 设计数据存储
    1.选择文件还是数据库
    2.如果您想提供 Bitmap 或其他庞大的文件导向型数据,请将数据存储在一个文件中,然后间接提供这些数据,而不是直接将其存储在表中
    3.使用二进制大型对象 (BLOB) 数据类型存储大小或结构会发生变化的数据。 例如使用 BLOB 列来存储 JSON
  2. 创建 ContentProvider 子类,实现关键方法
    1.ContentProvider 实例通过处理来自其他应用的请求来管理对结构化数据集的访问
    2.所有形式的访问最终都会调用 ContentResolver,后者接着调用 ContentProvider 的具体方法来获取访问权限
    3.注意文章开头提到的避免耗时操作和线程安全
    4.尽管必须实现这些方法,它们的返回值并不重要,只要返回符合要求的数据类型即可,即使不执行任何其他操作
  3. 定义提供程序的授权字符串(authority)、内容 URI 以及列名称
    1.对应前面设计的数据库表名和字段名
    2.如果想让内容提供者应用处理 Intent,则还要定义 Intent 操作、Extra 数据以及标志
    3.还要定义想要访问该数据的应用必须具备的权限
  4. 通过 ContentResolver 和 URI 进行增删改查

下面实践一个(由于给其他应用分享数据实质上就是跨进程数据通信,这里为了方便把ContentProvider放在其他进程即可)

相关文章

网友评论

      本文标题:Android四大组件----ContentProvider详解

      本文链接:https://www.haomeiwen.com/subject/zklwpftx.html