SQLite:无此表错误 Android P问题

6

在 Android P 之前,我的代码一切正常,但是在 Android P 上,我在处理数据库时遇到了很多问题。

我有一些 .db SQLite 数据库文件存储在 assets 文件夹中,我将它们导入到 Android 的数据库空间中,并且在 Android P 之前一直都可以工作。但是在 Android P 上,我遇到了这个异常:SQLite: No Such Table Error

我在 StackOverflow 上搜索并找到了这个问题的解决方案,我尝试了该答案的方法:Android P - 'SQLite: No Such Table Error' after copying database from assets

但现在我又遇到了另一个问题,仍然无法解决。现在,每次我尝试检查数据库是否已存在时,此代码总是返回 true,因此我从未创建数据库。即使数据库尚未创建,即使应用程序最近安装:

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

我的源代码是之前引用的Stack Overflow问题中被接受回答的源代码。

获取数据库路径的新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类:

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();
    }
}
5个回答

13

通过在this.getReadableDatabase();后添加this.close();,Arg最终解决了问题。

那个打开的连接是导致原始找不到表异常的原因。

所以我使用了Util.getDatabasePath(DB_NAME);代替在Android P - 'SQLite: No Such Table Error' after copying database from assets中提出的繁琐解决方案,现在代码更加简单了。

非常感谢@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 Pie 设备上它都无法正常工作。您能提供其他建议吗? - Madhan
即使添加了这个,我仍然遇到同样的问题。你还有其他建议吗? - Deepak Rajput

1
在您的DBHelper类中,在测试Util.getDatabasePath(DB_NAME)方法中是否存在数据库之前,您正在创建数据库。这行代码正在创建数据库。
this.DB_COMPLETE_PATH = Util.getDatabasePath(DB_NAME);

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

如果您将DB存储在默认应用程序的db路径中,则可以通过以下代码段检查是否存在DB:

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()方法中。


但在Android P中,必须使用该代码来获取DB的路径,因此这是一个恶性循环。我如何在Android P中获取DB的路径而不创建DB? - NullPointerException
context.getDatabasePath("my_database.db); - LifeStyle
但这是一个恶性循环。在Android P中,我如何获取数据库的路径,而不创建该数据库并且不使用getDatabasePath? - NullPointerException
我是指异常堆栈追踪。和你在数据库中创建其他表一样进行创建即可。 - LifeStyle
1
终于解决了,只需添加一行简单的代码。非常感谢! - NullPointerException
显示剩余8条评论

0

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

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

0

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


-2

通过在this.getReadableDatabase();之后添加this.close();,解决了我与Android P的问题。

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

[https://dev59.com/U1UL5IYBdhLWcg3wWG5I#53258585][1]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接