【安卓跨程序共享数据,探究ContentProvider】

ContentProvider主要用于在不同的应用程序之间实现数据共享的功能,它提供了一套完整的机制,允许一个程序访问另一个程序中的数据,同时还能保证被访问数据的安全性。
目前,使用ContentProvider是Android实现跨程序共享数据的标准方式。

Android系统的权限机制设计得非常简单,就是用户如果认可你所申请的权限,就会安装你的程序,如果不认可你所申请的权限,那么拒绝安装就可以了。

而在Android 6.0系统中新增了运行时权限功能。

现在用户不需要在安装软件的时候一次性授权所有申请的权限,而是可以在软件的使用过程中再对某一项权限申请进行授权。

比如一款相机应用在运行时申请了地理位置定位权限,就算拒绝了这个权限,也应该可以使用这个应用的其他功能,而不是像之前那样直接无法安装它。
在这里插入图片描述

class MainActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)makeCall.setOnClickListener {if (ContextCompat.checkSelfPermission(this,  Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) {ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.CALL_PHONE), 1)} else {call()}}}override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {super.onRequestPermissionsResult(requestCode, permissions, grantResults)when (requestCode) {1 -> {if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {call()} else {Toast.makeText(this, "You denied the permission", 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()}}}

ContentResolver的基本用法

ContentResolver中的增删改查方法都不接收表名参数,而是使用一个Uri参数代替,这个参数被称为内容URI。

内容URI给ContentProvider中的数据建立了唯一标识符,它主要由两部分组成:authority和path。

内容URI最标准的格式如下:
content://com.example.app.provider/table1
content://com.example.app.provider/table2
得到了内容URI字符串之后,我们只需要调用Uri.parse()方法,就可以将内容URI字符串解析成Uri对象了。
val uri = Uri.parse(“content://com.example.app.provider/table1”)

读取系统联系人
读取系统联系人示例写法如下(省略了申请运行时权限部分):

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)contactsView.adapter = adapter……readContacts()}……private fun readContacts() {// 查询联系人数据contentResolver.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null, null, null)?.apply {while (moveToNext()) {// 获取联系人姓名val displayName = getString(getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME))// 获取联系人手机号val number = getString(getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER))contactsList.add("$displayName\n$number")}adapter.notifyDataSetChanged()close()}}
}

在这里插入图片描述
创建ContentProvider的步骤:
ContentProvider类中有6个抽象方法,我们在使用子类继承它的时候,需要将这6个方法全部重写。

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

创建ContentProvider的步骤:

onCreate() .初始化ContentProvider的时候调用,通常会在这里完成对数据库的创建和升级等操作,返回true表示ContentProvider初始化成功,返回false则表示失败。
query () 从contentrovider中查询数据,uri参数用于确定查询那张表,projection 参数用于确定查询那些列,selection和selectionArgs参数用于约束查询哪些行,sortOrder参数用于对结果进行排序,查询的结果存放在Cursor对象中返回。

insert()。向ContentProvider中添加一条数据。uri参数用于确定要添加到的表,待添加的数据保存在values参数中。添加完成后,返回一个用于表示这条新记录的URI。

update()。更新ContentProvider中已有的数据。uri参数用于确定更新哪一张表中的数据,新数据保存在values参数中,selection和selectionArgs参数用于约束更新哪些行,受影响的行数将作为返回值返回。

delete()。从ContentProvider中删除数据。uri参数用于确定删除哪一张表中的数据,selection和selectionArgs参数用于约束删除哪些行,被删除的行数将作为返回值返回。

getType()。根据传入的内容URI返回相应的MIME类型。

实现跨进程数据共享:

借助UirMatcher 这个类能够实现匹配内容URi的功能。
当调用UriMaticher的match()方法时,可以将一个Uri对象传入,返回值是某个能够匹配这个Uri对象所对应的自定义代码,利用这个代码,就可以判断出调用方期望访问的是哪个表中的数据了:

class MyProvider : ContentProvider() {private val table1Dir = 0private val table1Item = 1private val table2Dir = 2private val table2Item = 3private 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表中的单条数据}}}}

实现跨程序数据共享

getType()方法是所有的ContentProvider都必须提供的一个方法,用于获取Uri对象所对应的MIME类型。一个内容URI所对应的MIME字符串主要由3部分组成,Android对这3个部分做了如下格式规定

必须以vnd开头。

如果内容URI以路径结尾,则后接android.cursor.dir/;如果内容URI以id结尾,则后接android.cursor.item/。

最后接上vnd..

所以,对于content://com.example.app.provider/table1这个内容URI,它所对应的MIME类型就可以写成:vnd.android.cursor.dir/vnd.com.example.app.provider.table1

对于content://com.example.app.provider/table1/1这个内容URI,它所对应的MIME类型就可以写成:vnd.android.cursor.item/vnd.com.example.app.provider.table1

实现跨进程数据共享在这里插入代码片
getType()方法中的逻辑,如下所示:

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/455567.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【机器学习与自然语言处理】预训练 Pre-Training 各种经典方法的概念汇总

