public class DBManager {
public static final String DATABASE_TABLE= "registration";
public static final String DATABASE_NAME = "userinfo.sqlite";
static final int DATABASE_VERSION = 1;
final Context context;
SQLiteDatabase db;
DatabaseHelper DBHelper;
public DBManager(Context ctx) {
this.context = ctx;
DBHelper = new DatabaseHelper(context);
}
private class DatabaseHelper extends SQLiteOpenHelper {
public DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
context.openOrCreateDatabase(DATABASE_NAME, context.MODE_PRIVATE, null);
}
@Override
public void onCreate(SQLiteDatabase db) {
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if(newVersion>oldVersion)
try {
copyDataBase();
} catch (IOException e) {
e.printStackTrace();
}
}
}
// ---opens the database---
public DBManager open() throws SQLException {
db = DBHelper.getWritableDatabase();
return this;
}
// ---closes the database---
public void close() {
DBHelper.close();
}
//Copies database from internal memory to the activity/fragement, To use the internal db
public void createDataBase() throws IOException {
boolean mDataBaseExist = checkDataBase();
if (mDataBaseExist) {
// do nothing - database already exist
} else {
DBHelper.getReadableDatabase();
try {
copyDataBase();
} catch (IOException e) {
throw new Error("Error copying database");
}
}
}
/** This method checks whether database exists or not **/
private boolean checkDataBase() {
SQLiteDatabase checkDB = null;
try {
String myPath = context.getDatabasePath(DATABASE_NAME).getPath()
.toString();
checkDB = SQLiteDatabase.openDatabase(myPath, null,
SQLiteDatabase.OPEN_READONLY);
} catch (SQLiteException e) {
// database does't exist yet.
}
if (checkDB != null) {
checkDB.close();
}
return checkDB != null ? true : false;
}
// Creates and copies database from assets folder to internal memory,
// must be run at least once when app is installed
public long copyDataBase() throws IOException {
String DB_PATH = context.getDatabasePath(DATABASE_NAME).getPath()
.toString();
// Open your local db as the input stream
InputStream myInput = context.getAssets().open(DATABASE_NAME);
// Path to the just created empty db
String outFileName = DB_PATH;
// Open the empty db as the output stream
OutputStream myOutput = new FileOutputStream(outFileName);
// transfer bytes from the inputfile to the outputfile
byte[] buffer = new byte[1024];
int length;
while ((length = myInput.read(buffer)) > 0) {
myOutput.write(buffer, 0, length);
}
// Close the streams
myOutput.flush();
myOutput.close();
myInput.close();
return length;
}
错误:
android.database.sqlite.SQLiteException: no such table: registration (code 1 SQLITE_ERROR): , while compiling: select * from registration where username = ? and password = ?
答案 0 :(得分:1)
是的,对于android 9,SQLite数据库中还有两个其他文件,如果您复制覆盖现有数据库的数据库,并且不先删除其他两个文件,则该数据库将认为自身已损坏。查看此答案:Ship android app with pre populated database
答案 1 :(得分:1)
您的问题是由于在复制之前使用了DBHelper.getReadableDatabase();
。
使用它(可能更容易使用)在data / data / the_package /文件夹/目录中创建 database 文件夹/ directoyr。
发生的事情是,这将打开数据库,并且在Android 9+的情况下会产生两个附加文件,作为Android 9+创建的-wal和-shm文件默认使用预先写入日志记录。
将数据库文件复制到新创建的文件上时,剩下两个其他文件。复制后打开数据库时,两个文件与复制的数据库不匹配,打开失败但被捕获,导致创建了新数据库。
有几种方法可以规避。
可以通过强制使用日志模式来打开数据库,例如覆盖 onConfigure 方法以调用enableWriteAheadLogging(false)。
在复制之前删除 -wal 和 -shm 文件。
创建数据库文件夹,而不是调用getReadableDatabase()
checkDB = SQLiteDatabase.openDatabase(myPath, null,SQLiteDatabase.OPEN_READONLY);
来查看数据库文件是否存在仍然有不必要的开销。检查数据库是否作为文件存在,如果不存在,请使用文件的 mkdirs 方法创建数据库目录(如果更改此目录将需要任何目录)。
This answer提供了执行后者的代码(请参见 checkDataBase 方法),并指出您还应该删除行DBHelper.getReadableDatabase();
。
答案 2 :(得分:0)
我也面临类似的问题,并解决了此问题,将其添加到我的SQLiteOpenHelper
@Override
public void onOpen(SQLiteDatabase db) {
super.onOpen(db);
db.disableWriteAheadLogging();
}
希望这可以解决您的问题