2014-08-31 38 views
0

我寫了一個應用程序,它使用資產文件夾中現有數據庫的數據。用於複製和使用的數據我寫了下面的ExternalOpenDbHelper:如何將新列添加到Android應用程序中資產文件夾上的現有數據庫?

public class ExternalDbOpenHelper extends SQLiteOpenHelper { 

    public static String DB_PATH; 

    private static String TABALE_NAME = "font"; 
    private static String FONT_ID = "_id"; 
    private static String FONT_TYPE = "font_type"; 
    private static String FONT_SIZE = "font_size"; 

    private static String POEM_TABLE = "poem"; 
    private static String POEM_ID = "_id"; 
    private static String READ_POINT = "read_point"; 
    private static String BOOKMARK = "bookmark"; 

    public static String DB_NAME; 
    public SQLiteDatabase database; 
    public final Context context; 
    private static final int DATABASE_VERSION = 2; 

    public SQLiteDatabase getDb() { 
     return database; 
    } 

    public ExternalDbOpenHelper(Context context, String databaseName) { 
     super(context, databaseName, null, DATABASE_VERSION); 
     this.context = context; 

     String packageName = context.getPackageName(); 

     DB_PATH = String.format("//data//data//%s//databases//", packageName); 
     DB_NAME = databaseName; 
     openDataBase(); 
    } 

    public void createDataBase() { 
     boolean dbExist = checkDataBase(); 
     if (!dbExist) { 
      this.getReadableDatabase(); 
      try { 
       copyDataBase(); 
      } catch (IOException e) { 
       Log.e(this.getClass().toString(), "Copying error"); 
       throw new Error("Error copying database!"); 
      } 
     } else { 
      Log.i(this.getClass().toString(), "Database already exists"); 
     } 
    } 

    private boolean checkDataBase() { 
     SQLiteDatabase checkDb = null; 
     try { 
      String path = DB_PATH + DB_NAME; 
      checkDb = SQLiteDatabase.openDatabase(path, null, 
        SQLiteDatabase.OPEN_READONLY); 
     } catch (SQLException e) { 
      Log.e(this.getClass().toString(), "Error while checking db"); 
     } 
     if (checkDb != null) { 
      checkDb.close(); 
     } 
     return checkDb != null; 
    } 

    private void copyDataBase() throws IOException { 

     InputStream externalDbStream = context.getAssets().open(DB_NAME); 

     String outFileName = DB_PATH + DB_NAME; 

     OutputStream localDbStream = new FileOutputStream(outFileName); 

     byte[] buffer = new byte[1024]; 
     int bytesRead; 
     while ((bytesRead = externalDbStream.read(buffer)) > 0) { 
      localDbStream.write(buffer, 0, bytesRead); 
     } 
     localDbStream.close(); 
     externalDbStream.close(); 

    } 

    public SQLiteDatabase openDataBase() throws SQLException { 
     String path = DB_PATH + DB_NAME; 
     if (database == null) { 
      createDataBase(); 
      database = SQLiteDatabase.openDatabase(path, null, 
        SQLiteDatabase.OPEN_READWRITE); 
     } 
     return database; 
    } 

    @Override 
    public synchronized void close() { 
     if (database != null) { 
      database.close(); 
     } 
     super.close(); 
    } 

    @Override 
    public void onCreate(SQLiteDatabase db) { 
    } 

    @Override 
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 

