深入分析 Android ContentProvider (十二)

文章目录

    • 深入分析 Android ContentProvider (十二)
    • Android 中 ContentProvider 的系统代码分析(续)
      • 1. ContentProvider 的内部实现机制
        • 1.1. ContentProvider 的创建与生命周期管理
        • 1.2. ContentProvider 的数据访问与处理
        • 1.3. ContentProvider 的权限管理与安全性
      • 2. ContentProvider 的通知机制
        • 示例:通知数据变化
      • 3. ContentProvider 的测试
        • 示例:ContentProvider 的单元测试
      • 4. 总结

深入分析 Android ContentProvider (十二)

Android 中 ContentProvider 的系统代码分析(续)

我们继续深入分析 Android 系统中 ContentProvider 的底层实现,进一步理解其工作流程及设计逻辑。

1. ContentProvider 的内部实现机制

ContentProvider 是 Android 中用于实现跨应用数据共享的组件。为了更详细地理解其内部工作机制,我们将探讨以下几个方面:

  1. ContentProvider 的创建与生命周期管理
  2. ContentProvider 的数据访问与处理
  3. ContentProvider 的权限管理与安全性
1.1. ContentProvider 的创建与生命周期管理

ContentProvider 的创建和生命周期管理由 Android 系统框架负责。当某个应用尝试访问 ContentProvider 时,系统会根据需要实例化该 ContentProvider 并调用其 onCreate() 方法。

在 Android 系统中,ContentProvider 的实例化是通过 ActivityThread 类来完成的。以下是相关的系统代码片段:

// ActivityThread.java
private IActivityManager mActivityManager;public final IContentProvider acquireProvider(Context c, String auth, int userId, boolean stable) {IContentProvider provider = null;try {provider = mActivityManager.getContentProvider(c.getIApplicationThread(), auth, userId, stable);} catch (RemoteException e) {// Handle exception}return provider;
}public final void installContentProviders(Context context, List<ProviderInfo> providers) {for (ProviderInfo info : providers) {ContentProviderHolder holder = installProvider(context, null, info, false, true, true);mAllProviders.put(holder.provider.getClass().getName(), holder);}
}private ContentProviderHolder installProvider(Context context, IContentProvider provider,ProviderInfo info, boolean noisy, boolean noReleaseNeeded, boolean stable) {ContentProvider localProvider = (ContentProvider)provider;localProvider.attachInfo(context, info);return new ContentProviderHolder(localProvider);
}
1.2. ContentProvider 的数据访问与处理

ContentProvider 的数据访问与处理是通过 ContentResolver 实现的。ContentResolver 是应用访问 ContentProvider 的主要接口,通过它可以进行查询、插入、更新和删除操作。

在系统代码中,ContentResolver 通过 IContentProvider 接口与 ContentProvider 进行通信。以下是相关的系统代码片段:

// ContentResolver.java
public final Cursor query(Uri uri, String[] projection, String selection,String[] selectionArgs, String sortOrder, CancellationSignal cancellationSignal) {IContentProvider provider = acquireProvider(uri);if (provider == null) {throw new IllegalArgumentException("Unknown URI " + uri);}try {return provider.query(mPackageName, uri, projection, selection, selectionArgs, sortOrder, cancellationSignal);} catch (RemoteException e) {throw new RuntimeException("Failed to query: " + uri, e);} finally {releaseProvider(provider);}
}

在这个过程中,ContentResolver 会通过 acquireProvider() 方法获取 ContentProvider 的实例,并通过 IContentProvider 接口调用相应的方法(如 query()insert()update()delete())来执行数据库操作。

1.3. ContentProvider 的权限管理与安全性

ContentProvider 的权限管理是通过 AndroidManifest.xml 中的 provider 标签进行配置的。开发者可以通过 android:permission 属性来限制访问权限。

在 ContentProvider 的内部实现中,可以通过检查调用方的权限来进一步增强安全性。以下是一个示例:

public class SecureContentProvider extends ContentProvider {@Overridepublic boolean onCreate() {return true;}@Overridepublic Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection,@Nullable String[] selectionArgs, @Nullable String sortOrder) {checkPermission();// 执行查询操作return null;}private void checkPermission() {Context context = getContext();if (context != null) {int permission = context.checkCallingOrSelfPermission("com.example.permission.READ_DATA");if (permission != PackageManager.PERMISSION_GRANTED) {throw new SecurityException("Permission denied");}}}// ... 其他方法的实现 ...
}

通过在操作前调用 checkPermission() 方法,可以确保只有具备相应权限的应用才能访问数据,提升数据安全性。

2. ContentProvider 的通知机制

ContentProvider 的数据变化通知机制通过 ContentObserverContentResolver.notifyChange() 实现。当数据发生变化时,ContentProvider 会通知观察者,以便其更新数据。

示例:通知数据变化
@Override
public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs) {int rowsUpdated;switch (uriMatcher.match(uri)) {case PLAYLISTS:rowsUpdated = database.update(DatabaseHelper.TABLE_PLAYLIST, values, selection, selectionArgs);break;case PLAYLIST_ID:selection = DatabaseHelper.COLUMN_ID + "=?";selectionArgs = new String[]{String.valueOf(ContentUris.parseId(uri))};rowsUpdated = database.update(DatabaseHelper.TABLE_PLAYLIST, values, selection, selectionArgs);break;default:throw new IllegalArgumentException("Unknown URI: " + uri);}getContext().getContentResolver().notifyChange(uri, null);return rowsUpdated;
}

