如何在 Android 7+ 中安全访问和迁移应用专属外部存储文件

小明大大_6972

小明大大_6972

2026-11-05

234人浏览

原创

如何在 Android 7+ 中安全访问和迁移应用专属外部存储文件

本文详解 Android 7.0(Nougat)及以上版本中跨应用访问外部存储(如 SD 卡)的限制与合规方案,重点说明为何直接读写其他应用的 Android/data/ 目录会失败,并介绍通过 Storage Access Framework(SAF)实现安全、用户授权的文件迁移方法。

本文详解 android 7.0(nougat)及以上版本中跨应用访问外部存储(如 sd 卡)的限制与合规方案,重点说明为何直接读写其他应用的 `android/data/` 目录会失败,并介绍通过 storage access framework(saf)实现安全、用户授权的文件迁移方法。

在 Android 7.0(API 24)及更高版本中,系统对应用外部存储的访问实施了严格的沙盒隔离机制。尽管 /storage/sdcard/Android/data/com.test.appA/files/ 和 /storage/sdcard/Android/data/com.test.appB/files/ 在文件系统路径上看似“可见”,但应用 A 默认无法直接读写应用 B 的专属目录——即使已声明 WRITE_EXTERNAL_STORAGE 权限并获得运行时授权。这是因为从 Android 7.0 开始,Android/data/ 下各应用子目录受 Scoped Storage(分区存储)雏形机制保护,每个应用仅对其自身包名对应的目录拥有完全读写权限。

⚠️ 注意:WRITE_EXTERNAL_STORAGE 权限在 Android 10+ 已被大幅弱化,在 Android 11+ 中对 Android/data/ 和 Android/obb/ 目录完全失效;即便在 Android 7–9,该权限也不授予跨包访问其他应用 Android/data/ 目录的能力。

那么,为什么文件管理器类 App 能访问这些路径?它们调用的并非传统存储权限,而是 Storage Access Framework(SAF) —— 一种以用户为中心、基于 Intent 的交互式文件访问机制。

✅ 正确做法:使用 Storage Access Framework(SAF)

SAF 允许应用通过系统提供的文档选择器(DocumentPicker),由用户显式授予对特定目录(如 Android/data/ 下某子目录)的持久读写权限。其核心是 StorageVolume + DocumentFile + takePersistableUriPermission() 的组合。

Android Control
Android Control

通过命令行工具(uiautomator、screencap、input、am)控制安卓设备。优先尝试非 root 执行,失败后自动回退至 root...

下载

示例:请求访问 App B 的专属目录

// 1. 启动 SAF 目录选择器,目标为 App B 的 files 目录
private void requestAppBDirectoryAccess() {
    Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
    // 构造目标 URI(需先获取 Volume UUID 或使用 SAF 探索方式)
    // 实际开发中,通常引导用户手动导航至 /Android/data/com.test.appB/files/
    startActivityForResult(intent, REQUEST_CODE_OPEN_DIRECTORY);
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == REQUEST_CODE_OPEN_DIRECTORY && resultCode == RESULT_OK && data != null) {
        Uri treeUri = data.getData();
        // 2. 获取持久化权限(关键!否则下次重启后失效)
        final int takeFlags = data.getFlags()
                & (Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
        getContentResolver().takePersistableUriPermission(treeUri, takeFlags);

        // 3. 使用 DocumentFile 操作文件
        DocumentFile pickedDir = DocumentFile.fromTreeUri(this, treeUri);
        if (pickedDir != null && pickedDir.canWrite()) {
            // 示例:列出文件
            for (DocumentFile file : pickedDir.listFiles()) {
                Log.d("SAF", "Found: " + file.getName());
            }
            // 示例:将 App A 的某个文件复制到此处(需先获取源文件 DocumentFile)
        }
    }
}

关键注意事项:

  • ? 用户必须手动选择目录:SAF 不支持直接构造 com.test.appB/files 的 URI,必须由用户在系统弹窗中导航并确认。
  • ? 持久化权限需主动申请:调用 takePersistableUriPermission() 是长期访问的前提,否则权限仅在本次会话有效。
  • ? 目标目录需可写:DocumentFile.canWrite() 返回 true 才能执行写入;部分厂商定制系统可能限制对 Android/data/ 的写入(需测试兼容性)。
  • ? 无需声明 READ/WRITE_EXTERNAL_STORAGE:SAF 权限独立于传统存储权限,Android 11+ 应用甚至可完全移除这些危险权限。

