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

Android 11及以上如何创建公共目录存储卸载不丢失的SQLite备份

解决方案

Android 10开始引入分区存储机制,禁止应用直接访问公共目录的原始路径,Android 11进一步强制该规则,原来的Environment.getExternalStoragePublicDirectory方法已废弃,应用专属目录下的文件会随应用卸载删除,要实现卸载不丢失备份,需要通过MediaStore API向公共存储目录(例如下载目录、文档目录)写入文件。

第一步:修改AndroidManifest配置

添加兼容所需的权限和属性:

<!-- 仅Android 9及以下需要存储权限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="28" />

<application
    ...
    <!-- 兼容Android 10设备 -->
    android:requestLegacyExternalStorage="true">
    ...
</application>

第二步:修改导出数据库的函数代码

替换原有逻辑,Android 10及以上使用MediaStore写入公共下载目录:

private void exportDatabaseNew(LinearLayout linearLayout) {
    FileInputStream fis = null;
    OutputStream output = null;
    try {
        File dbFile = getDatabasePath(DatabaseHelper.DATABASE_NAME);
        fis = new FileInputStream(dbFile);
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd", Locale.US);
        String currentDate = df.format(new Date());
        String backupName = "Survey_" + currentDate + ".db";

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            // Android 10+ 使用MediaStore写入公共下载目录
            ContentValues values = new ContentValues();
            values.put(MediaStore.MediaColumns.DISPLAY_NAME, backupName);
            values.put(MediaStore.MediaColumns.MIME_TYPE, "application/x-sqlite3");
            values.put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_DOWNLOADS + "/Db_Backup");

            ContentResolver resolver = getContentResolver();
            Uri uri = resolver.insert(MediaStore.Downloads.EXTERNAL_CONTENT_URI, values);
            if (uri == null) {
                throw new IOException("Failed to create new MediaStore record");
            }
            output = resolver.openOutputStream(uri);
        } else {
            // Android 9及以下沿用原有逻辑
            File folder = Environment.getExternalStoragePublicDirectory("Db_Backup");
            if (!folder.exists()) {
                folder.mkdirs();
            }
            File myFile = new File(folder, backupName);
            output = new FileOutputStream(myFile);
        }

        // 写入文件逻辑不变
        byte[] buffer = new byte[1024];
        int length;
        while ((length = fis.read(buffer)) > 0) {
            output.write(buffer, 0, length);
        }
        output.flush();
        Snackbar.make(linearLayout, R.string.backup_complete, Snackbar.LENGTH_LONG).show();

    } catch (Exception e) {
        e.printStackTrace();
        Snackbar.make(linearLayout, "备份失败:" + e.getMessage(), Snackbar.LENGTH_LONG).show();
    } finally {
        // 关闭流
        try {
            if (fis != null) fis.close();
            if (output != null) output.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

注意事项

  • 该方案不需要申请MANAGE_EXTERNAL_STORAGE特殊权限,符合谷歌应用商店的政策要求
  • 备份文件会保存在系统下载目录的Db_Backup文件夹下,卸载应用不会被删除
  • 如果需要做备份恢复功能,可以通过MediaStore查询下载目录下后缀为.db的备份文件读取即可
  • 若出现同名备份文件,系统会自动在文件名后加(1)(2)的后缀避免覆盖,也可以自己先查询同名文件再决定是否覆盖

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 01:45:03