当前位置: 首页 > news >正文

Android之内容提供者(ContentProvider)

目录

  • 作用
  • 基本结构
  • 示例
    • 1. 创建内容提供者类
    • 2.在AndroidManifest.xml中声明内容提供者
      • 使用内容提供者
        • 查询数据
        • 插入数据
        • 更新数据
        • 删除数据
      • 内容提供者的URI
    • 3.权限设置
      • 声明权限
      • 定义权限
      • 在代码中检查权限
      • 动态权限请求
      • 处理权限请求结果
  • 应用场景
    • 1. 应用之间的数据共享
      • 联系人应用
      • 媒体应用
    • 2. 应用内部的数据管理
      • 新闻应用
      • 任务管理应用
    • 3. 数据同步
      • 邮件应用
      • 笔记应用
    • 4. 数据的统一访问接口
      • 文件管理应用
      • 设置应用
    • 5. 数据的安全访问
      • 健康数据应用
      • 财务管理应用
    • 6. 数据的备份和恢复
      • 日历应用
      • 联系人应用
    • 7. 数据的观察与监听
      • 短信应用
      • 股票应用
    • 应用场景总结

内容提供者(ContentProvider)是Android四大组件之一,用于在不同应用之间共享数据。内容提供者通过统一资源标识符(URI)来标识数据,并使用一套标准的接口来访问和操作数据。它是Android系统中实现跨应用数据共享的主要方式。

作用

  • 数据共享:允许不同应用之间共享数据,例如联系人、媒体文件等。
  • 数据封装:提供统一的接口来访问和操作数据,隐藏底层数据存储的实现细节。
  • 权限控制:通过权限机制控制数据的访问,确保数据的安全性。

基本结构

内容提供者通过继承ContentProvider类来实现,主要包括以下几个方法:

  • onCreate():初始化内容提供者。
  • query():查询数据。
  • insert():插入数据。
  • update():更新数据。
  • delete():删除数据。
  • getType():返回数据的MIME类型。

示例

实现一个简单的内容提供者

1. 创建内容提供者类

public class MyContentProvider extends ContentProvider {private static final String AUTHORITY = "com.example.mycontentprovider";private static final String PATH = "mydata";public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/" + PATH);private SQLiteDatabase database;@Overridepublic boolean onCreate() {// 初始化数据库或其他数据存储MyDatabaseHelper dbHelper = new MyDatabaseHelper(getContext());database = dbHelper.getWritableDatabase();return database != null;}@Overridepublic Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {// 查询数据return database.query("mytable", projection, selection, selectionArgs, null, null, sortOrder);}@Overridepublic Uri insert(Uri uri, ContentValues values) {// 插入数据long id = database.insert("mytable", null, values);return ContentUris.withAppendedId(CONTENT_URI, id);}@Overridepublic int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {// 更新数据return database.update("mytable", values, selection, selectionArgs);}@Overridepublic int delete(Uri uri, String selection, String[] selectionArgs) {// 删除数据return database.delete("mytable", selection, selectionArgs);}@Overridepublic String getType(Uri uri) {// 返回数据的MIME类型return "vnd.android.cursor.dir/vnd.com.example.mycontentprovider.mydata";}
}

2.在AndroidManifest.xml中声明内容提供者

<providerandroid:name=".MyContentProvider"android:authorities="com.example.mycontentprovider"android:exported="true" />

使用内容提供者

其他应用或组件可以通过ContentResolver来访问内容提供者的数据。

