2012-07-22 26 views
15

Tôi là người mới sử dụng toàn bộ Android SQLite. Đây là những gì tôi có:Tệp DB trong Thư mục nội dung. Nó sẽ được cập nhật?

  • Tôi có db.sqlite trong thư mục assets.
  • Mục đích của db là CHỈ ĐỌC. Người dùng sẽ không viết thư cho nó.
  • Khi ứng dụng được cập nhật, db.sqlite sẽ được thay thế thành db mới (tôi sẽ xóa tệp cũ khỏi dự án và thêm tệp mới).

Những gì tôi quan tâm là:

  • sẽ file db cũ bị xóa? (đó là những gì tôi muốn, thay thế cái cũ bằng cái mới)
    • Tại sao hỏi? Bởi vì khi tôi gỡ lỗi ứng dụng của mình, mỗi khi tôi cập nhật tệp db, tôi cần phải gỡ cài đặt ứng dụng khỏi thiết bị để buộc cập nhật. Người dùng có cần phải làm như vậy khi họ cập nhật ứng dụng của tôi từ cửa hàng trò chơi không? Tôi sợ điều đó.
  • Điều này có bị ảnh hưởng bởi cách tôi triển khai onCreate(SQLiteDatabase)onUpgrade(SQLiteDatabase, int, int) không?
    • Nếu có, cách thích hợp để triển khai chúng đáp ứng yêu cầu của tôi là gì?

Đây là cách tôi mở rộng lớp SQLiteOpenHelper. Tôi đã theo một hướng dẫn tôi tìm thấy trên internet:

import java.io.FileOutputStream; 
import java.io.IOException; 
import java.io.InputStream; 
import java.io.OutputStream;  
import android.content.Context; 
import android.database.Cursor; 
import android.database.SQLException; 
import android.database.sqlite.SQLiteDatabase; 
import android.database.sqlite.SQLiteException; 
import android.database.sqlite.SQLiteOpenHelper; 
import android.util.Log; 

public class DataBaseHelper extends SQLiteOpenHelper{ 

    //The Android's default system path of your application database. 
    private static String DB_PATH = "/data/data/com.mydomain.myapp/databases/"; 
    private static String DB_NAME = "db.sqlite"; 
    private SQLiteDatabase myDataBase; 
    private final Context myContext; 

    /* 
    * Constructor 
    * Takes and keeps a reference of the passed context in order to access to the application assets and resources. 
    * @param context 
    **/ 
    public DataBaseHelper(Context context) { 

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

    /** 
    * Creates a empty database on the system and rewrites it with your own database. 
    * */ 
    public void createDataBase() throws IOException{ 

     boolean dbExist = checkDataBase(); 

     if(dbExist){ 
      //do nothing - database already exist 
      Log.i("myapp", "database already exist"); 
     }else{ 
      Log.i("myapp", "database NOT exist"); 

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

      try { 

       copyDataBase(); 

      } catch (IOException e) { 

       throw new Error("Error copying database"); 

      } 
     } 

    } 

    /** 
    * Check if the database already exist to avoid re-copying the file each time you open the application. 
    * @return true if it exists, false if it doesn't 
    */ 
    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; 
    } 

    /** 
    * Copies your database from your local assets-folder to the just created empty database in the 
    * system folder, from where it can be accessed and handled. 
    * This is done by transfering bytestream. 
    * */ 
    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_READWRITE); 

    } 

    @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) { 

    } 

    // My public helper methods to access and get content from the database go here 

Trả lời

29

Bạn không thể thay thế cơ sở dữ liệu ở onUpgrade() vì trong cơ sở dữ liệu này đã được sử dụng. Bạn phải làm điều đó trước khi cơ sở dữ liệu mở, như trong một hàm tạo của DatabaseHelper của bạn. Vì bạn không thể sử dụng onUpgrade(), bạn phải tự quản lý phiên bản cơ sở dữ liệu. Sử dụng SharedPreferences là một cách tốt cho nó. Bạn kiểm tra xem cơ sở dữ liệu của bạn có tồn tại không (nếu nó đã được sao chép từ thư mục assets) và kiểm tra phiên bản nếu cơ sở dữ liệu tồn tại. Bây giờ bạn có thể xóa cơ sở dữ liệu cũ và sao chép cơ sở dữ liệu mới từ assets. Xem triển khai bên dưới.

Để đánh dấu ứng dụng đã cập nhật của bạn được xuất bản với cơ sở dữ liệu mới trong assets chỉ cần nhập DATABASE_VERSION không đổi.

private static class DatabaseHelper extends SQLiteOpenHelper { 