通过 notifyChange() 方法,ContentProvider 可以通知 ContentObserver 数据已更新,触发 UI 更新或其他相关操作。

3. ContentProvider 的测试

为了确保 ContentProvider 的功能正确,可以编写单元测试进行验证。使用 Android 的 Instrumented Tests,可以在模拟设备上测试 ContentProvider 的行为。

示例:ContentProvider 的单元测试
@RunWith(AndroidJUnit4.class)
public class PlaylistProviderTest {private ContentResolver contentResolver;@Beforepublic void setUp() {Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();contentResolver = context.getContentResolver();}@Testpublic void testInsert() {ContentValues values = new ContentValues();values.put(DatabaseHelper.COLUMN_NAME, "Test Playlist");Uri newUri = contentResolver.insert(PlaylistProvider.CONTENT_URI, values);assertNotNull(newUri);}@Testpublic void testQuery() {Cursor cursor = contentResolver.query(PlaylistProvider.CONTENT_URI, null, null, null, null);assertNotNull(cursor);assertTrue(cursor.getCount() > 0);}@Testpublic void testUpdate() {ContentValues values = new ContentValues();values.put(DatabaseHelper.COLUMN_NAME, "Updated Playlist");int rowsUpdated = contentResolver.update(PlaylistProvider.CONTENT_URI, values, DatabaseHelper.COLUMN_ID + "=?", new String[]{"1"});assertEquals(1, rowsUpdated);}@Testpublic void testDelete() {int rowsDeleted = contentResolver.delete(PlaylistProvider.CONTENT_URI, DatabaseHelper.COLUMN_ID + "=?", new String[]{"1"});assertEquals(1, rowsDeleted);}
}

通过单元测试,可以验证 ContentProvider 的各项功能,确保其行为符合预期。

4. 总结

通过对 ContentProvider 系统代码的详细分析,我们可以更深入地理解其内部实现和工作机制。ContentProvider 提供了一个标准的接口,用于跨应用的数据共享和管理。通过 ContentResolver,应用可以方便地与 ContentProvider 进行交互,而 UriMatcher 则简化了 URI 的解析和匹配。掌握这些底层实现和工作流程,可以帮助开发者更好地设计和优化 ContentProvider,在实际项目中实现高效、安全的数据操作。

欢迎点赞|关注|收藏|评论,您的肯定是我创作的动力

在这里插入图片描述

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

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

相关文章

Go语言---sync.WaitGroup

