ContentProvider知识总结
ContentProvider简介
我们之前学习的所有存储数据的介质,只是在当前程序中存储的。我们可否实现跨程序使用呢。Android官方推介给我们使用ContentProvider技术,
ContentProvider主要用于在不同的程序之间实现数据共享的功能,它提供了一套完整的机制,允许一个程序访问另一个程序中的数据,同时还能保证被访问数据的安全性。
运行时权限
Android系统在6.0的时候引入运行时权限这个功能,从而能够更好的保护用户的隐私。
1.用户在不低于Android6.0的设备上安装该程序,会在安装界面给出提醒。这样用户就能清楚的知晓程序申请了那些权限
2.用户可以随时查看任何一个程序的权限申请情况,以此保证应用程序不会出现各种滥用权限的情况。
运行时权限:用户不需要再安装软件的时候一次性授权所有的申请权限,而是在软件的使用过程中,对某一个功能进行授权。
Android系统现将权限分为两种:
普通权限:不会直接威胁到用户隐私安全的权限,对于这部分权限,系统会自动帮我们进行授权,不需要用户手动操作
危险权限:可能会触及用户隐私,以及对设备的安全性造成影响的权限,如获取设备联系人信息,定位设备的地理位置等等
下图是Android10系统所有的危险权限,一共是11组30个权限
我们要用的时候直接到表里面进行查询即可。
注意点:我们在进行运行时权限处理时使用的是权限名,原则上用户一旦同意了某个权限的申请之后,同组的其他权限也会被我们系统自动授权,但是谨记,不能使用其开发业务功能,因为Android系统随时有可能调整权限的分组。
在程序中申请权限
我们通过实战来看一下,在程序中申请权限的说明,首先创建一个RuntimePermissionTest项目,申请一个CALL_PHONE,
首先修改activity_main.xml文件,在里面添加一个拨号的按钮
然后在AndroidMainfest中添加拨打电话的权限:
然后编写MainActivity中的代码,
我们查看最后的运行效果,点击按钮之后,会触发申请权限。
访问其他程序中的数据
ContentProvider一般的用法用两种:
1.使用现有的ContentProvider读取和操作响应的程序中的数据,
2.创建自己的ContentProvider,给程序提供外部访问接口
ContentResolver的基本用法
首先通过Context中的getContentResolver()方法获取实例,ContentResolver,该类中提供了一系列的方法对数据进行增删查改的操作,类似于SQLite中的方法,但是又有一些区别。
区别是ContentReslover中的方法,没有传递表明,需要传递的是一个URI参数,这个参数唯一标识了,这个URI分为两部分组成,一部分是authority,另一部分是paht,authority对应的是应用程序的包名,path对应的是同一应用程序的不用表。
我们需要使用Uri.parse("uri")这个方法来将和这个URI解析成为Uri对象。
构建好了之后我们就可以使用Uri对象进行查询了,例如下面代码
val cursor = contentResolver.query( uri, projection, selection selectionArgs, sortOrder )
我们对参数进行说明:
查询完返回的是一个Cursor对象,这时候我们就可以将数据从Cursor中逐个读取出来了。读取的思路仍然是通过移动游标的位置便利Cursor所有行,代码如下:
点击查看代码
while(cursor.moveToNext) {
val colimn1 = cursor.getString(cursor.getColumnIndex("column1"))
val column2 = cursor.getInt(cursor.getColumnIndex("column2"))
}
cursor.close()
下面就是增删查改的案例:
点击查看代码
添加数据
val values = content ValuesOf("column1",to "text","column2" to 1)
contentResolver.insert(rui,values)
更新数据
val values - contentValueof("column1" to "")
contentResolver.update(uri,values,"column1=? and column2 = ?",arrayOf("text","1"))
删除数据
contentResolver.delete(uri,"column2 =?",arrayof("1"))
读取联系人
我们通过实践案例来感受一下,一个程序来读取系统联系人。
我们首先创建一个ContactsTest项目,先在activity_main.xml里面增加一个ListView用来展示联系人信息
其次我们重点放在MainActicity里面,
最后有最重要的一点是,在AndroidMainfest里面添加权限:
我们运行程序后发现可以拿到数据。
创建自己的ContentProvider
实现跨程序共享数据功能,可以通过新建一个类去继承ContentProvider的方式来实现
创建ContentProvider的步骤
我们要实现跨程序共享数据,需要继承ContentProvider的方式来实现,所以我们查看ContentProvider类中的6个抽象方法
点击查看代码
package com.example.contactstest
import android.content.ContentProvider
import android.content.ContentValues
import android.database.Cursor
import android.net.Uri
class MyProvider : ContentProvider() {
override fun onCreate(): Boolean {
//初始化ContentProvider的时候使用,通常会在这里完成对数据库的创建和升级等操作。 返回TRUE表示初始化成功,返回FALSE表示初始化失败
TODO("Not yet implemented")
}
override fun query(
uri: Uri,
projection: Array<out String>?,
selection: String?,
selectionArgs: Array<out String>?,
sortOrder: String?
): Cursor? {
/*从ContentProvider中查询数据,uri参数要确定查询添加列表,
projection用于确定查询哪个列
selection和selectionArgs用于约束查询哪些行
sortOrder参数用于对结果进行排序
*/
TODO("Not yet implemented")
}
//根据传入的类型返回响应的MIME类型
override fun getType(p0: Uri): String? {
TODO("Not yet implemented")
}
override fun insert(p0: Uri, p1: ContentValues?): Uri? {
TODO("Not yet implemented")
/*
向ContentProvider中添加一条数据,uri参数用于确定要添加的表,待添加的数据保存在values中,
添加成功之后返回一个新的Uri
*/
}
override fun delete(p0: Uri, p1: String?, p2: Array<out String>?): Int {
TODO("Not yet implemented")
/*
从ContentProvider中删除数据,uri参数用于确定删除哪一张表中的数据p1和p2用于约束删除哪些行m被删除的行数据作为返回值
*/
}
override fun update(p0: Uri, p1: ContentValues?, p2: String?, p3: Array<out String>?): Int {
TODO("Not yet implemented")
/*
更新ContentProvider中已有的数据,Uri参数用于确定要更新哪一张表中的数据,新数据保存在value参数中,
selection和selectionArgs参数用于约束更新哪些行,受影响的行数作为返回值返回
*/
}
}
再来看关于URI的一些技巧,标准的URI的写法是,
content://com.example.app.provider/table/1 表示期望访问的是com.example.app这个应用的table表中id为1的数据,
内容URI的格式主要就只有以上两种,
1.以路径结尾表示期望访问该表中所有的数据
2.以id结尾表示期望访问该表中拥有相应id的数据
我们可以使用通配符匹配这两种格式的内容
*表示匹配任意长度的任意字符
表示匹配任意长度的数字
所以表示能够匹配任意表的内容URI格式就可以写成:
content://con.example.app.provider/table/*
一个能够匹配table表中任意一行数据内容的URI
content://com.example.app.provider/table/#
我们借助UriMatcher这个类可以轻松实现匹配内容URI的功能。
实现跨程序数据共享
我们首先在上一章中的DatabaseTest项目基础上继续开发,我们首先创建一个DatabaseProvider
然后在AndroidMainfest.xml文件中注册ContentProivider
最后修改一下布局activit_main.xml中
最后编写MainActivity里面的监听事件:
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)