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 的对象作为静态对象,所以我遇到了这个问题。
直到 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 的对象作为静态对象,所以我遇到了这个问题。