2012-06-08 68 views
5

複製我使用本教程: Tutorial Custom database升級SQLite數據庫,我是從資產的文件夾(安卓)

我從資產文件夾複製數據庫,並將其複製到我的設備(或模擬器)。一切都是正確的。我從DDMS的角度看到我的數據庫。但我想ASLO升級我的數據庫有時,所以我所做的:

super(context, DB_NAME, null, 2); //changed version from 1 to 2 

和修改onUpgrade方法:

@Override 
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 
    if(newVersion > oldVersion){ 
     this.myContext.deleteDatabase(DB_NAME); 
     try { 
      this.copyDataBase(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 
} 

但運行後我還有我的設備上舊版本的數據庫。我如何刪除舊版本的數據庫並複製新的。 DB_NAME是我的數據庫名稱(帶有格式,但不包含路徑),copyDataBase()是將數據庫複製到設備(以及它工作)的方法。

我貼我的所有代碼:

public class DataBaseHelper extends SQLiteOpenHelper{ 

    private static String DB_PATH = "/data/data/sitcom.quiz/databases/"; 

    private static String DB_NAME = "sitcoms.sqlite"; 

    private SQLiteDatabase myDataBase; 

    private final Context myContext; 

    public DataBaseHelper(Context context) { 

     super(context, DB_NAME, null, 4); 
     this.myContext = context; 
    } 

    public void createDataBase() throws IOException{ 

     boolean dbExist = checkDataBase(); 

     if(dbExist){ 
      //do nothing - database already exist 
     }else{ 

      this.getReadableDatabase(); 

      try { 

       copyDataBase(); 

      } catch (IOException e) { 

       throw new Error("Error copying database"); 

      } 
     } 

    } 

    private boolean checkDataBase(){ 

     SQLiteDatabase checkDB = null; 

     try{ 
      String myPath = DB_PATH + DB_NAME; 
      checkDB = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY); 

     }catch(SQLiteException e){ 
      //database does't exist yet. 
     } 

     if(checkDB != null){ 
      checkDB.close(); 
     } 

     return checkDB != null ? true : false; 
    } 


    private void copyDataBase() throws IOException{ 

     //Open your local db as the input stream 
     InputStream myInput = myContext.getAssets().open(DB_NAME); 

     // Path to the just created empty db 
     String outFileName = DB_PATH + DB_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(); 

    } 

    public void openDataBase() throws SQLException{ 

     //Open the database 
     String myPath = DB_PATH + DB_NAME; 
     myDataBase = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY); 

    } 

    @Override 
    public synchronized void close() { 

      if(myDataBase != null) 
       myDataBase.close(); 

      super.close(); 

    } 

    @Override 
    public void onCreate(SQLiteDatabase db) { 

    } 

    @Override 
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 
     Log.d("adas", "dasd"); 

     if(newVersion > oldVersion){ 
      String myPath = DB_PATH + DB_NAME; 
      this.myContext.deleteDatabase(myPath); 
      try { 
       this.copyDataBase(); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
     } 
    } 


} 

和我的活動:

DataBaseHelper myDbHelper = new DataBaseHelper(this); 
     myDbHelper = new DataBaseHelper(this); 

     try { 
      myDbHelper.createDataBase(); 
     } catch (IOException ioe) { 
      throw new Error("Unable to create database"); 
     } 
     try { 
      myDbHelper.openDataBase(); 
     }catch(SQLException sqle){ 
      throw sqle; 
     } 

感謝您是否可以給我一個理由或只能暗示爲什麼別工作。

回答

5

當函數onUpgrade()被調用時,android已經打開了數據庫。我不認爲有可能在這個時候刪除它。檢查日誌以獲取更多信息。如果你想這樣做,你需要將刪除和複製代碼移動到數據庫尚未打開的位置。

+0

是的,你是對的。我做了什麼 ?我使用共享首選項來簽署新版本的數據庫,並在使用此對象之前刪除數據庫。謝謝。 – kolek

+2

@ kolek:你能與大家分享解決方案嗎?我也需要類似的東西。 –

+0

爲什麼不分享解決方案,Kolek?請,很多人需要它。 –

2

試試這個代碼...我認爲它會解決你的問題。

public void onUpgrade(SQLiteDatabase database, int oldVersion, 
     int newVersion) { 
    Log.w(DatabaseHelper.class.getName(), 
      "Upgrading database from version " + oldVersion + " to " 
        + newVersion + ", which will destroy all old data"); 
    database.execSQL("DROP TABLE IF EXISTS " + DATABASE_NAME); 
    onCreate(database); 
} 
0

您可以在升級數據庫之前刪除舊的Db。