在Go语言中&#xff0c;给我们提供了用于线程同步的sync.WaitGroup&#xff0c;简单来讲&#xff0c;WaitGroup就是指等待一组&#xff0c;等待一个系列执行完成后才会继续向下执行。 WaitGroup数据结构 type WaitGroup struct {noCopy noCopystate atomic.Uint64 // 高 32 b…

无人驾驶的未来:AI如何重塑我们的出行世界

无人驾驶汽车&#xff0c;作为人工智能&#xff08;AI&#xff09;技术的集大成者&#xff0c;正以前所未有的速度改变着我们的出行方式。从机器学习到计算机视觉&#xff0c;再到人工智能生成内容&#xff08;AIGC&#xff09;&#xff0c;AI技术的每一次进步都在为无人驾驶汽…

华为手机连接电脑后电脑无反应、检测不到设备的解决方法

本文介绍华为手机与任意品牌电脑连接时&#xff0c;出现连接后电脑无反应、检测不到手机连接情况的解决方法。 最近&#xff0c;因为手机的存储空间愈发紧缺&#xff0c;所以希望在非华为电脑中&#xff0c;将华为手机内的照片、视频等大文件备份、整理一下。因此&#xff0c;需…

公司里的IT是什么?

公司里的IT是什么&#xff1f; 文章目录 公司里的IT是什么&#xff1f;1、公司里的IT2、IT技术3、IT行业4、IT行业常见证书 如果对你有帮助&#xff0c;就点赞收藏把&#xff01;(&#xff61;&#xff65;ω&#xff65;&#xff61;)&#xff89;♡ 前段时间&#xff0c;在公…

《Windows API每日一练》24.1 WinSock简介

本节将逐一介绍WinSock的主要特性和组件&#xff0c;套接字、WinSock动态库的使用。 本节必须掌握的知识点&#xff1a; Windows Socket接口简介 Windows Socket接口的使用 第178练&#xff1a;网络时间校验 24.1.1 Windows Socket接口简介 ■以下是WinSock的主要特性和组件…

实时转换,轻松编辑:2024年高效语音转文字解决方案

现在生活节奏越来越快了&#xff0c;很多时候一场会议内容的信息量就会呈几何式增长。用笔来记录肯定来不及&#xff0c;那还有一个方法就是录音或者录像。录制完成后我们可以使用语音转文字来快速获取会议内容是不是就方便了很多。 1.365在线转文字 链接传送&#xff1a;ww…

华为云依赖引入错误

问题&#xff1a;记录一次项目加载华为云依赖错误&#xff0c;如下&#xff1a; 错误信息&#xff1a;Could not find artifact com.huawei.storage:esdk-obs-java:pom:3.1.2.1 in bintray-qcloud-maven-repo (https://dl.bintray.com/qcloud/maven-repo/) 找到本地仓库&#…

【practise】string_atoi

今天来分享一道比较平常的练习题&#xff0c;说实话我自己写了半天&#xff0c;自己写的很烂最后还是看的答案… 1.题目概要 题目链接&#xff1a;LINK 2.题目难点 这个题目有两个难点&#xff0c;如下&#xff1a; 拿到了全部都是数字字符的字符串&#xff0c;怎么将这个…

从技术角度解读【与辉同行】文案(一)

视频文字内容 标题&#xff1a;走晋.山西 内容&#xff1a;将一段岁月熔成佳酿&#xff0c;三晋儿女荡气回肠。捧一把黄土架起火柴&#xff0c;华夏大地照亮火光。五千年黄土风云&#xff0c;历代千秋根固魂盈。三万顷汾河烟雨&#xff0c;唐风宋韵人杰地灵。当先辈手持石器抛挖…

秘密打造「AI陶哲轩」 震惊数学圈!谷歌IMO梦之队首曝光,菲尔兹奖得主深度点评

谷歌DeepMind正在做的&#xff0c;是要打造出世界上最强的AI数学家。 Perplexity AI的CEO对此做出了大胆预测——DeepMind继续研究下去的话&#xff0c;应该可以搞出一个「AI陶哲轩」了&#xff01; 这个预测可谓相当大胆。 要知道&#xff0c;陶哲轩在IMO竞赛圈&#xff0c;乃…

