android內置數據庫的一個錯誤解決方案:Can't upgrade read-only d...

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

   解決方案: 拷貝數據庫時,順便升級下數據的版本信息 android


  此次的android的app開發有個內置數據庫的功能,而在此以前,我在本地也經過sql建了一個數據庫,爲保持兼容性,我只添加了一個是否使用內置數據的功能,使用內置數據庫時,只需將apk中的數據庫文件覆蓋下data/data/<package_name/>下的文件便可,代碼以下: sql

/**
	 * 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不可能有問題的。 promise

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

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

	}
我採用這個方法,解決個人問題,但願對你們有幫助。
相關文章
相關標籤/搜索