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

ContentProvider:在Android中实现进程间数据共享

目录

一,ContentProvider

二,Uri和UriMatcher工具类

1,Uri

2,UriMatcher

三,自定义ContentProvider

 1,准备数据源

2,创建ContentProvider子类

 3,在Manifest文件中注册ContentProvider

四,使用ContentResolver访问数据

五,获取系统中CP的数据

1,获取通话记录

2,管理多媒体内容


一,ContentProvider

        ContentProvider内容提供者,是一种实现不同应用间共享数据的标准api,当应用想要提供数据时,就提供ContentProvider,其他应用通过ContentResolver来接收数据;

        ContentProvider以Uri的形式对外提供数据,其他应用使用ContentResolver通过Uri来访问数据;

        ContentProvider是单例模式的,多个ContentResolver请求数据时,是委托给同一个CP对象来操作的;

二,Uri和UriMatcher工具类

1,Uri

Uri的结构和网站URL命名规则类似:

Uri举例:content://org.edu.provider/words

  • content://:这部分是Android固定的
  • org.edu.provider:这部分是ContentProvider中的authority,结构一般为包名.provider
  • words:资源部分,根据资源不同这部分不同

通过Uri提供的静态方法parse()来实现将字符串转换为Uri:

  • Uri uri = Uri.parse("content://org.edu.p../words") 

2,UriMatcher

帮助ContentProvider操作Uri,进行Uri判断和注册等功能;

(1)UriMatcher通过构造器构造:

UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
//UriMatcher.NO_MATCH 表示不匹配任何路径的返回码(返回-1)

(2)注册Uri,只有注册过的Uri才能被访问:

//Uri的authorities
private static String AUTHORITIES = "com.example.contentprovider.ContentProvider.provider";//Uri的标识码,用于标识唯一的资源
private static Integer BOOK_CODE = 0;//注册Uri authorities + 资源名(表名)+ 标识码
matcher.addURI(AUTHORITIES, "tb_books", BOOK_CODE);//最终Uri格式为"content://com.example.contentprovider.ContentProvider.provider/tb_books/0"

 (3)通过int match(Uri uri)方法来判断Uri的对应的标识符,找不到返回-1:

private String getTable(Uri uri) {String tableName = "";if(matcher.match(uri) == BOOK_CODE)tableName = "tb_books";return tableName;
}

三,自定义ContentProvider

  • 准备数据源:可以是文件存储,Sqlite数据库等数据源;
  • 创建ContentProvider:自定义一个类继承ContentProvider,并重写增删改查等方法;
  • Manifest文件中注册ContentProvider;

 1,准备数据源

(1)以Sqlite数据库为数据源,创建SqliteOpenHelper类:

public class SqliteHelper extends SQLiteOpenHelper {public SqliteHelper(@Nullable Context context, @Nullable String name, @Nullable SQLiteDatabase.CursorFactory factory, int version) {super(context, name, factory, version);}@Overridepublic void onCreate(SQLiteDatabase db) {db.execSQL("create table if not exists tb_books(" +"id Integer primary key autoincrement, " +"name varchar(20) not null" +");");}@Overridepublic void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {}
}

2,创建ContentProvider子类

(2)创建ContentProvider,重写增删改查等方法,使用UriMatcher注册Uri:

public class MyContentProvider extends ContentProvider {private SQLiteDatabase bookDB;private static UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);private static String AUTHORITIES = "com.example.contentprovider.ContentProvider.provider";private static Integer BOOK_CODE = 0;//注册Uripublic MyContentProvider() {matcher.addURI(AUTHORITIES, "tb_books", BOOK_CODE);}@Overridepublic String getType(Uri uri) {return null;}private String getTable(Uri uri) {String tableName = "";if(matcher.match(uri) == BOOK_CODE)tableName = "tb_books";return tableName;}@Overridepublic boolean onCreate() {//获取Sqlite数据库SqliteHelper sqliteHelper = new SqliteHelper(getContext(),"bookDB.db",null,1);bookDB = sqliteHelper.getWritableDatabase();//插入数据ContentValues contentValuesBooks = new ContentValues();contentValuesBooks.put("name", "book1");bookDB.insert("tb_books", null, contentValuesBooks);return true;}@Overridepublic Uri insert(Uri uri, ContentValues values) {String table = getTable(uri);if(table.isEmpty()){return null;}else {long insert = bookDB.insert(table, null, values);if(insert > 0)return uri;else return null;}}@Overridepublic int delete(Uri uri, String selection, String[] selectionArgs) {String table = getTable(uri);if(table.isEmpty()){return -1;}else {int delete = bookDB.delete(table, selection, selectionArgs);return delete;}}@Overridepublic Cursor query(Uri uri, String[] projection, String selection,String[] selectionArgs, String sortOrder) {String table = getTable(uri);if(table.isEmpty()){return null;}else {Cursor cursor = bookDB.query(table, projection, selection, selectionArgs, null, null,sortOrder);return cursor;}}@Overridepublic int update(Uri uri, ContentValues values, String selection,String[] selectionArgs) {String table = getTable(uri);if(table.isEmpty()){return -1;}else {int update = bookDB.update(table, values, selection, selectionArgs);return update;}}
}

 3,在Manifest文件中注册ContentProvider