【NLP概念合集&#xff1a;一】预训练 Pre-Training&#xff0c;微调 Fine-Tuning 及其方法的概念区别 前言请看此正文预训练 Pre-Training无监督学习 unsupervised learning概念&#xff1a;标签PCA 主成分分析&#xff08;Principal Component Analysis&#xff09;降维算法L…

Web课程学习笔记--CSS-Sprite的应用

雪碧图CSS Sprite的应用 CSS雪碧&#xff0c;即CSS Sprite&#xff0c;也有人叫它CSS精灵&#xff0c;是一种CSS图像合并技术&#xff0c;该方法是将小图标和背景图像合并到一张图片上&#xff0c;然后利用css的背景定位来显示需要显示的图片部分。例如常见的商品分类导航其实所…

代码手术刀-自定义你的代码重构工具

前言 笔者近日在做代码仓库的存量代码缩减工作&#xff0c;首先考虑的是基于静态扫描的缩减&#xff0c;尝试使用了很多工具来对代码进行优化&#xff0c;例如PMD、IDEA自带的inspect功能、findBugs等。但是无一例外&#xff0c;要么过于“保守”&#xff0c;只给出扫描结果&a…

分享springboot框架的一个开源的本地开发部署教程(若依开源项目开发部署过程分享持续更新二开宝藏项目PostgresSQL数据库版)

1首先介绍下若依项目&#xff1a; 若依是一个基于Spring Boot和Spring Cloud技术栈开发的多租户权限管理系统。该开源项目提供了一套完整的权限管理解决方案&#xff0c;包括用户管理、角色管理、菜单管理、部门管理、岗位管理等功能。 若依项目采用前后端分离的架构&#xf…

基于OpenCV灰度图像转GCode的单向扫描实现

基于OpenCV灰度图像转GCode的单向扫描实现 引言单向扫描存在的问题灰度图像单向扫描代码示例结论 系列文章 ⭐深入理解G0和G1指令&#xff1a;C中的实现与激光雕刻应用⭐基于二值化图像转GCode的单向扫描实现⭐基于二值化图像转GCode的双向扫描实现⭐基于二值化图像转GCode的…

青马在线考试怎么搜题找答案?不妨看看这九个实用工具 #知识分享#微信#笔记

在信息爆炸的时代&#xff0c;选择适合自己的学习辅助工具和资料&#xff0c;能够提供更高效、便捷和多样化的学习方式。 1.WolframAlpha WolframAlpha堪称“数学解题神器”&#xff01; 可以搜索到大学多个专业的题目以及试卷答案&#xff0c;重点是提供的题目搜索大部分的…

第二代Qwen大模型发布,阿里巴巴一口气开源了30个不同参数规模的模型

关于Qwen-1.5系列更多信息参考DataLearnerAI原文&#xff1a; 重磅&#xff01;第二代通义千问大模型开源&#xff0c;阿里巴巴一口气开源了30个不同参数规模的模型&#xff0c;其中Qwen1.5-72B仅次于GPT-4.​www.datalearner.com/blog/1051707149237037​编辑https://link.zh…

性能实测:分布式存储 ZBS 与集中式存储 HDS 在 Oracle 数据库场景表现如何

作者&#xff1a;深耕行业的 SmartX 金融团队 金鑫 在金融客户的基础架构环境中&#xff0c;HDS 是一种被广泛使用的存储解决方案。作为集中式存储的代表之一&#xff0c;HDS 拥有高性能、高可用性和可扩展性的企业级存储特点&#xff0c;适用于实时数据处理、虚拟化和灾难备份…

Docker下安装GitLab

极狐GitLab Docker 镜像 | 极狐GitLab 安装所需最小配置 内存至少4G 系统内核至少3.10以上 uname -r 命令可以查看系统内核版本 安装Docker 1.更新 yum源 yum update 2.安装依赖(如果在操作第三步的时候提示yum-config-manager 未找到命令 就安装下面依赖) yum instal…

杨中科 ASP.NETCORE 高级14 SignalR

1、什么是websocket、SignalR 服务器向客户端发送数据 1、需求&#xff1a;Web聊天;站内沟通。 2、传统HTTP&#xff1a;只能客户端主动发送请求 3、传统方案&#xff1a;长轮询&#xff08;Long Polling&#xff09;。缺点是&#xff1f;&#xff08;1.客户端发送请求后&…

防范恶意勒索攻击!亚信安全发布《勒索家族和勒索事件监控报告》

本周态势快速感知 本周全球共监测到勒索事件81起&#xff0c;事件数量有所下降&#xff0c;比上月降低20%。 lockbit3.0仍然是影响最严重的勒索家族&#xff1b;akira和incransom也是两个活动频繁的恶意家族&#xff0c;需要注意防范。 本周alphv勒索组织窃取MBC法律专业公司…

[word] word表格内容自动编号 #经验分享#微信#其他

word表格内容自动编号 在表格中的内容怎么样自动编号&#xff1f;我们都知道Word表格和Excel表格有所不同&#xff0c;Excel表格可以轻松自动编号&#xff0c;那么在Word表格中如何自动编号呢&#xff1f; 1、选中内容后&#xff0c;点击段落-自动编号&#xff0c;选择其中一…