Android数据库备份后恢复异常:Toast显示成功但数据库未挂载求助
问题分析与解决方案
看起来你的数据库导入逻辑存在几个关键问题,导致虽然Toast提示成功,但实际数据库并未更新。我来一步步帮你排查和修复:
核心问题点
1. 导入逻辑完全反转
你当前的导入代码把源文件和目标文件搞反了:
- 备份时,你把应用内的数据库(
currentDB)复制到SD卡的DBBackupTest文件; - 但导入时,你却尝试把一个不存在的
/storage/emulated/legacy/DBBackup文件复制到SD卡的DBBackupTest,这等于完全没修改应用内的数据库!
2. 硬编码数据库路径不可靠
你用了硬编码的/storage/emulated/legacy/DBBackup作为应用数据库路径,这是错误的:应用的私有数据库存储在/data/data/你的包名/databases/目录下,不同设备、不同版本的路径可能不同,必须用系统API获取正确路径。
3. 未关闭数据库连接
如果应用正在使用数据库(比如有未关闭的SQLiteDatabase实例),直接复制数据库文件会导致SQLite读取缓存数据,新复制的文件不会立即生效,甚至可能复制失败。
修正后的代码
优化后的备份代码(可选,增加可读性)
给备份文件加上.db后缀,方便识别,同时修正路径拼接的冗余:
private void DBBackup() { try { File sd = Environment.getExternalStorageDirectory(); // 获取应用数据库的完整路径,无需再用data目录拼接 String currentDBPath = getContext().getDatabasePath(DBHelper.DB_NAME).getPath(); // 给备份文件加.db后缀,方便后续验证 String backupDBPath = "DBBackupTest.db"; File currentDB = new File(currentDBPath); File backupDB = new File(sd, backupDBPath); if (currentDB.exists()) { FileChannel src = new FileInputStream(currentDB).getChannel(); FileChannel dst = new FileOutputStream(backupDB).getChannel(); dst.transferFrom(src, 0, src.size()); src.close(); dst.close(); Toast.makeText(getContext(), "Export Successful!", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(getContext(), "Database not found!", Toast.LENGTH_SHORT).show(); } } catch (Throwable e) { e.printStackTrace(); Toast.makeText(getContext(), "Export Failed!", Toast.LENGTH_SHORT).show(); } }
修正后的导入代码
解决了路径反转、硬编码、数据库连接关闭的问题:
private void DBImport() { try { File sd = Environment.getExternalStorageDirectory(); // 获取应用数据库的正确路径 String currentDBPath = getContext().getDatabasePath(DBHelper.DB_NAME).getPath(); // 和备份时一致的备份文件名 String backupDBPath = "DBBackupTest.db"; File backupDB = new File(sd, backupDBPath); File currentDB = new File(currentDBPath); // 先检查备份文件是否存在 if (!backupDB.exists()) { Toast.makeText(getContext(), "Backup file not found!", Toast.LENGTH_SHORT).show(); return; } // 关键:导入前关闭所有数据库连接 // 假设你的DBHelper是单例模式,提供close方法关闭数据库 DBHelper.getInstance(getContext()).close(); if (sd.canRead()) { FileChannel src = new FileInputStream(backupDB).getChannel(); FileChannel dst = new FileOutputStream(currentDB).getChannel(); dst.transferFrom(src, 0, src.size()); src.close(); dst.close(); Toast.makeText(getContext(), "Import Successful!", Toast.LENGTH_SHORT).show(); // 导入后重新打开数据库连接 DBHelper.getInstance(getContext()).getWritableDatabase(); } } catch (Throwable e) { Toast.makeText(getContext(), "Import Failed!", Toast.LENGTH_SHORT).show(); e.printStackTrace(); } }
额外注意事项
权限处理:
- Android 6.0+ 需要动态申请
READ_EXTERNAL_STORAGE和WRITE_EXTERNAL_STORAGE权限; - Android 10+ 由于Scoped Storage限制,直接访问SD卡根目录可能失效,建议使用MediaStore或存储访问框架(SAF)来处理备份文件。
- Android 6.0+ 需要动态申请
Stetho 刷新问题:
导入后如果Stetho看不到新数据库,尝试重启应用或重新连接Stetho,因为Stetho可能缓存了旧的数据库快照。备份文件验证:
可以把SD卡上的DBBackupTest.db导出到电脑,用SQLite浏览器打开,确认备份的内容是正确的,再进行导入。
内容的提问来源于stack exchange,提问作者FroyoDevourer
相关产品推荐
相关产品推荐