四,使用ContentResolver访问数据

(1)通过getContentResolver()方法获取ContentResolver对象:

ContentResolver contentResolver = getContentResolver();

(2)获取Uri:

Uri uri = Uri.parse("content://com.example.contentprovider.ContentProvider.provider/tb_books");

 (3)通过ContentResolver调用增删改查等方法:

public class MainActivity extends AppCompatActivity {private ActivityMainBinding binding = null;private ContentResolver contentResolver;private Uri uri;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);binding = ActivityMainBinding.inflate(getLayoutInflater());setContentView(binding.getRoot());contentResolver = getContentResolver();uri = Uri.parse("content://com.example.contentprovider.ContentProvider.provider/tb_books");binding.btnAdd.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {AlertDialogUtil.showDialog(MainActivity.this,"添加","id","书名",new AlertDialogUtil.DialogClickCallback() {@Overridepublic void onClick(DialogInterface dialog, int which, String input1, String input2) {ContentValues contentValues = new ContentValues();contentValues.put("id", Integer.valueOf(input1));contentValues.put("name", input2);Uri insert = contentResolver.insert(uri, contentValues);if (insert != null) {Toast.makeText(MainActivity.this, "插入成功", Toast.LENGTH_SHORT).show();} elseToast.makeText(MainActivity.this, "插入失败", Toast.LENGTH_SHORT).show();}});}});binding.btnDelete.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {AlertDialogUtil.showDialog(MainActivity.this,"删除","id","书名",new AlertDialogUtil.DialogClickCallback() {@Overridepublic void onClick(DialogInterface dialog, int which, String input1, String input2) {String selection = "id = ?";String[] selectionArgs = {input1};int delete = contentResolver.delete(uri, selection, selectionArgs);if(delete > 0){Toast.makeText(MainActivity.this, "删除成功", Toast.LENGTH_SHORT).show();}elseToast.makeText(MainActivity.this, "删除失败", Toast.LENGTH_SHORT).show();}});}});binding.btnUpdate.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {AlertDialogUtil.showDialog(MainActivity.this,"修改","id","书名",new AlertDialogUtil.DialogClickCallback() {@Overridepublic void onClick(DialogInterface dialog, int which, String input1, String input2) {ContentValues contentValues = new ContentValues();contentValues.put("name", input2);String selection = "id = ?";String[] selectionArgs = {input1};int update = contentResolver.update(uri, contentValues, selection, selectionArgs);if(update > 0){Toast.makeText(MainActivity.this, "修改成功", Toast.LENGTH_SHORT).show();}elseToast.makeText(MainActivity.this, "修改失败", Toast.LENGTH_SHORT).show();}});}});binding.btnQuery.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {Cursor cursor = contentResolver.query(uri, null, null, null, null);StringBuffer result = new StringBuffer();if(cursor == null){Toast.makeText(MainActivity.this, "查询失败", Toast.LENGTH_SHORT).show();}else{while(cursor.moveToNext()){int indexOfName = cursor.getColumnIndex("name");int indexOfId = cursor.getColumnIndex("id");int id = cursor.getInt(indexOfId);String name = cursor.getString(indexOfName);result.append("id: " + id + ", name: " + name + "\n");}}binding.tvResult.setText(result);}});}
}

五,获取系统中CP的数据

        Android系统应用会采用CP(ContentProvider)的形式提供一些开放数据,只要知道相关的Uri。我们就可以直接通过ContentResolver来访问这些数据;

