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

   问题焦点:拷贝的内置数据库,在后续的使用时,抛出了 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());
		}

	}
我采用这个方法,解决我的问题,希望对大家有帮助。

你可能感兴趣的:(android,can,内置数据库)