Android 13及以上访问内部存储非媒体地图文件的权限问题
Android 13下访问自定义格式地图文件的权限解决方案
一、先清理无效权限
你当前添加的权限里,很多是系统保护权限(普通应用无法获取)或重复权限,完全可以删除:
MOUNT_UNMOUNT_FILESYSTEMS、WRITE_MEDIA_STORAGE、MEDIA_CONTENT_CONTROL、MANAGE_MEDIA:这些是系统级权限,第三方APP无法通过正常渠道获取,直接删除。- 重复的
READ_EXTERNAL_STORAGE、WRITE_EXTERNAL_STORAGE:保留一份即可,且Android 13及以上对非媒体文件,这两个权限已失效。 READ_MEDIA_AUDIO、READ_MEDIA_IMAGES、READ_MEDIA_VIDEO:你的文件是自定义.map格式,不属于媒体类型,这些权限没用,直接删除。
二、针对自定义文件的权限方案
根据文件存储位置,选择对应方案:
方案1:优先使用应用专属目录(无需权限)
如果地图文件可以放在应用的专属存储目录,这是最省心的方案——Android 13及所有版本都不需要任何权限,直接读写。
- 内部专属目录路径:
context.getFilesDir()(对应手机内部存储的Android/data/你的包名/files/) - 外部专属目录路径:
context.getExternalFilesDir(null)(对应外部存储的Android/data/你的包名/files/)
示例代码(读取文件):
File mapFile = new File(context.getFilesDir(), "country.map"); if (mapFile.exists()) { // 执行文件读写操作 }
方案2:访问公共目录(需MANAGE_EXTERNAL_STORAGE权限)
如果文件必须放在公共目录(比如Download、Documents),需要申请MANAGE_EXTERNAL_STORAGE权限,但注意:
- Google Play审核会严格限制该权限的使用,仅允许文件管理器、备份类等特定场景的APP申请,你的地图应用可能无法通过审核。
- 实现步骤:
- 在Manifest中声明权限:
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" tools:ignore="ScopedStorage" /> - 动态申请权限:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { if (!Environment.isExternalStorageManager()) { Intent intent = new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION); intent.setData(Uri.parse("package:" + getPackageName())); startActivity(intent); } }
- 在Manifest中声明权限:
方案3:使用存储访问框架(SAF,无需特殊权限)
这是Google推荐的替代方案,无需申请任何权限,通过让用户手动选择文件/目录来获取访问权限:
- 打开文件选择器获取
.map文件的Uri:Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT); intent.addCategory(Intent.CATEGORY_OPENABLE); intent.setType("*/*"); // 或者指定自定义类型 "application/x-map"(如果系统识别) startActivityForResult(intent, REQUEST_CODE_PICK_MAP_FILE); - 在
onActivityResult(或Activity Result API)中获取Uri后,通过ContentResolver读写:@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == REQUEST_CODE_PICK_MAP_FILE && resultCode == RESULT_OK) { Uri uri = data.getData(); // 读取文件内容 try (InputStream inputStream = getContentResolver().openInputStream(uri)) { // 处理输入流 } catch (IOException e) { e.printStackTrace(); } } }
三、总结
- 优先选择方案1,无需权限且符合Android存储规范;
- 若必须访问公共目录,优先用方案3(SAF),避免审核风险;
- 非必要不要用方案2,否则可能无法通过Google Play审核。
内容的提问来源于stack exchange,提问作者naod_goitom
相关产品推荐
相关产品推荐

