You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android 10 如何在Documents/MyFolder下创建SQLite数据库

Android 10 该场景适配结论

你拿到的/tree/home:/document/home:MyFolder是存储访问框架(SAF)返回的内容URI路径,不是Linux文件系统的真实路径,直接拼接字符串传给openOrCreateDatabase、或者用File类校验必然失败。

先直接回答你的两个疑问:

  • Android 10 强制启用分区存储,且没有提供Android 11才有的全局文件访问权限(MANAGE_EXTERNAL_STORAGE),在没有特殊配置的前提下,就算你知道文件夹真实存储路径是/storage/emulated/0/Documents/MyFolder,也没有权限直接通过File类访问。
  • 不要尝试从SAF返回的URI中解析真实文件路径:不同厂商ROM的URI格式不统一,就算解析出真实路径,你也没有该路径的访问权限,这条路完全走不通。

可行适配方案

方案1:合规SAF实现(无特殊权限要求,适配成本中等)

不要取URI的path字段拼接路径,直接通过DocumentFile在目标目录下创建数据库文件,再通过ContentResolver获取文件描述符打开SQLite数据库,参考实现:

// 在ActivityResult回调中,判断RESULT_OK之后
Uri treeUri = result.getData().getData();
// 首先持久化URI权限,否则应用重启后权限会失效
int takeFlags = result.getData().getFlags() & (Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
mContext.getContentResolver().takePersistableUriPermission(treeUri, takeFlags);

DocumentFile pickedDir = DocumentFile.fromTreeUri(mContext, treeUri);
DocumentFile newDir = pickedDir.findFile("MyFolder");
if (newDir == null) {
    newDir = pickedDir.createDirectory("MyFolder");
}

// 查找或创建数据库文件
DocumentFile dbFile = newDir.findFile("MyDatabase.sqlite");
if (dbFile == null) {
    dbFile = newDir.createFile("application/x-sqlite3", "MyDatabase.sqlite");
}

// 通过文件描述符打开数据库
try (ParcelFileDescriptor pfd = mContext.getContentResolver().openFileDescriptor(dbFile.getUri(), "rw")) {
    mDb = SQLiteDatabase.openDatabase(pfd.getFileDescriptor(), null, SQLiteDatabase.OPEN_READWRITE);
} catch (Exception e) {
    Log.e(TAG, "数据库打开失败", e);
}

注意:通过该方式打开的数据库,不要做任何依赖文件路径的操作,所有数据库操作直接使用返回的SQLiteDatabase实例即可。

方案2: legacy兼容模式(老项目快速适配,成本最低)

如果老项目改造成本过高,可以在AndroidManifest.xml的<application>标签下添加如下配置:

android:requestLegacyExternalStorage="true"

该配置会在Android 10系统上临时关闭分区存储,你可以沿用旧版本逻辑,直接使用真实文件路径/storage/emulated/0/Documents/MyFolder/MyDatabase.sqlite调用openOrCreateDatabase,不需要修改原有数据库逻辑。

提示:该配置在Android 11及以上系统会被自动忽略,你已经完成Android 11+的全路径访问适配的话,只要加版本判断逻辑,不会影响高版本系统的运行表现。

避坑说明

  • 不要使用网上流传的各类「URI转真实路径」工具类:这类方法在Android 10+上要么解析出的路径错误,要么解析后没有访问权限,没有实际使用价值。
  • 使用SAF方案必须调用takePersistableUriPermission持久化权限,否则应用重启后之前获取的URI会直接报权限错误。
  • Android 10没有开放全文件访问权限的申请入口,不要尝试在Android 10上适配MANAGE_EXTERNAL_STORAGE权限,该权限仅在Android 11及以上系统生效。

内容的提问来源于stack exchange,提问作者SparkyNZ

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 09:51:44