作者 : 林致宇日期 :2011/10/26 主要參考來源 : http://www.reigndesign.com/blog/using-your-own-sqlite-database-in-android-applicat ions/ 問題 : 如在存取一個已經建立好的資料庫? 解答 : 有一些應用程式會需要讀取已經建立好的資料庫, 例如一個試題測驗應用程式, 裡面的試題可能已經於電腦上, 使用任何的 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 除了此命令列工具之外, 當然還有其它具有較佳介面的工具可以使用, 例如網站 [2] 所介紹的 SQLite Database Browser, 讀者可至網站 [2] 下載 然而為了讓資料庫能夠正常地被 Android 所讀取, 有兩點必須注意 : 表格必須有一個名為 _id 的欄位, 且 type 要設成 INTEGER PRIMARY KEY 必須建立一個名為 android_metadata 的表格, 表格中要建立一個名為 locale 的欄位, 經筆者的測試, 我們不需要新增任何記錄 程式碼的撰寫 此處主要是參考網站 [2] 的說明而改寫的, 專案裡面共有兩個檔案 : DatabaseHelper.java 1 package lincyu.demo.database_from_outside; 2 3 import java.io.fileoutputstream; 4 import java.io.inputstream; 5 import java.io.outputstream; 6 7 import android.content.context; 8 import android.database.sqlite.sqlitedatabase; 9 import android.database.sqlite.sqliteexception; 10 import android.database.sqlite.sqliteopenhelper; 11 12 class DatabaseHelper extends SQLiteOpenHelper { 13 14 private static String DB_PATH = 15 "/data/data/" + 16 "lincyu.demo.database_from_outside" + 17 "/databases/"; 18 private static String DB_NAME = "questions.db"; 19 20 private final Context mctx; 21 22 public DatabaseHelper(Context context) { 23 super(context, DB_NAME, null, 1);
24 this.mctx = context; 25 } 26 27 public boolean createdatabase() { 28 boolean dbexist = checkdatabase(); 29 this.getreadabledatabase(); 30 if (dbexist == false) { 31 if (copydatabase() == false) { 32 return false; 33 } 34 } 35 return true; 36 } 37 38 private boolean checkdatabase() { 39 SQLiteDatabase checkdb = null; 40 String dbpath = DB_PATH + DB_NAME; 41 try { 42 checkdb = SQLiteDatabase.openDatabase(dbpath, 43 null, SQLiteDatabase.OPEN_READONLY); 44 } catch (SQLiteException e) { 45 return false; 46 } 47 if (checkdb!= null) { 48 checkdb.close(); 49 return true; 50 } 51 return false; 52 } 53 54 private boolean copydatabase() { 55 try { 56 InputStream input = mctx.getassets().open(db_name); 57 this.getreadabledatabase(); 58 String outfilename = DB_PATH + DB_NAME; 59 OutputStream output = 60 new FileOutputStream(outFileName); 61 byte [] buffer = new byte[1024];
62 int length; 63 while ((length = input.read(buffer)) > 0) { 64 output.write(buffer, 0, length); 65 } 66 output.flush(); 67 output.close(); 68 input.close(); 69 } catch (Exception e) { 70 return false; 71 } 72 return true; 73 } 74 75 @Override 76 public void oncreate(sqlitedatabase db) { 77 } 78 79 @Override 80 public void onupgrade(sqlitedatabase db, int oldv, int newv) { 81 } 82 } Database_From_Outside.java 1 package lincyu.demo.database_from_outside; 2 3 import android.app.activity; 4 import android.database.cursor; 5 import android.database.sqlite.sqlitedatabase; 6 import android.os.bundle; 7 import android.view.view; 8 import android.view.view.onclicklistener; 9 import android.widget.button; 10 import android.widget.textview; 11 import android.widget.toast; 12 13 public class Database_From_Outside extends Activity { 14 /** Called when the activity is first created. */ 15 @Override
16 public void oncreate(bundle savedinstancestate) { 17 super.oncreate(savedinstancestate); 18 setcontentview(r.layout.main); 19 20 DatabaseHelper dbhelper = new DatabaseHelper(this); 21 22 if (dbhelper.createdatabase() == false) { 23 Toast.makeText(this, " 無法建立 / 開啟資料庫 ", 24 Toast.LENGTH_SHORT).show(); 25 finish(); 26 return; 27 } 28 29 SQLiteDatabase db = dbhelper.getreadabledatabase(); 30 31 Cursor c = db.rawquery("select * from questions", null); 32 33 if (c.getcount() == 0) { 34 Toast.makeText(this, " 資料庫內無任何資料 ", 35 Toast.LENGTH_SHORT).show(); 36 finish(); 37 return; 38 } 39 c.movetofirst(); 40 41 final String question, answer; 42 43 question = c.getstring(c.getcolumnindex("_question")); 44 answer = c.getstring(c.getcolumnindex("_answer")); 45 46 db.close(); 47 48 TextView tv = (TextView)findViewById(R.id.question); 49 tv.settext(question); 50 51 Button btn = (Button)findViewById(R.id.btn_show_answer); 52 btn.setonclicklistener(new OnClickListener() { 53 public void onclick(view arg0) {
54 Toast.makeText(Database_From_Outside.this, 55 answer, Toast.LENGTH_SHORT).show(); 56 } 57 }); 58 } 59 } 程式測試 如果出現下面的畫面, 就代表資料庫被成功地讀取了 參考資料 : [1] SQLite Home Page, http://www.sqlite.org/ [2] Using your own SQLite database in Android applications ReignDesign, http://www.reigndesign.com/blog/using-your-own-sqlite-database-in-android-applicat ions/