Media Store 分区存储

文章讲述了在Android应用中向Download目录及其子目录写入文件时遇到的异常,以及提供了解决方案,包括手动清理、申请权限和使用MediaStoreAPI。同时介绍了MediaStore查询文件的方法和示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近测试把文件写入到系统Download目录时发现直接把文件写入到Download中时没有问题。但是如果在Download中添加了一级目录,比如Download/Test时,第一次安装app,而且download目录下没有Test时,可以正常写入文件。但是卸载重装app或者Download中原来就有Test目录,写入文件时就会出现以下异常

文件写入代码如下:

    private fun createFile1(){
        val path = "${Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)}/Test"
        val directory = File(path)
        if(!directory.exists()){
            directory.mkdirs()
        }
        val file = File(directory,"test.txt")
        FileOutputStream(file).use { outputStream->outputStream.write("Hello world!".toByteArray()) }
    }

解决方式用三种,第一种是手动删除掉Download中的Test目录,或者创建子目录时确保子目录在Download中不存在,这种解决方法简单粗暴。

第二种就是申请所有文件管理权限。

第三种就是用MediaStore写入文件,代码如下:

MediaStore 写入文件
    /**
     * 创建文件到download目录
     */
    private fun createFile() {
        val values = ContentValues().apply {
            put(MediaStore.MediaColumns.DISPLAY_NAME, "sdf.txt")// 文件名
            put(MediaStore.MediaColumns.MIME_TYPE, "text/plain")// 文件类型
            put(MediaStore.MediaColumns.RELATIVE_
<think>好的,我需要帮助用户理解一段用于测试Android MediaStore API访问权限限制的Java代码。首先,用户提到的代码可能与Android的存储权限相关,特别是在Android 11及以上版本中,作用域存储(Scoped Storage)的实施改变了应用访问外部存储的方式。根据引用[1],Android 11引入了更严格的存储权限管理,应用需要通过MediaStore API访问共享文件,而不是直接使用文件路径。 接下来,我需要分析用户提供的代码结构。虽然用户没有给出完整的代码,但根据常见的安全测试场景,这类代码可能涉及检查应用是否有权限访问MediaStore中的特定内容URI,或者尝试绕过权限限制。例如,代码可能尝试访问其他应用创建的媒体文件,验证是否有权限被拒绝。 此外,引用[2]提到配套设备管理API,这可能与测试中涉及的设备权限有关,但主要焦点应在MediaStore的访问。引用[3]指出Android R(即Android 11)在Activity部分的变更,特别是子Activity方法的弃用,这可能影响测试代码中的Activity启动方式。而引用[4]展示了一个Compose UI的示例,可能与测试代码的界面部分相关,但具体测试逻辑应集中在MediaStore的操作上。 需要指出代码中可能的关键点:使用ContentResolver查询MediaStore的URI,检查是否有权限异常(如SecurityException),或者尝试通过文件路径访问已被限制的数据。例如,若代码尝试直接访问/storage/emulated/0/DCIM/...路径,在Android 11上会触发权限错误,而应改用MediaStore API。 最后,应提醒用户注意Android版本差异,确保测试覆盖不同API级别的行为,并建议使用官方推荐的Scoped Storage最佳实践,如使用MediaStore、DocumentsProvider等API进行安全的文件访问。同时,参考官方文档(引用[1])来验证代码是否符合最新的存储策略。</think>### 代码功能与逻辑解析 您提供的代码片段虽不完整,但根据描述可推断其核心目标是测试Android系统对$MediaStore$ API的访问权限限制,主要涉及作用域存储(Scoped Storage)策略的合规性验证。以下是关键分析点: 1. **权限验证场景** 代码可能通过以下方式触发权限检查: ```java try { ContentResolver resolver = context.getContentResolver(); // 尝试访问非本应用创建的媒体文件URI resolver.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, null, "_data=?", new String[]{"/sdcard/DCIM/foreign_image.jpg"}, null); } catch (SecurityException e) { // 捕获权限异常,验证系统是否阻止非法访问[^1] } ``` 此场景验证应用在未申请`READ_EXTERNAL_STORAGE`权限时,能否访问其他应用创建的媒体文件。 2. **文件路径访问限制** Android 11+禁止直接通过文件路径访问共享存储空间[^1]。代码中若包含如下操作会触发系统拦截: ```java File file = new File("/storage/emulated/0/Download/secret.pdf"); if (file.exists()) { // 此处可能返回false,即使文件真实存在 Log.d("TEST", "Bypass failed: 文件路径访问已被阻止"); } ``` 3. **MediaStore API合规性测试** 有效的测试应使用标准API写入文件: ```java ContentValues values = new ContentValues(); values.put(MediaStore.MediaColumns.DISPLAY_NAME, "test_image.jpg"); values.put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg"); Uri uri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values); // 通过Uri获取输出流进行安全写入 ``` ### 安全测试关注点 | 测试类型 | 预期结果 | 实际结果验证方法 | |-------------------|------------------------------------|--------------------------------| | 跨应用媒体文件读取 | 抛出SecurityException | try-catch捕获异常 | | 非媒体目录访问 | 返回空数据集或权限错误 | 检查Cursor返回值 | | 文件路径直接操作 | File.exists()返回false | 日志输出与文件管理器对比 | ### 技术建议 1. 使用`Environment.isExternalStorageLegacy()`判断应用是否启用分区存储 2. 通过`ActivityResultContracts.RequestPermission`动态申请权限 3. 访问自有文件时使用`Context#getExternalFilesDir()`避免权限申请
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值