✅ 替代方案(有限适用)

  • Shared Preferences / ContentProvider / AIDL:适用于结构化数据共享,不适用于任意文件迁移。
  • 公共媒体目录(如 Environment.DIRECTORY_DOWNLOADS):可自由读写,但需用户接受文件存放位置变更,且不保证隐私性。
  • MediaStore API(Android 10+):适用于图片、音频、视频等媒体文件,对普通文档或应用专属文件支持有限。

总结

在 Android 7+ 上,跨应用迁移 Android/data/ 目录下的文件,唯一合规、稳定且面向未来的方式是 Storage Access Framework(SAF)。它虽需用户交互,却保障了隐私安全与系统一致性。开发者应摒弃“路径硬编码 + 权限强求”的旧思路,转而拥抱以用户授权为核心的现代存储模型。务必在 AndroidManifest.xml 中声明:

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxsdkversion="28"></uses-permission><!-- Android 10+ 可省略,SAF 无需此权限 -->

遵循 SAF 范式,你的应用才能在持续收紧的 Android 存储策略中保持兼容性与用户体验。

相关文章

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

android

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
android开发三大框架
android开发三大框架

android开发三大框架是XUtil框架、volley框架、ImageLoader框架。本专题为大家提供android开发三大框架相关的各种文章、以及下载和课程。

2023.08.14

922

4

android是什么系统
android是什么系统

Android是一种功能强大、灵活可定制、应用丰富、多任务处理能力强、兼容性好、网络连接能力强的操作系统。本专题为大家提供android相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.22

2767

5

android权限限制怎么解开
android权限限制怎么解开

android权限限制可以使用Root权限、第三方权限管理应用程序、ADB命令和Xposed框架解开。详细介绍:1、Root权限,通过获取Root权限,用户可以解锁所有权限,并对系统进行自定义和修改;2、第三方权限管理应用程序,用户可以轻松地控制和管理应用程序的权限;3、ADB命令,用户可以在设备上执行各种操作,包括解锁权限;4、Xposed框架,用户可以在不修改系统文件的情况下修改应用程序的行为和权限。

2023.09.19

5517

7

android重启应用的方法有哪些
android重启应用的方法有哪些

android重启应用有通过Intent、PendingIntent、系统服务、Runtime等方法。本专题为大家提供Android相关的文章、下载、课程内容,供大家免费下载体验。

2023.10.18

725

5

Android语音播放功能实现方法
Android语音播放功能实现方法

实现方法有使用MediaPlayer实现、使用SoundPool实现两种。可以根据具体的需求选择适合的方法进行实现。想了解更多语音播放的相关内容,可以阅读本专题下面的文章。

2024.03.01

964

5

DBeaver怎么导入数据
DBeaver怎么导入数据

DBeaver数据导入专题,整理Excel、CSV、SQL、TXT等常见文件的数据导入方法,涵盖目标数据库选择、数据表创建、字段映射、数据类型设置及导入参数配置等操作,帮助用户将本地文件中的数据写入数据库,并了解批量导入、重复数据处理和导入失败等常见问题的解决方法。

2026.11.05

0

12

DBeaver安全防护教程大全
DBeaver安全防护教程大全

DBeaver安全防护专题,围绕数据库连接安全、账号密码保护和访问权限管理展开,整理SSL/TLS加密连接、SSH隧道、数据库凭据保存及证书验证等配置方法,同时介绍敏感信息保护、远程连接风险和高权限账号使用等注意事项,帮助用户提高数据库日常管理的安全性。

2026.11.05

0

12

DBeaver连接创建与配置教程
DBeaver连接创建与配置教程

本专题聚焦DBeaver数据库连接配置与管理,覆盖从新建连接、选择数据库类型到填写连接参数和验证连接的完整流程。针对MySQL、PostgreSQL、SQL Server等常见数据库,整理相应的连接设置方法,并提供驱动缺失、认证失败和连接异常等问题的排查方向。

2026.11.04

0

16

XORM框架结构体映射与表结构同步
XORM框架结构体映射与表结构同步

本专题围绕XORM框架的结构体映射展开,说明表名与字段的命名策略、xorm标签常用属性、主键自增与时间字段自动填充,并演示Sync2自动建表、增量字段升级、索引声明与反向生成结构体的完整流程。

2026.11.04

0

15

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Excel 教程
Excel 教程

共162课时 | 45.2万人学习

Java 教程
Java 教程

共578课时 | 196.3万人学习

Uniapp从零开始实现新闻资讯应用
Uniapp从零开始实现新闻资讯应用

共64课时 | 9.7万人学习