如何在Android 13及兼容5/6/7低版本系统中低权限保存文件至外部存储?
适配Android 5/6/7至13的低权限文件保存方案
以下是针对不同Android版本的低权限文件保存方案,覆盖API 21(Android 5)至API 33(Android 13):
一、应用私有目录存储(无权限要求)
所有版本均无需申请存储权限,文件仅当前应用可访问,卸载应用时自动删除,适合仅应用自用的文件。
1. 内部私有目录
存储在系统分配的应用专属内部空间:
// 获取内部文件目录,创建自定义文件 File internalFile = new File(getFilesDir(), "app_data.txt"); // 获取内部缓存目录,适合临时文件 File internalCache = new File(getCacheDir(), "temp_cache.txt");
2. 外部私有目录
存储在外部存储的应用专属分区(Android 4.4+支持):
// 获取外部文件目录,可指定子目录如文档、图片 File externalDocDir = getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS); File externalFile = new File(externalDocDir, "app_doc.txt"); // 获取外部缓存目录 File externalCacheDir = getExternalCacheDir();
二、公共媒体目录存储(按需申请权限)
适合保存图片、视频、音频等媒体文件,允许其他应用访问,权限要求随版本变化:
Android 10(API 29)及以上
无需申请WRITE_EXTERNAL_STORAGE权限,直接通过MediaStore API插入文件:
ContentValues values = new ContentValues(); values.put(MediaStore.MediaColumns.DISPLAY_NAME, "my_photo.jpg"); values.put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg"); // 指定存储路径到公共图片目录下的自定义子文件夹 values.put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_PICTURES + "/MyApp"); Uri mediaUri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values); if (mediaUri != null) { try (OutputStream os = getContentResolver().openOutputStream(mediaUri)) { // 写入文件内容 os.write("media content".getBytes()); } catch (IOException e) { e.printStackTrace(); } }
Android 5-9(API 21-28)
需要申请WRITE_EXTERNAL_STORAGE权限,Android 6(API 23)及以上需动态申请:
// 检查权限 if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { // 动态申请权限 ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 100); return; } // 写入公共图片目录 File publicPicDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "MyApp"); if (!publicPicDir.exists()) publicPicDir.mkdirs(); File publicFile = new File(publicPicDir, "my_photo.jpg"); try (FileOutputStream fos = new FileOutputStream(publicFile)) { fos.write("media content".getBytes()); } catch (IOException e) { e.printStackTrace(); }
三、存储访问框架(SAF)通用方案(无权限要求)
Android 4.4(API 19)及以上支持,无需申请存储权限,由用户选择存储目录,适配所有目标版本到13,适合需要用户自主选择存储位置的场景:
1. 打开目录选择器
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE); startActivityForResult(intent, 200);
2. 处理选择结果并操作文件
@Override protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == 200 && resultCode == RESULT_OK && data != null) { Uri treeUri = data.getData(); // 持久化权限,重启应用后仍可访问 getContentResolver().takePersistableUriPermission(treeUri, Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); // 创建新文件 DocumentFile pickedDir = DocumentFile.fromTreeUri(this, treeUri); DocumentFile newFile = pickedDir.createFile("text/plain", "user_selected_file.txt"); if (newFile != null) { try (OutputStream os = getContentResolver().openOutputStream(newFile.getUri())) { os.write("SAF saved content".getBytes()); } catch (IOException e) { e.printStackTrace(); } } } }
方案选型建议
- 仅应用自用文件:优先选应用私有目录,无权限问题,适配最简单。
- 共享媒体文件:选公共媒体目录,Android10+无需权限,兼容性好。
- 用户自主选存储位置或操作非媒体公共文件:选SAF框架,完全无权限要求,跨版本通用。
内容的提问来源于stack exchange,提问作者Aman
相关产品推荐
相关产品推荐

