You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

安卓内部存储创建文件夹仅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

火山引擎 最新活动