ADI - 通过5 V至24 V输入提供双极性、双向DC-DC流入和流出电流

大部分电子系统都依赖于正电压轨或负电压轨&#xff0c;但是有些应用要求单电压轨同时为正负电压轨。在这种情况下&#xff0c;正电源或负电源由同一端子提供&#xff0c;也就是说&#xff0c;电源的输出电压可以在整个电压范围内调节&#xff0c;并且可以平稳转换极性。例如&a…

【CORS 报错】跨域请求问题:CORS 多种环境下的解决方案

&#x1f525; 个人主页&#xff1a;空白诗 文章目录 一、CORS错误的常见原因二、解决方案1. Vue3 Vite项目下的解决方案创建Vue3 Vite项目配置Vite的代理发送请求 2. jQuery项目下的解决方案使用CORS请求头使用JSONP 3. 其他环境下的解决方案使用服务器端代理设置CORS头使用…

“再来一单“业务功能开发

文章目录 概要整体架构流程技术细节小结 概要 再来一单”功能常见于餐饮、零售、外卖等行业&#xff0c;主要目的是为了简化用户的重复购买流程&#xff0c;提高用户体验和效率。 需求分析以及接口设计 再来一单就是将原订单中的商品重新加入到购物车中,所以本质上是"增…

java之WIFI信号模块

开发步骤分为以下几点&#xff1a; 1.在 AndroidManifest 中声明相关权限&#xff08;网络和文件读写权限&#xff09; 声明权限: <uses-permission android:name"android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name"android.…

matlab y=sin(x) - 2/π*(x)函数绘制

[TOC](matlab ysin(x) - 2/π*(x)函数绘制) ysin(x) - 2/π*(x) clc; clear; close all; x_axis_length 10; y_axis_length 10; % 创建 x 值向量 x_positive linspace(0.1, 10, 1000); % 正半轴上的 x 值 x_negative linspace(-10, -0.1, 1000); % 负半轴上的 x 值% 计算…

前端新手小白的React入坑指南

有个小伙伴跟我说&#xff0c;已经毕业了&#xff0c;开始实习了。但公司现在用的还是Vue&#xff0c;领导说是过段时间让他用React做项目&#xff0c;先自己学习起来。 我给他找了一些文档&#xff0c;顺便着呢&#xff0c;反正自己也写博客&#xff0c;自己也写一份吧&#x…

华为视觉智驾来了!买车千万不要乱选了

文 | AUTO芯球 作者 | 雷慢 华为又偷偷地憋大招了&#xff0c; 你们看&#xff0c;余承东昨天天悄咪咪地发了条微博宣布&#xff0c; 智界S7Pro版开始首发搭载华为视觉智驾方案&#xff0c; 也就是华为ADS基础版&#xff0c;车也陆续交给了车主们&#xff0c; 那问题来了&a…

江科大/江协科技 STM32学习笔记P13

文章目录 TIM定时中断1、TIM简介计数器PSC预分频器&#xff08;Prescaler&#xff09;ARR自动重装寄存器&#xff08;Auto Reload Register&#xff09; 2、定时器类型基本定时器主模式触发DAC 通用定时器高级定时器 3、定时器原理定时中断基本结构预分频器时序计数器时序RCC时…

从零开始掌握tcpdump:参数详解

Linux tcpdump命令详解 1. 语法 tcpdump [-adeflnnNOpqStvxX] [-c <数据包数目>] [-dd] [-ddd] [-F <表达文件>] [-i <网络界面>] [-r <数据包文件>] [-s <数据包大小>] [-tt] [-T <数据包类型>] [-vv] [-w <数据包文件>] [输出数…

【办公软件】Office 2019以上版本PPT 做平滑切换

Office2019以上版本可以在切页面时做平滑切换&#xff0c;做到一些简单的动画效果。如下在快捷菜单栏中的切换里选择平滑。 比如&#xff0c;在两页PPT中&#xff0c;使用同一个形状对象&#xff0c;修改了大小和颜色。 选择切换为平滑后&#xff0c;可以完成如下的动画显示。 …