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">
<ListView
android: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类型。