深入分析 Android ContentProvider (十二)

news2024/11/14 8:23:28

文章目录

    • 深入分析 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 {

    @Override
    public boolean onCreate() {
        return true;
    }

    @Override
    public 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;

    @Before
    public void setUp() {
        Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
        contentResolver = context.getContentResolver();
    }

    @Test
    public void testInsert() {
        ContentValues values = new ContentValues();
        values.put(DatabaseHelper.COLUMN_NAME, "Test Playlist");
        Uri newUri = contentResolver.insert(PlaylistProvider.CONTENT_URI, values);
        assertNotNull(newUri);
    }

    @Test
    public void testQuery() {
        Cursor cursor = contentResolver.query(PlaylistProvider.CONTENT_URI, null, null, null, null);
        assertNotNull(cursor);
        assertTrue(cursor.getCount() > 0);
    }

    @Test
    public 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);
    }

    @Test
    public 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.coloradmin.cn/o/1971220.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Node Red 与axios简易测试环境的搭建

为了学习在vue3中如何使用axios&#xff0c;我借Sider Fusion的帮助搭建了基于node的简易测试环境。 Axios 是一个基于 Promise 的 HTTP 客户端&#xff0c;通常用于浏览器环境&#xff0c;但它也可以在 Node.js 环境中使用。因此&#xff0c;可以在 Ubuntu 的 Bash 环境下通过…

NPDP|传统行业产品大神都是怎样管理产品的?

在传统行业中&#xff0c;产品管理不仅是技术的较量&#xff0c;更是策略、洞察力和执行力的综合体现。那些被誉为“产品大神”的经理们&#xff0c;他们如何管理产品&#xff0c;使其在市场上脱颖而出&#xff0c;成为行业内的佼佼者&#xff1f;本文将探讨他们的一些关键管理…

触发邮件接口如何与现有CRM系统无缝集成?

触发邮件接口的性能优化策略&#xff1f;如何设计高效的API接口&#xff1f; 随着企业对自动化和个性化沟通需求的增加&#xff0c;触发邮件接口的集成变得尤为重要。AokSend将探讨触发邮件接口如何与现有CRM系统无缝集成&#xff0c;以及这种集成带来的优势和挑战。 触发邮件…

c语言第七天笔记

作业题&#xff1a; 设计TVM&#xff08;地铁自动售票机&#xff09;机软件。 输入站数&#xff0c;计算费用&#xff0c;计费规则&#xff0c;6站2元&#xff0c;7-10站3元&#xff0c;11站以上为4元。 输入钱数&#xff0c;计算找零(找零时优先找回面额大的钞票)&#xff0…

与树莓派的“黄金”关系,是如何帮助这家医疗设备公司扩大规模

稳定的供应和与Raspberry Pi的“黄金”关系帮助医疗设备公司进行了规模扩张 埃及医疗设备制造商Bio Business需要将物联网功能集成到其成功的患者监测设备系列中。Raspberry Pi技术使他们得以实现。 解决方案 RP2040 Compute Module 4 企业规模 中小企业 行业 医疗技术 …

springbootJZ车行系统-计算机毕业设计源码93812

目 录 摘 要 1 绪论 1.1 研究背景与意义 1.2开发现状 1.3论文结构与章节安排 2 系统分析 2.1 可行性分析 2.1.1 技术可行性分析 2.1.2 经济可行性分析 2.1.3 操作可行性分析 2.2 系统功能分析 2.2.1 功能性分析 2.2.2 非功能性分析 2.3 系统用例分析 2.4 系统流…

Java语聊大厅语音聊天小程序系统源码

语聊大厅语音聊天小程序&#xff1a;遇见声音的温暖角落 &#x1f3a7; 【初识语聊大厅&#xff0c;声音的奇妙邂逅】 在这个快节奏的时代&#xff0c;你是否渴望一份不被视线束缚的真诚交流&#xff1f;语聊大厅语音聊天小程序&#xff0c;就是你我之间最温柔的桥梁。轻轻一…

禅道项目管理软件安装教程

一、禅道软件简介 禅道项目管理软件是一款国产开源项目管理软件。它集项目集管理、产品管理、项目管理、质量管理、DevOps、知识库、BI效能、工作流、学堂、反馈管理、组织管理和事务管理于一体&#xff0c;是一款专业的研发项目管理软件&#xff0c;完整覆盖了研发项目管理的…

提升Windows录屏体验:3款顶级电脑录屏软件推荐!

