Android 11下如何通过URI或DocumentFile打开大容量SQLite数据库
通过Uri/DocumentFile打开10GB+大容量RasterLite数据库的实现方案
核心实现思路
Android系统提供的SQLiteDatabase.openDatabase原生支持SQLite URI格式路径,你可以通过ContentResolver拿到目标数据库文件的文件描述符(FD),再拼接成SQLite可识别的FD路径直接打开,不需要把大文件读入内存,也不需要获取文件的绝对路径。
具体实现代码
首先在你已有的目录选择逻辑中找到目标RasterLite数据库文件,再按如下逻辑打开:
// 1. 从选中目录的文件列表中匹配目标RasterLite数据库文件 DocumentFile targetDbFile = null; for (DocumentFile file : fileList) { if (!file.isDirectory() && file.getName().endsWith(".db")/* 替换为你的数据库文件实际后缀 */) { targetDbFile = file; break; } } if (targetDbFile == null) { // 未找到目标文件的异常处理逻辑 return; } try { // 2. 申请目标文件的只读文件描述符 ParcelFileDescriptor pfd = getContentResolver().openFileDescriptor(targetDbFile.getUri(), "r"); if (pfd == null) { return; } // 3. 拼接SQLite支持的FD格式路径,只读模式可加mode=ro避免意外写入 String sqliteFdPath = String.format(Locale.US, "file:/proc/self/fd/%d?mode=ro", pfd.getFd()); // 4. 直接打开数据库,打开全程需保持pfd不被关闭 SQLiteDatabase rasterDb = SQLiteDatabase.openDatabase( sqliteFdPath, null, SQLiteDatabase.NO_LOCALIZED_COLLATORS | SQLiteDatabase.OPEN_READONLY ); // --- 此处写你的数据库业务逻辑 --- // 5. 资源释放,注意顺序:先关数据库,再关文件描述符 rasterDb.close(); pfd.close(); } catch (IOException | SQLiteException e) { // 异常处理逻辑 e.printStackTrace(); }
必要补充配置
你需要对用户选中的目录申请持久化Uri权限,否则App重启后之前拿到的Uri会失效,在onActivityResult获取到目录Uri后添加如下代码:
int takeFlags = resultData.getFlags() & (Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); getContentResolver().takePersistableUriPermission(uri, takeFlags);
注意事项
- 该方案无需将10GB级大文件拷贝到App私有目录,直接操作原文件,不会占用额外存储,也不会消耗过多内存
- 如果你使用的是自定义编译的RasterLite库,确保编译时开启了
SQLITE_ENABLE_URI_FILENAME编译选项(绝大多数主流RasterLite分发版本默认已开启) - 如果你的RasterLite封装库支持直接传入文件描述符作为打开参数,也可以直接传入
pfd.getFd()打开,逻辑和上述方案一致
内容的提问来源于stack exchange,提问作者user2304379
相关产品推荐
相关产品推荐

