[更新: 解決策 = 複数の apk をパッケージ化する代わりに、デバッガーを使用してデータベース スキーマの変更を正常にテストできる onUpgrade() コードを修正しました]
アプリの更新がマーケットに展開されたときにデータベースの更新が行われることを確認するために、2 つの apk をテストしようとしています。
Test1.apk: sqlite schema_version = 1 を含む Test2.apk: sqlite schema_version = 2 を含む
両方の apk は同じキーでデジタル署名されており、adb を使用して Test1.apk をインストールできます。Test2.apk をインストールしようとすると、次のメッセージが表示されます。
失敗 [INSTALL_FAILED_ALREADY_EXISTS]
新しいスキーマの変更をテストするにはどうすればよいですか? 答えがデバッガーからのものである場合、onUpgrade() が呼び出されると、データベースは常にロックされます。
//////////////// This Code Fixed The onUpgrade() Issue /////////////////////
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
//TODO: Write DB Update logic.
SQLiteDatabase upgradeDB = null;
if (newVersion > oldVersion){
Log.e(TAG, "NEWER VERSION DETECTED, DATABASE UPGRADE REQUIRED!");
InputStream inputStream = myContext.getResources().openRawResource(R.raw.dbscript_v2_0_0_0);
BufferedReader br2 = new BufferedReader(new InputStreamReader(inputStream), 1016688); //1016688 max
String buffer;
try {
db.beginTransaction();
//openDataBase();
while ((buffer = br2.readLine()) != null)
{
String[] execSql = buffer.split("\n");
execMultipleSQL(db, execSql);
}
db.setTransactionSuccessful();
Log.d(TAG, "onCreated sql: CREATED TABLES and INSERTED RECORDS");
} catch (SQLException e) {
Log.e("Error creating tables and debug data", e.toString());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
db.endTransaction();
//db.close();
}
}
else
{
Log.e(TAG, "NO DATABASE UPGRADE DETECTED");
}
}
////////////////////////////////////////////////////////////////////////////
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
//TODO: Write DB Update logic.
SQLiteDatabase upgradeDB = null;
if (newVersion > oldVersion){
Log.e(TAG, "NEWER VERSION DETECTED, DATABASE UPGRADE REQUIRED!");
InputStream inputStream = myContext.getResources().openRawResource(R.raw.dbscript_v2_0_0_0);
BufferedReader br2 = new BufferedReader(new InputStreamReader(inputStream), 1016688); //1016688 max
String buffer;
try {
String myPath = DATABASE_PATH + DATABASE_NAME;
myDataBase = SQLiteDatabase.openOrCreateDatabase(DATABASE_PATH + DATABASE_NAME, null);
myDataBase.beginTransaction();
//openDataBase();
while ((buffer = br2.readLine()) != null)
{
String[] execSql = buffer.split("\n");
execMultipleSQL(myDataBase, execSql);
}
myDataBase.setTransactionSuccessful();
//close();
Log.d(TAG, "onCreated sql: CREATED TABLES and INSERTED RECORDS");
} catch (SQLException e) {
Log.e("Error creating tables and debug data", e.toString());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
myDataBase.endTransaction();
myDataBase.close();
}
}
else
{
Log.e(TAG, "NO DATABASE UPGRADE DETECTED");
}
}
public void openDataBase() throws SQLException {
try
{
/* When the database is 1st installed on the device, this helper class creates a blank database using getWritableDatabase().
* The actual database is then populated using the SQLiteDatabase.openDatabase(PATH, null, Open_ReadWrite) to exec the sql.
*
* PROBLEM - SQLiteDatabase.openDatabase() Does not call onUpgrade() so we're
* unable to update the database for future versions
*
* SOLUTION - Check to see if the dbExists, if not use SQLiteDatabase.openDatabase()
* because it will create the DB from scripts, we don't care about onUpgrade();
* If the db does exist, call getWritableDatabase() to invoke onUpgrade checks for
* future releases where the SCHEMA_VERSION is greater than the current db SCHEMA_VERSION
*/
boolean dbExist = checkDataBase();
if(!dbExist){
/* Calls: DOES NOT call onUpgrade()
* Errors if db exists and there are db changes (New Columns/Tables), so use the below getWritableDatabase() instead */
String myPath = DATABASE_PATH + DATABASE_NAME;
myDataBase = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READWRITE);
}
else
{
/* Calls: onUpgrade()
* Errors if db does not exist, so use the above instead */
myDataBase = this.getWritableDatabase();
}
}
catch (Exception e) {
Log.e(TAG, "Error SQLiteFactoryAdapter openDataBase " + e.toString());
}
}