您的位置:首页 > 移动开发 > Android开发

android内置数据库的一个错误解决方案:Can't upgrade read-only d...

2013-08-12 19:04 549 查看
问题焦点:拷贝的内置数据库,在后续的使用时,抛出了 Can't upgrade read-only database from version 0 to 1的异常,确定不存在sql错误。

解决方案: 拷贝数据库时,顺便升级下数据的版本信息

这次的android的app开发有个内置数据库的功能,而在此之前,我在本地也通过sql建了一个数据库,为保持兼容性,我只添加了一个是否使用内置数据的功能,使用内置数据库时,只需将apk中的数据库文件覆盖下data/data/<package_name/>下的文件即可,代码如下:

/**
* 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());
}

}
我采用这个方法,解决我的问题,希望对大家有帮助。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