2015-06-27 44 views
0

我有一個靜態的sqlite數據庫。我怎麼能把它包含到應用程序中?我應該把它放在我的項目文件夾中?我應該如何從DatabaseHandler訪問它?如何使用我的自定義SQLite數據庫與Android應用程序?

我在網上發現的所有東西都是使用sqlite創建一個新的數據庫,並在其中存儲用戶或臨時數據,但沒有使用預定義數據的現有數據庫。

Official Google docs不知道該怎麼做。

+1

只需將它放在您的'assets'文件夾中即可。然後將其複製到您的應用程序數據庫路徑(如果不存在)。用它。要開心。 –

回答

0

處理這種情況基本上只是做一個文件複製。

棘手的部分是

  • 要創建數據庫只需要(否則只是打開它)
  • 要實現升級邏輯

我寫了一個示例助手類,演示如何當從資產中加載數據庫。

public abstract class SQLiteAssetHelper extends SQLiteOpenHelper { 

    // ---------------------------------- 
    // CONSTANTS 
    // ---------------------------------- 

    private static final String DATABASE_DIR_NAME = "databases"; 

    // ---------------------------------- 
    // ATTRIBUTES 
    // ---------------------------------- 

    private final Context mContext; 
    private final CursorFactory mFactory; 

    private SQLiteDatabase mDatabase; 

    private String mDatabaseName; 
    private String mDatabaseAssetPath; 
    private String mDatabaseDiskPath; 

    private boolean mIsProcessingDatabaseCreation; // Database creation may take some time 

    // ---------------------------------- 
    // CONSTRUCTORS 
    // ---------------------------------- 

    public SQLiteAssetHelper(Context context, String name, CursorFactory factory, String destinationPath, int version) { 
     super(context, name, factory, version); 

     mContext = context; 
     mFactory = factory; 

     mDatabaseName = name; 

     mDatabaseAssetPath = DATABASE_DIR_NAME + "/" + name; 
     if (destinationPath == null) { 
      mDatabaseDiskPath = context.getApplicationInfo().dataDir + "/" + DATABASE_DIR_NAME; 
     } else { 
      mDatabaseDiskPath = destinationPath; 
     } 
    } 

    // ---------------------------------- 
    // OVERRIDEN METHODS 
    // ---------------------------------- 

    @Override 
    public synchronized SQLiteDatabase getWritableDatabase() { 
     if (mDatabase != null && mDatabase.isOpen() && !mDatabase.isReadOnly()) { 
      // the database is already open and writable 
      return mDatabase; 
     } 

     if (mIsProcessingDatabaseCreation) { 
      throw new IllegalStateException("getWritableDatabase is still processing"); 
     } 

     SQLiteDatabase db = null; 
     boolean isDatabaseLoaded = false; 

     try { 
      mIsProcessingDatabaseCreation = true; 
      db = createOrOpenDatabase(); 
      // you should probably check for database new version and process upgrade if necessary 
      onOpen(db); 
      isDatabaseLoaded = true; 
      return db; 
     } catch (IOException e) { 
      e.printStackTrace(); 
      return null; 
     } finally { 
      mIsProcessingDatabaseCreation = false; 
      if (isDatabaseLoaded) { 
       if (mDatabase != null) { 
        try { 
         mDatabase.close(); 
        } catch (Exception e) { 
         e.printStackTrace(); 
        } 
       } 
       mDatabase = db; 
      } else { 
       if (db != null) db.close(); 
      } 
     } 
    } 

    @Override 
    public final void onCreate(SQLiteDatabase db) { 
     // getWritableDatabase() actually handles database creation so nothing to code here 
    } 

    @Override 
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 
     // TODO implement your upgrade logic here 
    } 

    // ---------------------------------- 
    // PRIVATE METHODS 
    // ---------------------------------- 

    private void copyDatabaseFromAssets() throws IOException { 

     String dest = mDatabaseDiskPath + "/" + mDatabaseName; 
     String path = mDatabaseAssetPath; 

     InputStream is = mContext.getAssets().open(path); 

     File databaseDestinationDir = new File(mDatabaseDiskPath + "/"); 
     if (!databaseDestinationDir.exists()) { 
      databaseDestinationDir.mkdir(); 
     } 
     IOUtils.copy(is, new FileOutputStream(dest)); 
    } 

    private SQLiteDatabase createOrOpenDatabase() throws IOException { 

     SQLiteDatabase db = null; 
     File file = new File (mDatabaseDiskPath + "/" + mDatabaseName); 
     if (file.exists()) { 
      db = openDatabase(); 
     } 

     if (db != null) { 
      return db; 
     } else { 
      copyDatabaseFromAssets(); 
      db = openDatabase(); 
      return db; 
     } 
    } 

    private SQLiteDatabase openDatabase() { 
     try { 
      SQLiteDatabase db = SQLiteDatabase.openDatabase(
        mDatabaseDiskPath + "/" + mDatabaseName, mFactory, SQLiteDatabase.OPEN_READWRITE); 
      return db; 
     } catch (SQLiteException e) { 
      e.printStackTrace(); 
      return null; 
     } 
    } 

    // ---------------------------------- 
    // NESTED CLASSES 
    // ---------------------------------- 

    private static class IOUtils { 

     private static final int BUFFER_SIZE = 1024; 

     public static void copy(InputStream in, OutputStream outs) throws IOException { 
      int length; 
      byte[] buffer = new byte[BUFFER_SIZE]; 

      while ((length = in.read(buffer)) > 0) { 
       outs.write(buffer, 0, length); 
      } 

      outs.flush(); 
      outs.close(); 
      in.close(); 
     } 

    }; // IOUtils 

} 

然後你只需要創建從一個以上這樣的擴展類:

public class MyDbHelper extends SQLiteAssetHelper { 

    // ---------------------------------- 
    // CONSTANTS 
    // ---------------------------------- 

    private static final int DATABASE_VERSION = 1; 
    private static final String DATABASE_FILE_NAME = "test.db"; 

    // ---------------------------------- 
    // CONSTRUCTORS 
    // ---------------------------------- 

    public MyDbHelper(Context context) { 
     super(context, DATABASE_FILE_NAME, null, context.getFilesDir().getAbsolutePath(), DATABASE_VERSION); 
    } 

} 

每次會從你的MyDbHelper實例調用getWritableDatabase(),它會做所有的副本/爲你打開東西並返回可寫數據庫。

正如我之前所說的,我沒有在這個示例中實現upgrade()方法,您將不得不這樣做。 我也沒有實現getReadableDatabase(),因爲我通常只使用getWritableDatabase()。你可能需要這樣做。

如果你想測試它,只需做到以下幾點:以上

    • 複製的代碼創建一個名爲「數據庫」,在你的資產的文件夾,並在裏面
    • 插入您的SQLite數據庫文件在MyDatabaseHelper中,使用資產文件夾中的數據庫名稱更改DATABASE_FILE_NAME常量的值
    • 不要忘記實例化MyDatabaseHelper並調用getWritableDatabse()

    希望這對我有所幫助。

  • 相關問題