安卓内部存储创建文件夹仅OPPO生效,三星小米等品牌失效问题咨询
问题分析与解决方案
你遇到的这个问题,本质是Android存储权限规则的版本差异加上不同厂商的适配策略导致的。Environment.getExternalStorageDirectory()这个方法在Android 10(API级别29)及以上已经被标记为废弃,而且受限于分区存储(Scoped Storage)的规则,直接在外部存储根目录创建自定义文件夹的操作,在三星、小米这类严格遵循官方规范的厂商设备上会被限制;而OPPO可能在部分系统版本中保留了更宽松的权限策略,所以你的代码能在它上面生效。
具体修复方案
1. 优先使用应用专属外部存储目录(推荐)
如果你的PDF文件夹是用来存储应用私有的文件(不需要其他应用访问),直接用应用专属的外部存储目录就好——这个目录不需要额外申请存储权限,也完全不受分区存储限制:
public void createPDF() { TextView dttt = (TextView)findViewById(R.id.dttt); String da = dttt.getText().toString(); final Cursor cursor = db.getDateWise(da); Document doc = new Document(); try { // 获取应用专属的外部存储目录,路径类似 /storage/emulated/0/Android/data/你的应用包名/files File appPrivateDir = getExternalFilesDir(null); // 在专属目录下创建PDF子文件夹 File pdfDir = new File(appPrivateDir, "PDF"); if (!pdfDir.exists()) { pdfDir.mkdirs(); } Log.d("PDFCrea...", "文件夹创建成功:" + pdfDir.getAbsolutePath()); // 后续的PDF生成、写入操作都基于这个目录即可 // ... 你的PDF处理代码 } catch (Exception e) { Log.e("PDFCreaError", e.getMessage()); e.printStackTrace(); } }
2. 如果需要让其他应用访问文件夹(存到公共目录)
要是你希望PDF能被其他应用找到(比如放在Downloads目录),可以按以下两种方式处理:
方式一:利用公共Downloads目录(兼容Android 10+)
public void createPDF() { TextView dttt = (TextView)findViewById(R.id.dttt); String da = dttt.getText().toString(); final Cursor cursor = db.getDateWise(da); Document doc = new Document(); try { // 获取系统公共的Downloads目录 File publicDownloadDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS); File pdfDir = new File(publicDownloadDir, "CollactionApp/PDF"); if (!pdfDir.exists()) { pdfDir.mkdirs(); } Log.d("PDFCrea...", "文件夹创建成功:" + pdfDir.getAbsolutePath()); // 后续操作 } catch (Exception e) { Log.e("PDFCreaError", e.getMessage()); e.printStackTrace(); } }
注意:Android 10设备上需要在AndroidManifest.xml里添加临时兼容属性:
<application ... android:requestLegacyExternalStorage="true"> </application>
这个属性仅对API 29生效,Android 11及以上需要用下面的方式。
方式二:申请全文件访问权限(Android 11+)
在AndroidManifest.xml中添加权限声明:
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
然后在代码中引导用户开启权限:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { if (!Environment.isExternalStorageManager()) { Intent permissionIntent = new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION); Uri uri = Uri.fromParts("package", getPackageName(), null); permissionIntent.setData(uri); startActivity(permissionIntent); } }
额外注意事项
- 针对Android 9及以下设备,别忘了在Manifest中声明基础存储权限:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
- Android 10及以上系统默认开启分区存储,
requestLegacyExternalStorage只是临时兼容方案,长期来看还是建议适配官方的存储规则。
内容的提问来源于stack exchange,提问作者AJAY ARORA




