SQLite: No Such Table Error Android P问题

SQLite: No Such Table Error Android P problem

直到 Android P 我的代码一切正常,但现在 Android P 我在使用数据库时遇到很多问题。

我将 .db sqlite 数据库文件存储在资产文件夹中。我正在将它们导入 android 的数据库 space 并且在 Android P 之前它工作正常。在 android P 中我得到这个异常:SQLite: No Such Table Error

我在这里搜索并找到了这个,并尝试应用已接受的答案:

问题是现在我遇到了另一个问题,但它仍然不起作用。现在我遇到的问题是 每次我尝试检查数据库是否已经存在时,此代码始终 returns 为真,因此我从未创建数据库 。即使没有创建数据库,即使最近安装了应用程序:

private boolean checkIfDBExists() {
    File dbFile = new File(DB_COMPLETE_PATH);
    return dbFile.exists();
}

我的源码是之前引用的Whosebug问题中accepted answer的源码

新的Android P获取数据库路径所需的方式:

public static String getDatabasePath(String fileNname){
    MySQLiteOpenHelper helper = new MySQLiteOpenHelper(ApplicationContextProvider.getContext(), fileNname);
    SQLiteDatabase database = helper.getReadableDatabase();
    String path = database.getPath();
    database.close();
    return path;
}

public class MySQLiteOpenHelper extends SQLiteOpenHelper {
    public MySQLiteOpenHelper(Context context, String databaseName) {
        super(context, databaseName, null, 2);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {

    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

    }

    @Override
    public void onOpen(SQLiteDatabase db) {
        super.onOpen(db);
        db.disableWriteAheadLogging();
    }
}

我的 DBHelper class:

public class DbHelper extends SQLiteOpenHelper{ 
    private  String DB_NAME;
    private  String DB_COMPLETE_PATH;
    private SQLiteDatabase mDataBase;
    private static final int DATABASE_VERSION = 1;

    public DbHelper(String name) throws IOException {
        super(ApplicationContextProvider.getContext(), name+".db", null, DATABASE_VERSION);
        this.DB_NAME = name+".db";
        this.DB_COMPLETE_PATH = Util.getDatabasePath(DB_NAME);

        boolean mustOverWriteDB; 

        if (checkIfDBExists()==false) {
            createDataBase();
        }

        openDataBase();
    }

    private void createDataBase() throws IOException {
        this.getReadableDatabase();
        try {           
            copyDataBase();            
        } catch (IOException e) {           
            throw new RuntimeException(e);
        }
    }

    public void copyDataBase() throws IOException {
        InputStream myInput = App.getInstance().getAssetsFile(DB_NAME);
        String outFileName = DB_COMPLETE_PATH;
        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();
    }
}

在您的 DBHelper class 中,您在测试方法 Util.getDatabasePath(DB_NAME) 中是否存在数据库之前创建数据库。此行创建数据库

this.DB_COMPLETE_PATH = Util.getDatabasePath(DB_NAME);

通过调用此方法,您 sql open helper 创建了数据库(在您的情况下为空,因为在 OnCreate() 方法中没有发生任何事情)。

如果您将数据库存储在默认应用程序的数据库路径中,那么您可以通过下一个片段检查数据库是否存在:

File f = context.getDatabasePath("my_database.db");
if(f.exists()) {
   //Your code if DB exist
} else {
   //Your code if DB doesn't exist
}

禁用 WAL 的更好地方是 SQLiteOpenHelper 中的 onConfigure() 方法

Arg 终于解决了它在 this.getReadableDatabase();

之后添加 this.close();

那个打开的连接正在生成原来没有这样的 table 异常

所以我用了Util.getDatabasePath(DB_NAME);而不是 中提出的复杂解决方案,现在代码更简单

非常感谢@LifeStyle 找到了真正的问题。

现在代码简单多了:

public static String getDatabasePath(String fileNname){
    return ApplicationContextProvider.getContext().getDatabasePath(fileNname).getAbsolutePath();
}

public class DbHelper extends SQLiteOpenHelper{
    private String DB_NAME;
    private String DB_COMPLETE_PATH;
    private SQLiteDatabase mDataBase;
    private static final int DATABASE_VERSION = 1;

    public DbHelper(String name) throws IOException {
        super(ApplicationContextProvider.getContext(), name+".db", null, DATABASE_VERSION);
        this.DB_NAME = name+".db";
        this.DB_COMPLETE_PATH = Util.getDatabasePath(DB_NAME);

        if (checkIfDBExists()==false){
            createDataBase();
        }

        openDataBase();
    }

    private void createDataBase() throws IOException {
        this.getReadableDatabase();
        this.close();
        try {           
            copyDataBase();            
        } catch (IOException e) {           
            throw new RuntimeException(e);
        }
    }

    private boolean checkIfDBExists() {
        File dbFile = new File(DB_COMPLETE_PATH);
        return dbFile.exists();
    }
}

我的 Android P 问题通过在 this.getReadableDatabase();

之后添加 this.close(); 得到解决
`private void createDataBase() throws IOException {
    this.getReadableDatabase();
    this.close(); 
    try {           
        copyDataBase();            
    } catch (IOException e) {           
        throw new RuntimeException(e);
    }
}`

[

将此路径添加到您的数据库

String dbPath = "/data/data/" + mContext.getPackageName() + "/cache/" + mDataBaseName;

实际上我将 SQLiteDatabase 的对象作为静态对象,所以我遇到了这个问题。