問題焦點:拷貝的內置資料庫,在後續的使用時,拋出了 Can't upgrade read-only database from version 0 to 1的異常,確定不存在sql錯誤。

 

解決方案: 拷貝資料庫時,順便升級下資料的版本資訊



這次的android的app開發有個內置資料庫的功能,而在此之前,我在本地也通過sql建了一個資料庫,為保持相容性,我只添加了一個是否使用內置資料的功能,使用內置資料庫時,只需將apk中的資料庫檔案覆蓋下data/data/下的檔即可,代碼如下:

 

/**
* this method should be invoke in another thread except UI thread
* @throws IOException
*/
private void copyDataBase() throws IOException {
MyUtil.log(DBConfig.DB_TAG,
"內置資料庫之copyDatabase");
Open your local db as the input stream
InputStream myInput = mCoNtext.getAssets().open(DBConfig.DATABASE_NAME);
Path to the just created empty db
String outFileName = DB_PATH + DBConfig.DATABASE_NAME;

 

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();



}

 

採用這種方法後,首次調用後,初始化了dbhelper後,倒能正常使用,但從第二次開始,就出現了:

 

SQLiteException: Can't upgrade read-only database from version 1 to 2

 

網上關於這個異常的說法很多,一般是sql語句錯誤居多,但不適合我的這個場景,我不是初次建資料庫,而是使用一個正常內置資料庫,首次能讀寫,就說明 sql不可能有問題的。

 

對於我的這個異常,跟蹤代碼,最後發現,原來內置的資料庫在拷貝時,並未保存資料庫的版本資訊,也即版本為0,當第二次初始化sqlitehelper 時,android內部的sqlitehelper便會再次調用oncreate,於是,內置的資料庫表已存在,不能再次更新,便拋出了這個異常,知道了原因,就有解決方案了:拷貝資料時,順帶升級下資料庫版本即可:

 

public void updateVersion(){
SQLiteDatabase checkDB = null;
try {
String myPath = DB_PATH + DBConfig.DATABASE_NAME;
checkDB = SQLiteDatabase.openDatabase(myPath, null,
SQLiteDatabase.OPEN_READWRITE);



checkDB.beginTransaction();
int version = checkDB.getVersion();
checkDB.setVersion(DBConfig.DATABASE_VERSION);
checkDB.setTransactionSuccessful();
MyUtil.log(DBConfig.DB_TAG, "修改資料庫版本資訊 成功");

 

} catch (SQLiteException e) {
database does't exist yet.
} finally {
if (checkDB != null) {
checkDB.endTransaction();
checkDB.close();
}
}

 

}

 

總的使用方法是:

 

/**
* Creates a empty database on the system and rewrites it with your own
* database.
*
* you should promise this methods be used only once.
* */
public void createDataBase() throws IOException {
MyUtil.log(DBConfig.DB_TAG, "內置資料庫之createDataBase");
boolean dbExist = checkDataBase();

 

try {
copyDataBase();
MyUtil.log(DBConfig.DB_TAG, "內置資料庫之 修改資料庫版本資訊");
updateVersion();
} catch (IOException e) {

 

throw new Error("Error copying database:" + e.getMessage());
}

 

}
 
來自
http://my.oschina.net/chengliqun/blog/152184
arrow
arrow
    全站熱搜

    戮克 發表在 痞客邦 留言(0) 人氣()