ContentProvider简介
在Android中,可以通过文件存储、SharedPreferences和数据库这三种数据持久化技术来保存数据,但是这三种方式只能访问本应用的数据,如果要访问其他应用的数据,就需要使用ContentProvider。
ContentProvider是Android提供的跨程序共享数据的标准方式,主要用于在不同应用程序之间实现数据共享,它可以控制程序的一部分数据进行共享,另一部分数据不共享,从而保证程序的数据不会被泄露。
ContentProvider通常有两种使用方式,一种是访问其他程序提供的ContentProvider对其数据进行读取或操作,一种是在自己的应用程序创建ContentProvider,来向其它程序提供数据访问的接口。
访问其他程序的数据
ContentProvider的增删改查方法不接受表名,而是使用Uri参数,Uri参数由authority和path两部分组成,其中authority通常是应用程序包名,用来对区分不同的应用程序,path通常是表名,用来区分统一程序中不同的表。
URI通常和网址一样用字符串表示,所以在使用ContentProvider的增删改查方法时,需要使用Uri.parse()进行解析得到Uri对象。
URI标准格式:**协议名://authority/path
解析URI对象:Uri.parse(“协议名://authority/path”)
下面是通过ContentProvider查询系统联系人的代码。
class MainActivity : AppCompatActivity() {private var contacts = ArrayList<String>()lateinit var adapter: ArrayAdapter<String>override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)adapter = ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, contacts)contactsList.adapter = adapter// 读取系统联系人需要READ_CONTACTS权限if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS) == PackageManager.PERMISSION_DENIED) {ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.READ_CONTACTS), 1)} else {readContacts()}}override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {super.onRequestPermissionsResult(requestCode, permissions, grantResults)when (requestCode) {1 -> {if (permissions.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_DENIED) {Toast.makeText(this, "You Denied the Permission", Toast.LENGTH_SHORT).show()} else {readContacts()}}}}private fun readContacts() {// 使用getContentResolver获取ContentResolver对象,然后查询系统联系人contentResolver.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null, null, null, null)?.apply {// 通过游标访问查询到的数据while (moveToNext()) {val name = getString(getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME))val number = getString(getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER))contacts.add("$name\n$number")}adapter.notifyDataSetChanged()close()}}}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?><androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"><ListViewandroid:id="@+id/contactsList"android:layout_width="match_parent"android:layout_height="match_parent"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintRight_toRightOf="parent"app:layout_constraintTop_toTopOf="parent" /></androidx.constraintlayout.widget.ConstraintLayout>
创建ContentProvider供外部访问
创建ContentProvider的步骤
- 新建一个类继承自ContentProvider。
- 重写ContentProvider类的6个抽象方法。
- onCreate() 在初始化时调用,通常在这里完成数据库的创建和升级,返回值为true表示初始化成功,为false表示初始化失败。
- query()查询数据
- insert()插入数据,添加成功后,返回一个表示这条新纪录的URI。
- updata()更新数据
- delete()删除数据,被删除的行数将会作为返回值返回。
- getType()根据传入的内容URI返回相应的MIME类型。
