Marshmallow设备SD卡无法保存数据至Android文件夹外求助
解决安卓6.0设备上SD卡Android文件夹外写入失败的问题
首先咱们得先理清楚你遇到的核心限制:从Android 4.4(KitKat)开始,第三方应用默认只能访问自身在SD卡上的私有目录(就是你现在用的/storage/4130-1912/Android/data/com.enable/files),要写入到Android文件夹之外的目录,得满足几个前提条件,我给你一步步拆解:
1. 先搞定必要的权限申请
安卓6.0(Marshmallow)开始要求动态申请存储权限,你得先在Manifest里声明权限:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
然后在代码里动态申请,确保用户授权后再进行写入操作:
// 检查权限是否已授权 if (ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { // 申请权限 ActivityCompat.requestPermissions(activity, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1001); // 自定义请求码 }
2. 优先写入系统公共目录(避开沙箱限制)
即便拿到了存储权限,你也不能随意在SD卡根目录创建自定义文件夹——这是安卓的沙箱规则限制。你只能写入系统预设的公共目录,比如Documents、Pictures、Downloads这些。举个例子,获取SD卡的Documents目录并创建子文件夹:
File[] externalDirs = ContextCompat.getExternalFilesDirs(context, null); if (externalDirs.length > 1 && externalDirs[1] != null) { // 从私有目录路径中提取SD卡根路径 String sdCardRoot = externalDirs[1].getAbsolutePath().split("/Android/")[0]; // 目标目录:SD卡Documents下的MyAppData文件夹 File targetDir = new File(sdCardRoot + "/Documents/MyAppData"); if (!targetDir.exists()) { boolean isCreated = targetDir.mkdirs(); if (isCreated) { // 目录创建成功,现在可以在这里写入文件了 Log.d("SDCard", "目录创建成功:" + targetDir.getAbsolutePath()); } else { Log.e("SDCard", "目录创建失败,检查权限或SD卡状态"); } } }
3. 必须写入自定义目录?用存储访问框架(SAF)
如果你的需求一定要在Android文件夹外创建完全自定义的目录(比如/storage/4130-1912/MyCustomFolder),那只能通过SAF让用户手动授权该目录的读写权限,步骤如下:
- 启动SAF的目录选择器,让用户选要授权的目录:
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE); startActivityForResult(intent, 1002); // 自定义请求码
- 在
onActivityResult中处理授权结果,持久化权限并操作目录:
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == 1002 && resultCode == RESULT_OK) { Uri treeUri = data.getData(); // 持久化权限,确保重启App后依然有效 getContentResolver().takePersistableUriPermission(treeUri, Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); // 使用DocumentFile操作目录和文件 DocumentFile rootDir = DocumentFile.fromTreeUri(this, treeUri); DocumentFile customDir = rootDir.createDirectory("MyCustomFolder"); // 创建测试文件并写入内容 DocumentFile newFile = customDir.createFile("text/plain", "test.txt"); try (OutputStream os = getContentResolver().openOutputStream(newFile.getUri())) { os.write("测试SD卡自定义目录写入".getBytes()); } catch (IOException e) { e.printStackTrace(); } } }
对你现有代码的补充说明
你当前的代码是正确获取SD卡私有目录的方式,但要注意:
- 当
paths[1]不为空时,它就是SD卡上的App私有目录,无需额外权限就能读写 - 只要想访问Android文件夹之外的区域,就必须走上面的权限申请或SAF流程
最后提醒:在安卓6.0设备上,一定要确保动态权限申请成功后再尝试写入,否则会直接抛出SecurityException哦。
内容的提问来源于stack exchange,提问作者Pankaj Thapa