    private static final String DATABASE_NAME = "database.db"; 
    private static final int DATABASE_VERSION = 1; 
    private static final String SP_KEY_DB_VER = "db_ver"; 
    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(SP_KEY_DB_VER, 1); 
      if (DATABASE_VERSION != dbVersion) { 
       File dbFile = mContext.getDatabasePath(DATABASE_NAME); 
       if (!dbFile.delete()) { 
        Log.w(TAG, "Unable to update database"); 
       } 
      } 
     } 
     if (!databaseExists()) { 
      createDatabase(); 
     } 
    } 

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

    /** 
    * Creates database by copying it from assets directory. 
    */ 
    private void createDatabase() { 
     String parentPath = mContext.getDatabasePath(DATABASE_NAME).getParent(); 
     String path = mContext.getDatabasePath(DATABASE_NAME).getPath(); 

     File file = new File(parentPath); 
     if (!file.exists()) { 
      if (!file.mkdir()) { 
       Log.w(TAG, "Unable to create database directory"); 
       return; 
      } 
     } 

     InputStream is = null; 
     OutputStream os = null; 
     try { 
      is = mContext.getAssets().open(DATABASE_NAME); 
      os = new FileOutputStream(path); 

      byte[] buffer = new byte[1024]; 
      int length; 
      while ((length = is.read(buffer)) > 0) { 
       os.write(buffer, 0, length); 
      } 
      os.flush(); 
      SharedPreferences prefs = PreferenceManager 
        .getDefaultSharedPreferences(mContext); 
      SharedPreferences.Editor editor = prefs.edit(); 
      editor.putInt(SP_KEY_DB_VER, DATABASE_VERSION); 
      editor.commit(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } finally { 
      if (is != null) { 
       try { 
        is.close(); 
       } catch (IOException e) { 
        e.printStackTrace(); 
       } 
      } 
      if (os != null) { 
       try { 
        os.close(); 
       } catch (IOException e) { 
        e.printStackTrace(); 
       } 
      } 
     } 
    } 

    @Override 
    public void onCreate(SQLiteDatabase db) { 
    } 

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

Mã của bạn là đơn giản hơn nhiều so với tôi. Tôi hy vọng nó hoạt động. Mặc dù tôi có một vấn đề trước khi thử nghiệm nó: Trong 'initialize()', bạn chỉ cần xóa db cũ nếu nó tồn tại và phiên bản khác. Bạn có giả sử tạo một cái mới không? – iTurki

+0

Có "if (! DatabaseExists()) {createDatabase();}" sau nó. Nó tạo ra db nếu nó bị xóa. Tất nhiên nó có thể được viết lại để lưu kiểm tra này. – biegleux

+0

Tôi không chú ý đến điều đó. Nghĩ rằng đó là một phần 'khác'! Tôi đoán việc triển khai của bạn sẽ hoạt động. Cảm ơn :) – iTurki

0

Sau khi tìm kiếm nhiều thứ. Tôi tìm thấy cơ sở dữ liệu thư mục tài sản này chỉ đọc. bạn không thể cập nhật cơ sở dữ liệu trong thư mục nội dung. giả sử phiên bản ứng dụng tiếp theo của bạn xuất bản trên cửa hàng google play với cơ sở dữ liệu cập nhật mới trong thư mục khẳng định. nếu tên của cả hai cơ sở dữ liệu trong khẳng định là như nhau (trong ứng dụng trước và ứng dụng mới) hệ thống android sẽ đọc tập tin cơ sở dữ liệu cũ chỉ. Bởi vì hệ thống tập tin không thể chứa hai tập tin cùng tên. Những gì bạn cần làm chỉ là thay đổi tên của tên tệp cơ sở dữ liệu mới trong dataOpenhelper.class. như database_1.db.

public class DatabaseOpenHelper extends SQLiteAssetHelper { 
    private static final String DATABASE_NAME = "dbbasic_5.db"; 
    private static final int DATABASE_VERSION = 3; 
    private Context contaxtDB; 

    // ********* reminder ********** 
    // only change database_name = like dbbasic_5.6.7.8 . 
    // ******* do not change database_version 
    // 

    public DatabaseOpenHelper(Context context) { 
     super(context, DATABASE_NAME, null, DATABASE_VERSION); 
     contaxtDB = context; 
    } 

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

    } 


} 
0

này đang làm việc tốt, hãy thử nó

public class DatabaseHelper extends SQLiteOpenHelper { 

private static final int DATABASE_VERSION = 3; 
private static final String SP_KEY_DB_VER = "db_ver"; 
private static final String DATABASE_NAME = "db.db"; 
private static String DB_PATH = "/data/data/APP_PACKAGE/databases/"; 
    static SQLiteDatabase db; 
    public Context context; 

SessionManager session; 

    public DatabaseHelper(Context context) { 
      super(context, DATABASE_NAME, null, DATABASE_VERSION); 
      this.context = context; 
      session = SessionManager.getInstance(context);; 
      //initialize(); 
     } 

    public void createDataBase() throws IOException { 
      if (!checkDataBase()) { 
       getWritableDatabase(); 
       copyDataBase(); 
      } 
     } 

    public boolean checkDataBase() { 
      /**/ 
      boolean found = new File(DB_PATH + DATABASE_NAME).exists(); 
      if(found) 
      { 
       int dbVersion = Integer.valueOf(session.getData(SP_KEY_DB_VER, "1")); 
       if (DATABASE_VERSION != dbVersion) { 
        File dbFile = context.getDatabasePath(DATABASE_NAME); 
        if (!dbFile.delete()) { 
         Log.w("Warning: ", "Unable to update database"); 
        } 
        found = false; 
       } 
      } 
      return found; 
     } 

     public void copyDataBase() throws IOException { 
      InputStream myInput = this.context.getAssets().open(DATABASE_NAME); 
      OutputStream myOutput = new FileOutputStream(DB_PATH + DATABASE_NAME); 
      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(); 
      session.saveData(SP_KEY_DB_VER, String.valueOf(DATABASE_VERSION)); 
      //int dbVersion = prefs.in(SP_KEY_DB_VER, 3); 
     } 

     public void openDataBase() throws SQLException { 
      db = SQLiteDatabase.openDatabase(DB_PATH + DATABASE_NAME, null, 0); 
     } 
    } 

MainActivity -> OnCreate

db = new DatabaseHelper(context); 
try { 
    db.createDataBase(); 
} catch (IOException ioe) { 
    throw new Error("Unable to create database"); 
} 

db.openDataBase(); 
Các vấn đề liên quan