InputStream mInput = mContext.getAssets().open(DB_NAME); 拋出 IOException,導致跳入 catch 區塊。原因通常為:
assets/ 根目錄(或子目錄路徑不匹配)。public class DatabaseHelper extends SQLiteOpenHelper {
private static String DB_NAME = "app.db";
private static String DB_PATH = ""; // 運行時動態決定
private final Context context;
public DatabaseHelper(Context context) {
super(context, DB_NAME, null, 1);
this.context = context;
DB_PATH = context.getDatabasePath(DB_NAME).getParent() + "/";
}
public void createDatabase() throws IOException {
if (!checkDatabase()) {
getReadableDatabase(); // 建立空資料庫檔案
close();
copyDatabase();
}
}
private boolean checkDatabase() {
File dbFile = new File(DB_PATH + DB_NAME);
return dbFile.exists();
}
private void copyDatabase() throws IOException {
InputStream is = context.getAssets().open(DB_NAME);
OutputStream os = new FileOutputStream(DB_PATH + DB_NAME);
byte[] buffer = new byte[1024];
int length;
while ((length = is.read(buffer)) > 0) {
os.write(buffer, 0, length);
}
os.flush(); os.close(); is.close();
}
@Override public void onCreate(SQLiteDatabase db) {}
@Override public void onUpgrade(SQLiteDatabase db, int oldV, int newV) {}
}
// Application 或首個 Activity onCreate
DatabaseHelper helper = new DatabaseHelper(this);
try {
helper.createDatabase();
} catch (IOException e) {
e.printStackTrace();
}
SQLiteDatabase db = helper.getReadableDatabase();
Cursor c = db.rawQuery("SELECT * FROM my_table", null);
// ...
c.close(); db.close();
若 assets 單檔超過 1MB(舊版 Android 限制),可將資料庫拆分為多個壓縮檔(.zip、.sqlite3.gz),首次啟動時解壓合併。
adb shell 進入 /data/data/pkg/databases/ 檢查檔案大小。sqlite3 指令開啟驗證表結構與資料。