     if (newVersion > oldVersion) { 
      db.execSQL("ALTER TABLE cat ADD point BOOLEAN NOT NULL DEFAULT 0;"); 
      db.execSQL("ALTER TABLE poem ADD read_point BOOLEAN NOT NULL DEFAULT false;"); 
      db.execSQL("ALTER TABLE poem ADD bookmark INTEGER NOT NULL DEFAULT 0;"); 
     } 
    } 

    public int updateFont(int i, String fontName, int p) { 
     SQLiteDatabase db = this.getWritableDatabase(); 

     ContentValues font = new ContentValues(); 
     font.put(FONT_TYPE, fontName); 
     font.put(FONT_SIZE, p); 

     String whereClause = FONT_ID + " LIKE ?"; 
     String[] whereArgs = new String[] { String.valueOf(i) }; 

     return db.update(TABALE_NAME, font, whereClause, whereArgs); 
    } 

    public void updateReadPoint(int poemId, int readPointTeransfer) { 
     SQLiteDatabase db = this.getWritableDatabase(); 
     String whereClause; 
     String[] whereArgs; 

     if (poemId != readPointTeransfer) { 
      ContentValues readPoint = new ContentValues(); 
      readPoint.put(READ_POINT, Boolean.toString(true)); 

      whereClause = POEM_ID + " LIKE ?"; 
      whereArgs = new String[] { String.valueOf(poemId) }; 

      db.update(POEM_TABLE, readPoint, whereClause, whereArgs); 

      if (readPointTeransfer != -1) { 
       readPoint.put(READ_POINT, Boolean.toString(false)); 
       whereArgs = new String[] { String.valueOf(readPointTeransfer) }; 
       db.update(POEM_TABLE, readPoint, whereClause, whereArgs); 
      } 
     } 
    } 

    public void updateBookmarkList(int i, String idOfThisPoem) { 


     SQLiteDatabase db = this.getWritableDatabase(); 
     ContentValues bookmarkValue = new ContentValues(); 
     String whereClause = POEM_ID + " LIKE ?"; 
     String[] whereArgs = new String[] { idOfThisPoem }; 
     if (i == 0) { 

      bookmarkValue.put(BOOKMARK, Integer.toString(0)); 
      db.update(POEM_TABLE, bookmarkValue, whereClause, whereArgs); 
     } else if (i == 1) { 

      bookmarkValue.put(BOOKMARK, Integer.toString(1)); 
      db.update(POEM_TABLE, bookmarkValue, whereClause, whereArgs); 
     } 
    } 

    public boolean bookmarkStatus(String idOfThisPoem){ 
     String idOfThisBookmarkedPoem = null; 
     Boolean iconFull = null; 

     String[] tableColumns = new String[] { POEM_ID, BOOKMARK }; 
     String whereClause = POEM_ID + " LIKE ?"; 
     String[] whereArgs = new String[] { idOfThisPoem }; 
     Cursor poetCursor = database.query(POEM_TABLE, tableColumns, 
       whereClause, whereArgs, null, null, POEM_ID); 

     poetCursor.moveToFirst(); 
     if (!poetCursor.isAfterLast()) { 
      do { 

       idOfThisBookmarkedPoem = poetCursor.getString(1); 

      } while (poetCursor.moveToNext()); 
     } 
     poetCursor.close(); 

     if (Integer.valueOf(idOfThisBookmarkedPoem) == 0) { 
      iconFull = false; 

     } else if (Integer.valueOf(idOfThisBookmarkedPoem) == 1) { 
      iconFull = true; 

     } 
     return iconFull; 
    } 

} 

在我的代碼檢查,如果數據被複制在手機上沒有再次複製,但是,如果沒有路徑上從資產文件夾複製和讀/寫在手機上覆制的數據庫。我不能在每次應用程序運行時從資產複製數據庫,因爲我只是在數據庫上寫入(//數據//數據//%s //數據庫//)。現在我需要在它的兩個表格上添加新的列,因爲我之前發佈它不喜歡最終用戶卸載並再次安裝應用程序。我嘗試搜索大量的工作,但找不到解決方案。我想如果我可以刪除數據(//數據//數據//%s //數據庫//)路徑可以做到這一點。

+1

考慮使用https://github.com/jgilfelt/android-sqlite-asset-helper,而不是基於非常古老的博客文章的一些破碎的代碼。 – laalto 2014-08-31 10:44:54

+0

謝謝,但我無法理解你的意思。你說我在我的代碼中選擇了錯誤的路徑,並且必須將其更改爲github上的代碼? – user3752236 2014-08-31 11:45:03

回答

0

如何在Android應用程序的資產文件夾中的現有數據庫添加新列?

您無法修改資產。

歡迎您通過SQLiteDatabase對象調用execSQL()並執行ALTER TABLE聲明修改您的本地數據庫副本。

我回復laalto的評論:請use SQLiteAssetHelper。除此之外,它爲您提供了多種向現有數據庫添加新列的方法。

+0

謝謝您的回答,我這樣做意味着我在資產數據庫中添加了新列,並將DATABASE_VERSION更改爲2,並且升級方法編寫了更改表指令,但它不適用於我,因爲我無法刪除(if(!dbExist ))的oncreate方法。 – user3752236 2014-08-31 11:19:52

0

您需要對您的數據庫進行版本控制。換句話說,當您打開數據庫時,您似乎沒有對當前版本進行任何檢查。

例如,您可以定義當前版本:

public static final int DATABASE_VERSION = 1; 

但當DB是必須添加的偏好(SharedPreferences)或類似的保存是安裝在用戶的設備上的數據庫版本的東西安裝。然後在稍後的更新中,您可以更改版本並添加代碼以將數據庫更新爲新版本。既然你還沒有這樣做,你還需要檢查沒有識別版本的情況。

要執行升級,使用ExternalDbOpenHelper構造函數或類似openDataBase甚至checkDataBase的方法調用onUpgrade當前DB版本和已安裝的DB版本做你的版本檢查。

像這樣:

onUpgrade(database, settings.getInt(OLD_DB_VERSION, 0), DATABASE_VERSION); 

你還必須記住保存新的DB版本執行更新或者新的安裝後發生。

相關問題