当前位置:首页 > 行业动态 > 正文

安卓存储权限访问所有文件系统

Android 10+默认沙盒,仅自身目录,需MANAGE_EXTERNAL_STORAGE等权限及用户授权方可访问全部

安卓存储权限基础概念

存储权限分类

权限名称 作用范围
READ_EXTERNAL_STORAGE 读取外部存储(含SD卡)的任意文件
WRITE_EXTERNAL_STORAGE 向外部存储写入/删除文件
READ_INTERNAL_STORAGE 读取应用安装目录下的内部存储文件(需Root权限才有效)
WRITE_INTERNAL_STORAGE 向应用安装目录下的内部存储写入文件(默认可写,无需额外权限)

存储区域划分

存储类型 路径示例 特点
应用私有目录 /data/data/包名/ 仅限当前应用访问,无需存储权限
外部公共目录 /sdcard//storage/emulated/0/ 所有应用共享,需声明存储权限
系统级目录 /system/ 仅限系统应用访问,普通应用不可读写

Android 10+ 存储权限变革

Scoped Storage机制

  • 核心变化:应用默认只能访问自己的私有目录,访问公共目录需通过特定API。
  • 受影响操作
    • 直接通过文件路径访问/sdcard/Download/等公共目录会失败
    • 必须使用MediaStoreStorage Access Framework访问媒体文件

权限行为调整

权限 Android 10前行为 Android 10+行为
READ_EXTERNAL_STORAGE 可访问全部外部存储文件 仅能访问应用创建的文件和特定媒体目录
WRITE_EXTERNAL_STORAGE 可写入全部外部存储 仅能写入应用专属目录

完整文件系统访问方案

传统权限申请流程(Android 10以下)

// 动态请求权限
ActivityCompat.requestPermissions(
    this, 
    new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
    REQUEST_CODE
);

Android 10+兼容方案

场景 解决方案
访问任意文件 使用Storage Access Framework(通过DocumentFile操作)
管理媒体文件 通过MediaStore数据库接口操作(替代文件路径访问)
文件共享场景 使用ACTION_OPEN_DOCUMENT获取持久化Uri权限

关键API示例

// 通过SAF选择文件
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
startActivityForResult(intent, REQUEST_CODE);
// 通过MediaStore插入图片
ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.DISPLAY_NAME, "test.jpg");
Uri uri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);

特殊文件访问处理

文件类型 访问方式
系统配置文件 需Root权限,通过Runtime.getRuntime().exec()执行系统命令
其他应用安装文件 通过PackageManager查询安装路径,需声明QUERY_ALL_PACKAGES权限(Android 11+)
缓存文件 优先使用应用私有缓存目录(getCacheDir()),无需存储权限

权限问题诊断指南

常见错误及解决方案

现象 原因分析
openFailed: EACCES 未获取存储权限/Android 10+访问受限目录
FileNotFoundException Scoped Storage下路径访问方式错误
SecurityException 尝试访问其他应用私有文件

调试工具推荐

  • ADB命令adb shell ls -l /sdcard/ 查看文件权限
  • 日志监控:使用Logcat过滤TAGStorageManager的日志
  • 模拟器配置:在AVD设置中启用Storage模拟SD卡

相关问题与解答

Q1:如何将旧版存储API迁移到Android 10+?

A

  1. 替换直接文件路径访问为MediaStoreDocumentProvider
  2. 使用Context.getExternalFilesDir()代替Environment.getExternalStorageDirectory()
  3. AndroidManifest.xml添加requestLegacyExternalStorage="true"作为过渡方案

Q2:如何实现跨应用文件共享?

A

  1. 通过setIntent附加Intent.FLAG_GRANT_READ_URI_PERMISSION分享文件Uri
  2. 使用ContentResolvertakePersistableUriPermission()获取长期访问权限
  3. 确保目标应用已声明对应intent-filter(如category.OPENABLE
0