|
資料庫存取相關的 Android 類別,包含了 SQLiteOpenHelper, SQLiteDatabase, Cursor 等,介紹如何從 assets 資料夾讀取一個已經存在的資料庫,並將之寫入 /data/data/<package name>/databases 裡,若使用 ADT Bundle (Eclipse),assets 資料夾位於 Project 的根目錄下,若使用 Android Studio,您必須在 /app/src/main 自行建立 assets 資料夾 [1]。
有一些應用程式會需要讀取已經建立好的資料庫,例如一個試題測驗應用程式,裡面的試題可能已經於電腦上,使用任何的 SQLite 資料庫產生工具,產生一個資料庫檔案(例如:questions.db),我們會希望我們的應用程式能夠直接讀取這個檔案,而不是在應用程式第一次執行時,利用程式去做 INSERT 的動作,下面將示範如何實作出這樣的功能。
第一個步驟是產生 SQLite 資料庫檔案,產生資料庫檔案的工具很多,其中一個是到 SQLite 的官方網站[1]下載,以 Windows 作業系統為例,網站有提供一個已經編譯好的命令列工具 sqlite3.exe,首先進入 Windows 所提供的『命令提示字元』,進入放置 sqlite3.exe 的資料夾後就可以執行它,執行時後面加個檔案名稱當參數,下面是一個範例:
C:\>sqlite3 questions.db
SQLite version 3.7.8 2011-09-19 14:49:19
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite> create table questions(_question, _type, _answer);
sqlite> insert into questions values("1+1", "Math", "2");
sqlite> .exit
在上面的範例中,我們做了兩件事,首先建立一個表格,接著再插入一筆資料到表格內,我們可以再次執行 sqlite3,來驗證資料是否有正確被寫入:
C:\>sqlite3 questions.db
SQLite version 3.7.8 2011-09-19 14:49:19
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite> select * from questions;
1+1|Math|2
除然而為了讓資料庫能夠正常地被 Android 所讀取,有兩點必須注意:
表格必須有一個名為『_id』的欄位,且 type 要設成『INTEGER PRIMARY KEY』。
必須建立一個名為『android_metadata』的表格,表格中要建立一個名為『locale』的欄位,經筆者的測試,我們不需要新增任何記錄。
產生好 questions.db 後我們就可以把這個檔案放到 assets 資料夾,接著就是要進行程式的撰寫:
- package lincyu.demo.database_from_outside;
-
- import java.io.FileOutputStream;
- import java.io.InputStream;
- import java.io.OutputStream;
-
- import android.content.Context;
- import android.database.sqlite.SQLiteDatabase;
- import android.database.sqlite.SQLiteException;
- import android.database.sqlite.SQLiteOpenHelper;
-
- class DatabaseHelper extends SQLiteOpenHelper {
-
- private static String DB_PATH = "/data/data/" +
- "lincyu.demo.database_from_outside" + "/databases/";
- private static String DB_NAME = "questions.db";
-
- private final Context mCtx;
-
- public DatabaseHelper(Context context) {
- super(context, DB_NAME, null, 1); 24 this.mCtx = context;
- }
-
- public boolean createDatabase() {
- boolean dbExist = checkDatabase();
- this.getReadableDatabase();
- if (dbExist == false) {
- if (copyDatabase() == false) {
- return false;
- }
- }
- return true;
- }
-
- private boolean checkDatabase() {
- SQLiteDatabase checkDB = null;
- String dbpath = DB_PATH + DB_NAME;
- try {
- checkDB = SQLiteDatabase.openDatabase(dbpath,
- null, SQLiteDatabase.OPEN_READONLY);
- } catch (SQLiteException e) {
- return false;
- }
- if (checkDB != null) {
- checkDB.close();
- return true;
- }
- return false;
- }
-
- private boolean copyDatabase() {
- try {
- InputStream input = mCtx.getAssets().open(DB_NAME);
- this.getReadableDatabase();
- String outFileName = DB_PATH + DB_NAME;
- OutputStream output =
- new FileOutputStream(outFileName);
- byte [] buffer = new byte[1024];
- int length;
- while ((length = input.read(buffer)) > 0) {
- output.write(buffer, 0, length);
- }
- output.flush();
- output.close();
- input.close();
- } catch (Exception e) {
- return false;
- }
- return true;
- }
-
- @Override
- public void onCreate(SQLiteDatabase db) {
- }
-
- @Override
- public void onUpgrade(SQLiteDatabase db, int oldV, int newV) {
- }
- }
複製代碼
從程式碼我們不能發現,其實就只是單純的讀寫檔案,然而必須一提的是,要存取 assets 資料夾必須利用 Context 類別的 getAssets 方法來存取,getAssets 會回傳一個 AssetManager 物件,再呼叫其 open,就可讀取 assets 資料夾下的檔案。
參考資料
[1] Where to place Assets folder in Android Studio - Stack Overflow, http://stackoverflow.com/questions/18302603/where-to-place-assets-folder-in-android-studio
https://ithelp.ithome.com.tw/articles/10158728
|
|