Hey&#xff01;伙伴们&#xff0c;是不是有时候会觉得需要录屏呢&#xff1f;比如做个教学视频啦、直播玩游戏啦&#xff0c;或者是把重要的会议内容记录下来。这时候有一款好的电脑录屏软件简直不要太棒&#xff01;作为你们身边的科技小能手&#xff0c;今天我就来给大家安利…

vue2前端监听usb

在 Vue2 前端应用中监听 USB 设备的插入和拔出事件&#xff0c;可以使用浏览器提供的 WebUSB API。这需要运行在支持 WebUSB API 的浏览器上&#xff0c;并且用户需要授予相应的权限。 以下是一个示例&#xff0c;展示如何在 Vue2 项目中监听 USB 设备的插入和拔出事件。 1. …

【practise】string_atoi

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

新160个crackme - 019-Acid Bytes.3

运行分析 需要破解Name和Serial PE分析 upx壳 linux系统&#xff1a;upx -d CrackMe3.exe 脱壳发现是Delphi系统&#xff0c;32位 静态分析&动态调试 找到关键字符串&#xff0c;进入关键函数 静态分析&#xff0c;发现了Name和Serial明文 验证成功

深入理解 Git `git add -p` 命令中的交互选项

个人名片 🎓作者简介:java领域优质创作者 🌐个人主页:码农阿豪 📞工作室:新空间代码工作室(提供各种软件服务) 💌个人邮箱:[2435024119@qq.com] 📱个人微信:15279484656 🌐个人导航网站:www.forff.top 💡座右铭:总有人要赢。为什么不能是我呢? 专栏导…

2 路模拟量转 Lora模块(开关量,0-10V,4-20ma)

一、功能概述 本产品是一款无线中继器&#xff0c;将 0~ 10V 电压信号转为无线信号&#xff0c; 通过无线方式远传&#xff0c;实现远程通信功能。采用 Lora 无线通信技术&#xff0c; 工作中心频率 433M&#xff0c;空旷传输距离 7000 米。点对点电流远传&#xff0c;用无 线…

智慧工厂数字孪生解决方案

项目背景 随着工业自动化和智能化的不断深入&#xff0c;智慧工厂正成为制造业的新标杆。数字孪生技术作为智慧工厂的核心&#xff0c;通过物理模型、传感器更新、运行历史等数据的集成&#xff0c;实现对现实世界的映射&#xff0c;反映实体装备的全生命周期过程。 方案简介 …

Nacos在Docker上单机模式部署

文章目录 前言一、Nacos二、单机Docker部署 前言 Nacos是阿里巴巴开源的一款用于动态服务发现、配置管理和服务管理的平台。它是“Dynamic Naming and Configuration Service”的缩写&#xff0c;旨在帮助用户实现微服务架构中的服务注册与发现、配置管理、动态DNS服务等功能。…

【一文了解大数据及数据要素,浅说隐私计算、联邦学习】

大数据 不等于 数据要素 大数据&#xff1a;大数据指的是体量巨大、增长迅速且结构复杂的数据集合。传统的数据处理工具无法有效存储和分析这些数据。大数据的处理涉及新的技术和方法&#xff0c;以提取有用的信息和知识。 数据作为新型生产要素&#xff0c;是数字化、网络化、…

C语言bsearch函数

目录 开头1.什么是bsearch函数2.bsearch函数的第五个参数的写法3.bsearch函数的实际运用有序数组查询有序字符串查询有序二维字符串数组查询 结尾 开头 大家好&#xff0c;我叫这是我58。今天&#xff0c;我们来学一下关于C语言里的bsearch函数的一些知识。 1.什么是bsearch函…

Ubuntu系统中下载安装Checkmk,搭建网络监控系统

文章目录 checkmk是什么&#xff1f;下载安装checkmkUbuntu系统安装选择checkmk版本下载checkmk安装checkmk检查checkmk版本创建checkmk站点启动checkmk及站点 推荐阅读 checkmk是什么&#xff1f; Checkmk 是一款开源的、可扩展的、企业级的网络监控工具。Checkmk提供了丰富的…

unity2D游戏开发14漫游

漫游算法 让敌人在地图上漫游,发现玩家在附加,就会追击,直到玩家逃跑或者杀死玩家 将Enemy预购件拖进场景,并将实例EnemyObject添加CircleCollider2D,选中Is Trigger复选框 创建漫游脚本 选中EnemyObject,点击Animation,右击enemy-idle-1,选择Set as Layer Default St…