AndroidでデータベースといえばSQLiteとなると思う。
ただし、PC等でデータベースを作成しておいて、それをアプリから使うとなると少し大変。
プロジェクトのassetsフォルダに置いただけでは開くことができない。
そこで、起動時の始めの1回だけ、assetsに置いたデータベースファイルをデータベースパスへコピーしてやるという方法で解決する。
SQLite扱うクラスSQLiteDatabaseのインスタンスはSQLiteOpenHelperクラスを使って作るのが正しい方法なよう。
そこで、SQLiteOpenHelperを継承したクラスを作成。
getReadableDatabaseメソッド、getWritableDatabaseメソッドそれぞれで、データーベースパスのファイルの有無を確認して、なければassetsからコピーする。
ちなみに以下のソースでは、コンストラクタに渡すversionが変わった時も、コピーし直すようにもしている。
import java.io.IOException; import java.io.File; 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.SQLiteOpenHelper; public class SQLiteOpenFromAssets extends SQLiteOpenHelper { private Context mContext; private String mDBName; private boolean mUpgrade; public SQLiteOpenFromAssets(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) { super(context, name, factory, version); mContext = context; mDBName = name; mUpgrade = false; } protected void resourceCopyFromAsset() throws IOException { File of; File od; InputStream is; OutputStream os; byte[] buf; int size; of = mContext.getDatabasePath(mDBName); od = new File(of.getParent()); od.mkdirs(); is = mContext.getAssets().open(mDBName); os = new FileOutputStream(of); buf = new byte[1024]; for ( ; ; ) { size = is.read(buf); if (0 > size) break; os.write(buf, 0, size); } os.flush(); os.close(); is.close(); } @Override public SQLiteDatabase getReadableDatabase() { try { SQLiteDatabase db; if (! mContext.getDatabasePath(mDBName).exists()) { resourceCopyFromAsset(); } db = super.getReadableDatabase(); if (mUpgrade) { close(); resourceCopyFromAsset(); db = super.getReadableDatabase(); } return db; } catch (IOException e) { return null; } } @Override public SQLiteDatabase getWritableDatabase() { try { SQLiteDatabase db; if (! mContext.getDatabasePath(mDBName).exists()) { resourceCopyFromAsset(); } db = super.getWritableDatabase(); if (mUpgrade) { close(); resourceCopyFromAsset(); db = super.getWritableDatabase(); } return db; } catch (IOException e) { return null; } } @Override public void onCreate(SQLiteDatabase db) { mUpgrade = false; } @Override public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) { mUpgrade = true; } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { mUpgrade = true; } }
使うときはこんな感じ
SQLiteOpenFromAssets helper = new SQLiteOpenFromAssets(context, "test.db", null, 1); SQLiteDatabase db = helper.getReadableDatabase();
補足
SQLiteOpenHelperクラスのソースを見ればわかるが、super.getReadableDatabaseやsuper.getWritableDatabaseメソッド内でバージョンチェックが行われ、状況によってonDowngradeやonUpgradeメソッドが呼ばれる。
onUpgradeメソッドでコピー作業をしたいところだが、トランザクションの最中なので、ココではできない。なのでフラグだけ変えておいて後で処理を行う。
コメントをお書きください