錯誤代碼分析
String filePath = "data/data/com.datab.cn/mobile.db"; // 缺少前導 "/"
File jhPath = new File(filePath);
SQLiteDatabase.openOrCreateDatabase(jhPath, null); // 參數錯誤:第一參數需文件路徑字符串
核心問題
- 路徑缺少根目錄:應為
/data/data/package.name/databases/。
- assets 數據庫不可直接打開:assets 內文件只讀,必須先複製到應用私有目錄。
openOrCreateDatabase(String path, ...) 接受路徑字符串,非 File 對象。
標準複製流程
private static final String DB_NAME = "mobile.db";
private static final String DB_PATH = "/data/data/" + context.getPackageName() + "/databases/";
public SQLiteDatabase openDatabase(Context context) {
File dbFile = new File(DB_PATH + DB_NAME);
if (dbFile.exists()) return SQLiteDatabase.openDatabase(dbFile.getAbsolutePath(), null, SQLiteDatabase.OPEN_READWRITE);
// 複製 assets → 目標目錄
File dir = new File(DB_PATH);
if (!dir.exists()) dir.mkdirs();
try (InputStream is = context.getAssets().open(DB_NAME);
FileOutputStream fos = new FileOutputStream(dbFile)) {
byte[] buffer = new byte[1024];
int len;
while ((len = is.read(buffer)) > 0) fos.write(buffer, 0, len);
} catch (IOException e) { throw new RuntimeException("DB copy failed", e); }
return SQLiteDatabase.openDatabase(dbFile.getAbsolutePath(), null, SQLiteDatabase.OPEN_READWRITE);
}
最佳實踐
- 使用
SQLiteAssetHelper 庫(com.readystatesoftware.sqliteasset:sqliteassethelper:+)一行代碼搞定複製與升級。
- 數據庫版本升級實現
onUpgrade 執行遷移腳本。
- 避免在主線程複製大數據庫,啟動時顯示進度或放入線程池。