1、动态申请权限
<uses-feature
android:name="android.hardware.telephony"
android:required="false" />
<uses-permission android:name="android.permission.CALL_PHONE" />
package com.jpc.contentprovidertest
import android.content.Intent
import android.content.pm.PackageManager
import android.net.Uri
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button
import android.widget.Toast
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
/**
* 运行时权限的核
* 心就是在程序运行过程中由用户授权我们去执行某些危险操作,程序是不可以擅自做主去执行
* 这些危险操作的。因此,第一步就是要先判断用户是不是已经给过我们授权了,借助的是
* ContextCompat.checkSelfPermission()方法。checkSelfPermission()方法接收两
* 个参数:第一个参数是Context,这个没什么好说的;第二个参数是具体的权限名,比如打电
* 话的权限名就是Manifest.permission.CALL_PHONE。然后我们使用方法的返回值和
* PackageManager.PERMISSION_GRANTED做比较,相等就说明用户已经授权,不等就表示用
* 户没有授权。
* 如果已经授权的话就简单了,直接执行拨打电话的逻辑操作就可以了,这里我们把拨打电话的
* 逻辑封装到了call()方法当中。如果没有授权的话,则需要调用
* ActivityCompat.requestPermissions()方法向用户申请授权。
* requestPermissions()方法接收3个参数:第一个参数要求是Activity的实例;第二个参数
* 是一个String数组,我们把要申请的权限名放在数组中即可;第三个参数是请求码,只要是唯
* 一值就可以了,这里传入了1。
*
*/
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val makeCall = findViewById<Button>(R.id.btn_make_call)
makeCall.setOnClickListener {
if (ContextCompat.checkSelfPermission(this,
android.Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this,
arrayOf(android.Manifest.permission.CALL_PHONE), 1)
} else {
call()
}
}
}
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>,
grantResults: IntArray
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
when(requestCode) {
1 -> {
if(grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
call()
}else{
Toast.makeText(this, "你拒绝了该权限申请", Toast.LENGTH_SHORT).show()
}
}
}
}
private fun call(){
try {
val intent = Intent(Intent.ACTION_CALL)
intent.data = Uri.parse("tel:10086")
startActivity(intent)
}catch (e: SecurityException){
e.printStackTrace()
}
}
}
2、读取手机联系人
<uses-permission android:name="android.permission.READ_CONTACTS"/>
package com.jpc.contentprovidertest
import android.app.Activity
import android.content.Intent
import android.content.pm.PackageManager
import android.net.Uri
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.provider.ContactsContract
import android.widget.ArrayAdapter
import android.widget.Button
import android.widget.ListView
import android.widget.Toast
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
class MainActivity : AppCompatActivity() {
private val contactsList = ArrayList<String>()
private lateinit var adapter: ArrayAdapter<String>
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
adapter = ArrayAdapter(this, android.R.layout.simple_list_item_1, contactsList)
val listView = findViewById<ListView>(R.id.contacts_view)
listView.adapter = adapter
if(ContextCompat.checkSelfPermission(this, android.Manifest.permission.READ_CONTACTS)
!= PackageManager.PERMISSION_GRANTED){
ActivityCompat.requestPermissions(this, arrayOf(android.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(grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
call()
}else{
Toast.makeText(this, "你拒绝了该权限申请", Toast.LENGTH_SHORT).show()
}
}
}
}
private fun readContacts() {
// 查询联系人数据
// ContactsContract.CommonDataKinds.Phone类已经帮我们做好了封装,提供了一个
//CONTENT_URI常量,而这个常量就是使用Uri.parse()方法解析出来的结果
contentResolver.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null, null,null)
?.apply {
while (moveToNext()){
// 获取联系人姓名
val name = getString(getColumnIndexOrThrow(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME))
val phone = getString(getColumnIndexOrThrow(ContactsContract.CommonDataKinds.Phone.NUMBER))
contactsList.add("$name\n$phone")
}
// 通知并刷新ListView
adapter.notifyDataSetChanged()
close() // 关闭Cursor对象
}
}
}
3、创建自己的ContentProvider
class MyProvider : ContentProvider() {
override fun onCreate(): Boolean {
return false
}
override fun query(uri: Uri, projection: Array<String>?, selection: String?,
selectionArgs: Array<String>?, sortOrder: String?): Cursor? {
return null
}
override fun insert(uri: Uri, values: ContentValues?): Uri? {
return null
}
override fun update(uri: Uri, values: ContentValues?, selection: String?,
selectionArgs: Array<String>?): Int {
return 0
}
override fun delete(uri: Uri, selection: String?, selectionArgs: Array<String>?): Int {
return 0
}
override fun getType(uri: Uri): String? {
return null
}
}
(1) onCreate()。初始化ContentProvider的时候调用。通常会在这里完成对数据库的创建和升级等操作,返回true表示ContentProvider初始化成功,返回false则表示失败。
(2) query()。从ContentProvider中查询数据。uri参数用于确定查询哪张表,projection参数用于确定查询哪些列,selection和selectionArgs参数用于约束查询哪些行,sortOrder参数用于对结果进行排序,查询的结果存放在Cursor对象中返回。
(3) insert()。向ContentProvider中添加一条数据。uri参数用于确定要添加到的表,待添加的数据保存在values参数中。添加完成后,返回一个用于表示这条新记录的URI。
(4) update()。更新ContentProvider中已有的数据。uri参数用于确定更新哪一张表中的数据,新数据保存在values参数中,selection和selectionArgs参数用于约束更新哪些行,受影响的行数将作为返回值返回。
(5) delete()。从ContentProvider中删除数据。uri参数用于确定删除哪一张表中的数据,selection和selectionArgs参数用于约束删除哪些行,被删除的行数将作为返回值返回。
(6) getType()。根据传入的内容URI返回相应的MIME类型。
一个标准的内容URI写法是:
content://com.example.app.provider/table1
这就表示调用方期望访问的是com.example.app这个应用的table1表中的数据。
除此之外,我们还可以在这个内容URI的后面加上一个id,例如:
content://com.example.app.provider/table1/1
这就表示调用方期望访问的是com.example.app这个应用的table1表中id为1的数据。
内容URI的格式主要就只有以上两种,以路径结尾表示期望访问该表中所有的数据,以id结尾表示期望访问该表中拥有相应id的数据。我们可以使用通配符分别匹配这两种格式的内容URI,规则如下。
- *表示匹配任意长度的任意字符。
- #表示匹配任意长度的数字。
所以,一个能够匹配任意表的内容URI格式就可以写成:
content://com.example.app.provider/*
一个能够匹配table1表中任意一行数据的内容URI格式就可以写成:文章来源:https://www.toymoban.com/news/detail-845989.html
content://com.example.app.provider/table1/#
再借助UriMatcher这个类就可以轻松地实现匹配内容URI的功能。UriMatcher中提供了一个addURI()方法,这个方法接收3个参数,可以分别把authority、path和一个自定义代码传进去。这样,当调用UriMatcher的match()方法时,就可以将一个Uri对象传入。文章来源地址https://www.toymoban.com/news/detail-845989.html
class MyProvider : ContentProvider() {
private val table1Dir = 0
private val table1Item = 1
private val table2Dir = 2
private val table2Item = 3
private val uriMatcher = UriMatcher(UriMatcher.NO_MATCH)
init {
uriMatcher.addURI("com.example.app.provider", "table1", table1Dir)
uriMatcher.addURI("com.example.app.provider ", "table1/#", table1Item)
uriMatcher.addURI("com.example.app.provider ", "table2", table2Dir)
uriMatcher.addURI("com.example.app.provider ", "table2/#", table2Item)
}
...
override fun query(uri: Uri, projection: Array<String>?, selection: String?,
selectionArgs: Array<String>?, sortOrder: String?): Cursor? {
when (uriMatcher.match(uri)) {
table1Dir -> {
// 查询table1表中的所有数据
}
table1Item -> {
// 查询table1表中的单条数据
}
table2Dir -> {
// 查询table2表中的所有数据
}
table2Item -> {
// 查询table2表中的单条数据
}
}
...
}
...
}
class MyProvider : ContentProvider() {
...
override fun getType(uri: Uri) = when (uriMatcher.match(uri)) {
table1Dir -> "vnd.android.cursor.dir/vnd.com.example.app.provider.table1"
table1Item -> "vnd.android.cursor.item/vnd.com.example.app.provider.table1"
table2Dir -> "vnd.android.cursor.dir/vnd.com.example.app.provider.table2"
table2Item -> "vnd.android.cursor.item/vnd.com.example.app.provider.table2"
else -> null
}
}
4、实战
class DatabaseProvider : ContentProvider() {
private val bookDir = 0
private val bookItem = 1
private val categoryDir = 2
private val categoryItem = 3
private val authority = "com.example.databasetest.provider"
private var dbHelper: MyDatabaseHelper? = null
private val uriMatcher by lazy {
val matcher = UriMatcher(UriMatcher.NO_MATCH)
matcher.addURI(authority, "book", bookDir)
matcher.addURI(authority, "book/#", bookItem)
matcher.addURI(authority, "category", categoryDir)
matcher.addURI(authority, "category/#", categoryItem)
matcher
}
override fun onCreate() = context?.let {
dbHelper = MyDatabaseHelper(it, "BookStore.db", 2)
true
} ?: false
www.blogss.cn
override fun query(uri: Uri, projection: Array<String>?, selection: String?,
selectionArgs: Array<String>?, sortOrder: String?) = dbHelper?.let {
// 查询数据
val db = it.readableDatabase
val cursor = when (uriMatcher.match(uri)) {
bookDir -> db.query("Book", projection, selection, selectionArgs,
null, null, sortOrder)
bookItem -> {
val bookId = uri.pathSegments[1]
db.query("Book", projection, "id = ?", arrayOf(bookId), null, null,
sortOrder)
}
categoryDir -> db.query("Category", projection, selection, selectionArgs,
null, null, sortOrder)
categoryItem -> {
val categoryId = uri.pathSegments[1]
db.query("Category", projection, "id = ?", arrayOf(categoryId),
null, null, sortOrder)
}
else -> null
}
cursor
}
override fun insert(uri: Uri, values: ContentValues?) = dbHelper?.let {
// 添加数据
val db = it.writableDatabase
val uriReturn = when (uriMatcher.match(uri)) {
bookDir, bookItem -> {
val newBookId = db.insert("Book", null, values)
Uri.parse("content://$authority/book/$newBookId")
}
categoryDir, categoryItem -> {
val newCategoryId = db.insert("Category", null, values)
Uri.parse("content://$authority/category/$newCategoryId")
}
else -> null
}
uriReturn
}
override fun update(uri: Uri, values: ContentValues?, selection: String?,
selectionArgs: Array<String>?) = dbHelper?.let {
// 更新数据
val db = it.writableDatabase
val updatedRows = when (uriMatcher.match(uri)) {
bookDir -> db.update("Book", values, selection, selectionArgs)
bookItem -> {
val bookId = uri.pathSegments[1]
db.update("Book", values, "id = ?", arrayOf(bookId))
}
categoryDir -> db.update("Category", values, selection, selectionArgs)
categoryItem -> {
val categoryId = uri.pathSegments[1]
db.update("Category", values, "id = ?", arrayOf(categoryId))
}
else -> 0
}
updatedRows
} ?: 0
override fun delete(uri: Uri, selection: String?, selectionArgs: Array<String>?)
= dbHelper?.let {
// 删除数据
www.blogss.cn
val db = it.writableDatabase
val deletedRows = when (uriMatcher.match(uri)) {
bookDir -> db.delete("Book", selection, selectionArgs)
bookItem -> {
val bookId = uri.pathSegments[1]
db.delete("Book", "id = ?", arrayOf(bookId))
}
categoryDir -> db.delete("Category", selection, selectionArgs)
categoryItem -> {
val categoryId = uri.pathSegments[1]
db.delete("Category", "id = ?", arrayOf(categoryId))
}
else -> 0
}
deletedRows
} ?: 0
override fun getType(uri: Uri) = when (uriMatcher.match(uri)) {
bookDir -> "vnd.android.cursor.dir/vnd.com.example.databasetest.provider.book"
bookItem -> "vnd.android.cursor.item/vnd.com.example.databasetest.provider.book"
categoryDir -> "vnd.android.cursor.dir/vnd.com.example.databasetest.
provider.category"
categoryItem -> "vnd.android.cursor.item/vnd.com.example.databasetest.
provider.category"
else -> null
}
}
到了这里,关于Android ContentProvider基础知识学习笔记的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!