查询数据
Cursor cursor = getContentResolver().query(MyContentProvider.CONTENT_URI,null, // projectionnull, // selectionnull, // selectionArgsnull  // sortOrder
);if (cursor != null) {while (cursor.moveToNext()) {// 处理查询结果}cursor.close();
}
插入数据
ContentValues values = new ContentValues();
values.put("column_name", "value");
Uri newUri = getContentResolver().insert(MyContentProvider.CONTENT_URI, values);
更新数据
ContentValues values = new ContentValues();
values.put("column_name", "new_value");
int rowsUpdated = getContentResolver().update(MyContentProvider.CONTENT_URI, values, "column_name = ?", new String[]{"old_value"});
删除数据
int rowsDeleted = getContentResolver().delete(MyContentProvider.CONTENT_URI, "column_name = ?", new String[]{"value"});

内容提供者的URI

内容提供者通过URI来标识和访问数据。URI的结构通常如下:

content://<authority>/<path>/<id>
  • authority:内容提供者的唯一标识符,通常是应用包名。
  • path:数据的路径,表示数据的类型或表名。
  • id:可选,用于标识特定的数据项。

3.权限设置

声明权限

AndroidManifest.xml文件中声明权限,以限制对内容提供者的访问。可以声明读权限、写权限或两者兼有。

<providerandroid:name=".MyContentProvider"android:authorities="com.example.mycontentprovider"android:exported="true"android:readPermission="com.example.mycontentprovider.READ"android:writePermission="com.example.mycontentprovider.WRITE" />

在上述示例中,android:readPermission和android:writePermission属性用于指定读和写权限。只有声明了这些权限的应用程序才能访问内容提供者的数据。

定义权限

在AndroidManifest.xml文件中定义自定义权限:

<permissionandroid:name="com.example.mycontentprovider.READ"android:protectionLevel="normal" />
<permissionandroid:name="com.example.mycontentprovider.WRITE"android:protectionLevel="normal" />

protectionLevel属性定义了权限的保护级别。常见的保护级别包括:

  • normal:普通权限,系统会自动授予这些权限。
  • dangerous:危险权限,用户需要显式授予这些权限。
  • signature:签名权限,只有与内容提供者应用具有相同签名的应用才能获得这些权限。

在代码中检查权限

在内容提供者的代码中,可以使用checkCallingPermission()方法来检查调用应用是否具有所需的权限。

@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {if (getContext().checkCallingPermission("com.example.mycontentprovider.READ") != PackageManager.PERMISSION_GRANTED) {throw new SecurityException("Permission denied to read data");}// 执行查询操作return database.query("my_table", projection, selection, selectionArgs, null, null, sortOrder);
}@Override
public Uri insert(Uri uri, ContentValues values) {if (getContext().checkCallingPermission("com.example.mycontentprovider.WRITE") != PackageManager.PERMISSION_GRANTED) {throw new SecurityException("Permission denied to write data");}// 执行插入操作long id = database.insert("my_table", null, values);return ContentUris.withAppendedId(CONTENT_URI, id);
}

动态权限请求

对于危险权限,调用应用需要在运行时请求权限。

// 请求读权限
if (ContextCompat.checkSelfPermission(this, "com.example.mycontentprovider.READ") != PackageManager.PERMISSION_GRANTED) {ActivityCompat.requestPermissions(this, new String[]{"com.example.mycontentprovider.READ"}, REQUEST_CODE);
}// 请求写权限
if (ContextCompat.checkSelfPermission(this, "com.example.mycontentprovider.WRITE") != PackageManager.PERMISSION_GRANTED) {ActivityCompat.requestPermissions(this, new String[]{"com.example.mycontentprovider.WRITE"}, REQUEST_CODE);
}

处理权限请求结果

在调用应用中,处理权限请求结果:

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {if (requestCode == REQUEST_CODE) {if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {// 权限授予,执行相应操作} else {// 权限被拒绝,显示提示信息}}
}

应用场景

1. 应用之间的数据共享

内容提供者允许不同应用之间共享数据。例如,一个联系人应用可以通过内容提供者共享联系人信息,其他应用可以访问这些联系人数据。

联系人应用

Android系统自带的联系人应用使用内容提供者来管理联系人数据,其他应用可以访问这些数据以获取联系人信息。

媒体应用

音乐播放器应用可以通过内容提供者共享音乐文件信息,其他应用可以访问这些音乐文件以播放或管理音乐。

2. 应用内部的数据管理

内容提供者不仅可以在应用之间共享数据,还可以在应用内部不同组件之间共享数据。例如,一个应用的多个Activity或Fragment可以通过内容提供者共享和管理数据。

新闻应用

一个新闻应用的不同Activity或Fragment可以通过内容提供者共享新闻数据。

任务管理应用

一个任务管理应用的不同组件可以通过内容提供者共享和管理任务数据。

3. 数据同步

内容提供者可以与同步适配器(SyncAdapter)结合使用,实现数据的同步。例如,一个邮件应用可以使用内容提供者和同步适配器同步邮件数据。

邮件应用

邮件应用可以使用内容提供者存储邮件数据,并通过同步适配器实现邮件数据的同步。

笔记应用

笔记应用可以使用内容提供者存储笔记数据,并通过同步适配器实现笔记数据的同步。

4. 数据的统一访问接口

内容提供者提供了统一的接口来访问和操作数据。通过内容提供者,应用程序可以使用标准的URI和CRUD操作接口来访问和管理数据,而不需要关心底层数据存储的实现细节。

文件管理应用

文件管理应用可以使用内容提供者提供的统一接口访问和管理不同类型的文件数据。

设置应用

系统设置应用可以使用内容提供者提供的统一接口访问和管理系统设置数据。

5. 数据的安全访问

内容提供者可以通过权限控制来实现数据的安全访问。应用程序可以通过内容提供者设置权限,限制其他应用对数据的访问。

健康数据应用

健康数据应用可以使用内容提供者存储健康数据,并通过权限控制限制其他应用对健康数据的访问。

财务管理应用

财务管理应用可以使用内容提供者存储财务数据,并通过权限控制限制其他应用对财务数据的访问。

6. 数据的备份和恢复

内容提供者可以与备份服务结合使用,实现数据的备份和恢复。例如,一个日历应用可以使用内容提供者和备份服务备份日历数据。

日历应用

日历应用可以使用内容提供者存储日历数据,并通过备份服务实现日历数据的备份和恢复。

联系人应用

联系人应用可以使用内容提供者存储联系人数据,并通过备份服务实现联系人数据的备份和恢复。

7. 数据的观察与监听

内容提供者可以与内容观察者(ContentObserver)结合使用,实现对数据变化的观察和监听。例如,一个短信应用可以使用内容观察者监听短信数据的变化。

短信应用

短信应用可以使用内容观察者监听短信数据的变化,并在有新短信时通知用户。

股票应用

股票应用可以使用内容观察者监听股票数据的变化,并在股票价格变化时通知用户。

应用场景总结

内容提供者在Android应用开发中有广泛的应用场景,包括应用之间的数据共享、应用内部的数据管理、数据同步、数据的统一访问接口、数据的安全访问、数据的备份和恢复以及数据的观察与监听。通过内容提供者,开发者可以实现数据的高效管理和安全共享,提高应用的功能性和用户体验。

Activity之Intent、生命周期、启动模式
Android之service两种启动方式的异同
Android之Service与IntentService区别
Android之广播(Broadcast)
ANR 超时的定义

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 算法力扣刷题记录 八十三【96.不同的二叉搜索树】
  • 鼠标手势软件,效率办公必备!移动鼠标即可执行命令
  • 个人效能是一个系统
  • Redis 缓存预热、雪崩、穿透、击穿
  • 坐牢第二十七天(聊天室)
  • [游戏开发] LuaTable转string存读二进制文件
  • vue 后台管理 之 axios使用及接口拦截响应等
  • 基于神经网络逆同步控制方法的两变频调速电机控制系统matlab仿真
  • Linux git安装与部署
  • 服务器数据恢复—IBM服务器raid5阵列硬盘出现坏道的数据恢复案例
  • 服务器上部署服务
  • Revite二次开发_使用WPF和WebView2制作一个访问网站的窗口
  • pygame游戏开发系列教程(1)
  • C++数组入门
  • Python知识点:如何使用Boto3进行AWS服务管理
  • ES6指北【2】—— 箭头函数
  • 《微软的软件测试之道》成书始末、出版宣告、补充致谢名单及相关信息
  • 【面试系列】之二:关于js原型
  • 07.Android之多媒体问题
  • 5分钟即可掌握的前端高效利器:JavaScript 策略模式
  • canvas 高仿 Apple Watch 表盘
  • create-react-app做的留言板
  • CSS中外联样式表代表的含义
  • express + mock 让前后台并行开发
  • HomeBrew常规使用教程
  • Java 23种设计模式 之单例模式 7种实现方式
  • JavaScript/HTML5图表开发工具JavaScript Charts v3.19.6发布【附下载】
  • mysql innodb 索引使用指南
  • nginx(二):进阶配置介绍--rewrite用法,压缩,https虚拟主机等
  • SegmentFault 2015 Top Rank
  • Spring框架之我见(三)——IOC、AOP
  • Spring思维导图,让Spring不再难懂(mvc篇)
  • 编写高质量JavaScript代码之并发
  • 从PHP迁移至Golang - 基础篇
  • 番外篇1:在Windows环境下安装JDK
  • 分布式任务队列Celery
  • 构建工具 - 收藏集 - 掘金
  • 关于for循环的简单归纳
  • 关于List、List?、ListObject的区别
  • 基于Vue2全家桶的移动端AppDEMO实现
  • 今年的LC3大会没了?
  • 区块链技术特点之去中心化特性
  • ​LeetCode解法汇总518. 零钱兑换 II
  • # 利刃出鞘_Tomcat 核心原理解析(七)
  • ###STL(标准模板库)
  • (+4)2.2UML建模图
  • (1)Map集合 (2)异常机制 (3)File类 (4)I/O流
  • (二)斐波那契Fabonacci函数
  • (附源码)springboot教学评价 毕业设计 641310
  • (三)Pytorch快速搭建卷积神经网络模型实现手写数字识别(代码+详细注解)
  • .bat文件调用java类的main方法
  • .NET 5.0正式发布,有什么功能特性(翻译)
  • .net core使用ef 6
  • .NET 常见的偏门问题
  • .NET 的程序集加载上下文