2012-06-08 23 views
5

tôi sử dụng hướng dẫn này: Tutorial Custom databaseNâng cấp cơ sở dữ liệu SQLite mà tôi sao chép từ thư mục nội dung (Android)

sao chép cơ sở dữ liệu từ thư mục tài sản và sao chép nó vào điện thoại của mình (hoặc giả lập). Mọi thứ đều chính xác. Tôi thấy cơ sở dữ liệu của tôi trong quan điểm DDMS. Nhưng tôi muốn aslo nâng cấp cơ sở dữ liệu của tôi đôi khi vì vậy tôi đã làm:

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

và sửa đổi onUpgrade phương pháp:

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

Nhưng sau khi chạy tôi vẫn còn có phiên bản cũ của cơ sở dữ liệu trên điện thoại của tôi. Làm thế nào tôi có thể xóa phiên bản cũ của cơ sở dữ liệu và sao chép mới. DB_NAME là tên cơ sở dữ liệu của tôi (có định dạng, nhưng không phải đường dẫn) và copyDataBase() là phương thức sao chép cơ sở dữ liệu vào thiết bị (và nó hoạt động).

tôi dán tất cả các mã của tôi:

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


} 

và hoạt động của tôi:

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

Cảm ơn nếu bạn có thể cho tôi lý do hay chỉ gợi ý tại sao công việc t don này'.

Trả lời

5

android đã mở db khi hàm onUpgrade() được gọi. tôi không nghĩ rằng nó có thể xóa nó vào lúc này. kiểm tra nhật ký để biết thêm thông tin. nếu bạn muốn làm theo cách này, bạn cần phải di chuyển xóa và sao chép mã đến một nơi mà db chưa được mở.

+0

Vâng, bạn là đúng. Tôi đã làm gì ? Tôi đã sử dụng tùy chọn chia sẻ để ký phiên bản mới của cơ sở dữ liệu và tôi xóa cơ sở dữ liệu trước khi tôi sử dụng đối tượng này. Cảm ơn. – kolek

+2

@kolek: Bạn có thể chia sẻ giải pháp với mọi người không? Tôi cũng cần một cái gì đó tương tự. –

+0

Tại sao bạn không chia sẻ giải pháp, Kolek? Làm ơn, nhiều người cần nó. –

2

Hãy thử mã này ... Tôi nghĩ rằng nó sẽ giải quyết vấn đề của bạn.

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

Bạn có thể xóa Db cũ trước khi nâng cấp 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

Chỉ cần một sự bổ sung:

trong CreateDatabase() có việc kiểm tra sau;

this.getReadableDatabase();

Điều này sẽ kiểm tra nếu đã có cơ sở dữ liệu với tên được cung cấp và nếu không tạo cơ sở dữ liệu trống sao cho có thể ghi đè lên cơ sở dữ liệu trong thư mục nội dung. Trên các thiết bị mới hơn, công trình này hoàn hảo nhưng có một số thiết bị không hoạt động. Chủ yếu là các thiết bị cũ hơn. Tôi không biết chính xác lý do tại sao, nhưng có vẻ như hàm getReadableDatabase() không chỉ nhận được cơ sở dữ liệu mà còn mở nó. Nếu bạn sau đó sao chép cơ sở dữ liệu từ thư mục tài sản trên nó, nó vẫn có con trỏ đến một cơ sở dữ liệu rỗng và bạn sẽ nhận được bảng không tồn tại lỗi.

Vì vậy, để làm cho nó hoạt động trên tất cả các thiết bị mà bạn nên thay đổi nó vào dòng sau:

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

Thậm chí nếu cơ sở dữ liệu được mở trong việc kiểm tra, nó được đóng lại sau đó và nó sẽ không cung cấp cho bạn còn rắc rối nữa.

1

Khi cơ sở dữ liệu được sao chép từ nội dung, theo mặc định là phiên bản 0. Trong phương pháp sao chép dữ liệu từ nội dung, hãy đặt phiên bản của nó bằng phương thức setVersion(int version) cho đối tượng cơ sở dữ liệu của bạn. Nếu db tồn tại, hãy kiểm tra phiên bản của nó theo phương thức getVersion() trên đối tượng cơ sở dữ liệu của bạn. Bây giờ, hãy tự mình xử lý onUpgrade của mình, tức lànếu db evrsion đã được cập nhật noe, sau đó nâng cấp cơ sở dữ liệu và sau đó setVersion(int new dbVersion).

0

Ý tưởng chính là bạn nên sử dụng SharedPreferences để lưu trữ phiên bản cơ sở dữ liệu của mình bất cứ khi nào bạn tạo cơ sở dữ liệu mới.
Sau đó, khi bạn tạo cơ sở dữ liệu, bạn phải kiểm tra xem cơ sở dữ liệu có phiên bản mới thì bạn xóa cơ sở dữ liệu cũ và tạo việc một
Mã này mới với tôi

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) { 
     } 
    } 
Các vấn đề liên quan