Android 9(API 28)从文件路径填充数据库失败,提示表不存在
Android 9 (API 28) 复制Assets数据库后找不到表的问题解决
问题背景
采用Assets目录复制数据库的方案在Android 8.1及以下版本正常运行,但在Android 9(API 28)中启动Exammode Activity时触发SQLiteException,提示找不到Technical表,执行SELECT Id FROM Technical WHERE TopicId ='Che1'语句失败。
复制数据库代码
private static String DB_NAME = "QuotesData.db"; private static String DB_PATH = "/data/data/[PACKAGE NAME]/databases/"; private void copyDataBase() throws IOException { InputStream myInput = context.getAssets().open(DB_NAME); String outFileName = DB_PATH + DB_NAME; OutputStream myOutput = new FileOutputStream(outFileName); byte[] buffer = new byte[1024]; int length; while ((length = myInput.read(buffer)) > 0) { myOutput.write(buffer, 0, length); } myOutput.flush(); myOutput.close(); myInput.close(); }
报错日志
E/AndroidRuntime: FATAL EXCEPTION: main Process: com.in22labs.neet, PID: 23832 java.lang.RuntimeException: Unable to start activity ComponentInfo{com.in22labs.neet/com.in22labs.neet.Quiz.Exammode}: android.database.sqlite.SQLiteException: no such table: Technical (code 1 SQLITE_ERROR): , while compiling: SELECT Id FROM Technical WHERE TopicId ='Che1' at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2913) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3048) at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78) at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108) at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1808) at android.os.Handler.dispatchMessage(Handler.java:106) at android.os.Looper.loop(Looper.java:193) at android.app.ActivityThread.main(ActivityThread.java:6669) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
解决方案
1. 替换硬编码的数据库路径
Android 9及以上版本不推荐硬编码/data/data/[PACKAGE]/databases/路径,改用系统API获取正确路径,避免权限或路径识别问题:
private static String DB_NAME = "QuotesData.db"; // 获取正确的数据库路径 private String getDBPath() { return context.getDatabasePath(DB_NAME).getAbsolutePath(); } private void copyDataBase() throws IOException { InputStream myInput = context.getAssets().open(DB_NAME); String outFileName = getDBPath(); // 确保数据库父目录存在 File dbDir = new File(outFileName).getParentFile(); if (!dbDir.exists()) { dbDir.mkdirs(); } OutputStream myOutput = new FileOutputStream(outFileName); byte[] buffer = new byte[1024]; int length; while ((length = myInput.read(buffer)) > 0) { myOutput.write(buffer, 0, length); } myOutput.flush(); myOutput.close(); myInput.close(); }
2. 禁用SQLite WAL模式
Android 9默认启用WAL(Write-Ahead Logging)模式,复制数据库时若未同步WAL文件会导致数据库不完整。在打开数据库后执行语句禁用WAL:
// 在DataBaseTechnical类的初始化或打开数据库逻辑中添加 SQLiteDatabase db = getWritableDatabase(); db.execSQL("PRAGMA journal_mode=DELETE;");
3. 复制前清理旧数据库文件
若之前存在不完整的数据库副本,会导致加载异常,复制前先删除旧文件:
private void copyDataBase() throws IOException { String outFileName = getDBPath(); File oldDbFile = new File(outFileName); if (oldDbFile.exists()) { oldDbFile.delete(); } // 后续复制逻辑... InputStream myInput = context.getAssets().open(DB_NAME); OutputStream myOutput = new FileOutputStream(outFileName); byte[] buffer = new byte[1024]; int length; while ((length = myInput.read(buffer)) > 0) { myOutput.write(buffer, 0, length); } myOutput.flush(); myOutput.close(); myInput.close(); }
4. 验证数据库复制完整性
复制完成后检查表是否存在,确保复制过程无异常:
// 复制后添加校验逻辑 private boolean isDatabaseValid() { String dbPath = getDBPath(); SQLiteDatabase db = null; Cursor cursor = null; try { db = SQLiteDatabase.openDatabase(dbPath, null, SQLiteDatabase.OPEN_READONLY); cursor = db.rawQuery("SELECT name FROM sqlite_master WHERE type='table' AND name='Technical'", null); return cursor.getCount() > 0; } catch (SQLiteException e) { e.printStackTrace(); return false; } finally { if (cursor != null) cursor.close(); if (db != null) db.close(); } }
调用copyDataBase()后可通过isDatabaseValid()验证,若返回false则重新触发复制流程。
内容的提问来源于stack exchange,提问作者Shakthi
相关产品推荐
相关产品推荐