if(dbExist){ 
       Log.v("com.db","db exists"); 
       myContext.deleteDatabase(DB_NAME);`enter code here` 
       //openDataBase(); 
       //do nothing - database already exist 
      }else{ 
       Log.v("com.db","dbnot exists"); 
       //By calling this method and empty database will be created into the default system path 
        //of your application so we are gonna be able to overwrite that database with our database. 
       this.getReadableDatabase(); 
} 
0

只是一個加法:

中的CreateDatabase

()有下面的檢查;

this.getReadableDatabase();

這將檢查是否已經存在具有提供名稱的數據庫,是否創建空數據庫以便可以使用assets文件夾中的數據庫覆蓋它。在較新的設備上,它可以完美地工作,但有些設備無法正常工作。主要是舊設備。我不知道究竟是什麼原因,但似乎getReadableDatabase()函數不僅獲取數據庫,而且還打開它。如果您然後將資產文件夾中的數據庫複製到它上面,它仍然具有指向空數據庫的指針,並且您將得到表不存在的錯誤。

因此,爲了使所有設備上工作,你應該把它修改爲以下行:

SQLiteDatabase db = this.getReadableDatabase(); 
if (db.isOpen()){ 
    db.close(); 
} 

即使數據庫在檢查開,此後它被關上,它不會給你任何更多的麻煩。

1

當從資產複製數據庫時,缺省情況下版本爲0. 在從資產複製數據庫的方法中,使用方法setVersion(int version)爲數據庫對象設置其版本。 如果數據庫存在,請通過數據庫對象上的方法getVersion()檢查其版本。現在自己處理onUpgrade即如果db evrsion已經更新了noe,然後升級數據庫,然後setVersion(int new dbVersion)

0

主要思想是當你創建新的數據庫時,你應該使用SharedPreferences來存儲你的數據庫版本。
之後,當您創建數據庫時,必須檢查是否有數據庫新版本,那麼你刪除舊的數據庫,並創建了我新的一個
此代碼工作

private static class DatabaseHelper extends SQLiteOpenHelper { 

     private static final String DATABASE_NAME = "database.name"; 
     private static final int DATABASE_VERSION = 1; 
     private static final String KEY_DB_VER = "database_version"; 
     private final Context mContext; 

     public DatabaseHelper(Context context) { 
      super(context, DATABASE_NAME, null, DATABASE_VERSION); 
      mContext = context; 
      initialize(); 
     } 

     /** 
     * Initializes database. Creates database if doesn't exist. 
     */ 
     private void initialize() { 
      if (databaseExists()) { 
       SharedPreferences prefs = PreferenceManager 
         .getDefaultSharedPreferences(mContext); 
       int dbVersion = prefs.getInt(KEY_DB_VER, 1); 
       // 
       if (DATABASE_VERSION != dbVersion) { 
        File dbFile = mContext.getDatabasePath(DATABASE_NAME); 
        // delete the old databse 
        if (!dbFile.delete()) { 
         Log.w(TAG, "Unable to update database"); 
        } 
       } 
      } 
      // create database if needed 
      if (!databaseExists()) { 
       createDatabase(); 
      } 
     } 

     /** 
     * Returns true if database file exists, false otherwise. 
     * @return 
     */ 
     private boolean databaseExists() { 
      File dbFile = mContext.getDatabasePath(DATABASE_NAME); 
      return dbFile.exists(); 
     } 

     public void createDataBase() throws IOException { 
      // If database not exists copy it from the assets 
      boolean mDataBaseExist = databaseExists(); 

      if (!mDataBaseExist) { 
       this.getReadableDatabase(); 
       this.close(); 
       try { 
        // Copy the database from assests 
        copyDataBase(); 

        //**save the database version by SharedPreferences** 

        SharedPreferences prefs = PreferenceManager 
          .getDefaultSharedPreferences(mContext); 
        SharedPreferences.Editor editor = prefs.edit(); 
        editor.putInt(KEY_DB_VER, DATABASE_VERSION); 
        editor.commit(); 

        Log.e(TAG, "createDatabase database created"); 

       } catch (IOException mIOException) { 
        throw new Error("ErrorCopyingDataBase"); 
       } 
      } 
     } 

     // Copy the database from assets 
     private void copyDataBase() throws IOException { 
      Log.i("TAG", "copy database"); 
      InputStream mInput = mContext.getAssets().open(DB_NAME); 
      String outFileName = DB_PATH + DB_NAME; 
      OutputStream mOutput = new FileOutputStream(outFileName); 
      byte[] mBuffer = new byte[1024]; 
      int mLength; 
      while ((mLength = mInput.read(mBuffer)) > 0) { 
       mOutput.write(mBuffer, 0, mLength); 
      } 
      mOutput.flush(); 
      mOutput.close(); 
      mInput.close(); 
     } 

     @Override 
     public void onCreate(SQLiteDatabase db) { 
     } 

     @Override 
     public void onUpgrade(SQLiteDatabase db, int oldVersion, 
       int newVersion) { 
     } 
    } 
相關問題