1,获取通话记录

通话记录的Uri为:CallLog.Calls.CONTENT_URI

获取通话记录用到的常量:

  • CallLog.Calls._ID: "_id"
  • CallLog.Calls.CACHED_NAME:”name”
  • CallLog.Calls.NUMBER:”number”
  • CallLog.Calls.TYPE:”type” CallLog.Calls.DATE:”date”
  • CallLog.Calls.DURATION:”duration”

2,管理多媒体内容

此CP支持的Uri如下:

  • MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
  • MediaStore.Audio.Media.INTERNAL_CONTENT_URI
  • MediaStore.Images.Media.EXTERNAL_CONTENT_URI
  • MediaStore.Images.Media.INTERNAL_CONTENT_URI
  • MediaStore.Video.Media.EXTERNAL_CONTENT_URI
  • MediaStore.Video.Media.INTERNAL_CONTENT_URI
  • Content://sms/outbox  发送箱短信URI
  • Content://sms/sent  收信箱短信URI
  • Content://sms/draft  草稿箱短信URI 

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • unity2107,导入spine骨骼动画报错
  • 8.4.数据库基础技术-SQL
  • Java后端面试题
  • Lua脚本 快速掌握
  • 华为设备的两种配置生效模式
  • 深度学习 —— 个人学习笔记20(转置卷积、全卷积网络)
  • 【大数据】6:MapReduce YARN 初体验
  • DAMA学习笔记(十五)-数据管理组织与角色期望
  • 模拟三层--控制层、业务层和数据访问层
  • 抓包分析排查利器TCPdump
  • Qt读写sysfs
  • 8月13日学习笔记 LVS
  • 代码随想录算法训练营day42|动态规划part09
  • 【中等】 猿人学web第一届 第5题 js混淆-乱码增强
  • HAProxy原理及实例
  • JS中 map, filter, some, every, forEach, for in, for of 用法总结
  • 《网管员必读——网络组建》(第2版)电子课件下载
  • 「前端」从UglifyJSPlugin强制开启css压缩探究webpack插件运行机制
  • Github访问慢解决办法
  • JavaScript 是如何工作的:WebRTC 和对等网络的机制!
  • Java知识点总结(JDBC-连接步骤及CRUD)
  • js ES6 求数组的交集,并集,还有差集
  • nodejs:开发并发布一个nodejs包
  • Promise初体验
  • react-core-image-upload 一款轻量级图片上传裁剪插件
  • sublime配置文件
  • Vue 2.3、2.4 知识点小结
  • 大主子表关联的性能优化方法
  • 分布式任务队列Celery
  • 开放才能进步!Angular和Wijmo一起走过的日子
  • 通过几道题目学习二叉搜索树
  • 因为阿里,他们成了“杭漂”
  • Nginx实现动静分离
  • ​【数据结构与算法】冒泡排序:简单易懂的排序算法解析
  • ​软考-高级-系统架构设计师教程(清华第2版)【第15章 面向服务架构设计理论与实践(P527~554)-思维导图】​
  • ​探讨元宇宙和VR虚拟现实之间的区别​
  • # centos7下FFmpeg环境部署记录
  • #100天计划# 2013年9月29日
  • #162 (Div. 2)
  • #define 用法
  • #多叉树深度遍历_结合深度学习的视频编码方法--帧内预测
  • $.each()与$(selector).each()
  • $redis-setphp_redis Set命令,php操作Redis Set函数介绍
  • (11)工业界推荐系统-小红书推荐场景及内部实践【粗排三塔模型】
  • (2)(2.10) LTM telemetry
  • (2009.11版)《网络管理员考试 考前冲刺预测卷及考点解析》复习重点
  • (55)MOS管专题--->(10)MOS管的封装
  • (二)【Jmeter】专栏实战项目靶场drupal部署
  • (二)Kafka离线安装 - Zookeeper下载及安装
  • (二)PySpark3:SparkSQL编程
  • (二刷)代码随想录第16天|104.二叉树的最大深度 559.n叉树的最大深度● 111.二叉树的最小深度● 222.完全二叉树的节点个数
  • (转)C#调用WebService 基础
  • (转)chrome浏览器收藏夹(书签)的导出与导入
  • (转)树状数组
  • (转载)Google Chrome调试JS