へんてこのブログ

日々気づいたことや、最近やっていることを書いています

既存のDBをAndroidで使えるようにする方法

既存のDBをAndroidで使えるようにする方法を書いてみます

今回は下の二つのサイトを参考にさせていただきました
http://y-anz-m.blogspot.com/2011/01/android-sqline-database.html
http://d.hatena.ne.jp/ipreachable/20110129/1296326519

なぜか自分の環境では上のサイトのやり方ではうまくできなかったので、そのやり方を書きます

まずextends SQLiteOpenHelperしたクラスの紹介(パッケージ名省略)

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

import android.content.Context;
import android.content.res.AssetManager;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;

public class DataBaseHelper extends SQLiteOpenHelper {  
	private static final String TAG = "DataBaseHelper";
    private static final String SRC_DATABASE_NAME = "test.db";  // assetsフォルダにあるdbのファイル名
    private static final String DATABASE_NAME = "test.db.db";  // コピー先のDB名
    private static final int DATABASE_VERSION = 1;

    private final Context context;
    private final File databasePath;
    private boolean createDatabase = false;

    public DataBaseHelper(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
        
        this.context = context;
        this.databasePath = context.getDatabasePath(DATABASE_NAME);
        
        
        
    }

    @Override
    public synchronized SQLiteDatabase getWritableDatabase() {
        SQLiteDatabase database = super.getWritableDatabase();
        if (createDatabase) {
            try {
                database = copyDatabase(database);
            } catch (IOException e) {
                //Log.wtf(TAG, e);
                // TODO: エラー処理
            }
            
        }
        return database;
    }

    private SQLiteDatabase copyDatabase(SQLiteDatabase database) throws IOException {
        // dbがひらきっぱなしなので、書き換えできるように閉じる
        database.close();

        // コピー!
        InputStream input = context.getAssets().open(SRC_DATABASE_NAME);
        OutputStream output = new FileOutputStream(databasePath);
        copy(input, output);
        
        createDatabase = false;
        // dbを閉じたので、また開く
        return super.getWritableDatabase();
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        super.onOpen(db);
        // getWritableDatabase()したときに呼ばれてくるので、
        // 初期化する必要があることを保存する
        this.createDatabase = true;
    }

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

    // CopyUtilsからのコピペ
    private static int copy(InputStream input, OutputStream output) throws IOException {
        byte[] buffer = new byte[1024 * 4];
        int count = 0;
        int n = 0;
        while (-1 != (n = input.read(buffer))) {
            output.write(buffer, 0, n);
            count += n;
        }
        return count;
    }
    
    
}

こんな感じです
ipreachableさんの日記の物を丸写しした感じですねw

これでDBの準備ができました
あとはこれの使い方です
extends Activityをしたクラス(パッケージ名とかimport省略)

public class mainActivity extends Activity {
    /** Called when the activity is first created. */
	
	private DataBaseHelper mDbHelper;  
	private SQLiteDatabase db;  

        @Override  
	public void onCreate(Bundle savedInstanceState) {  
	    super.onCreate(savedInstanceState);  
	    setContentView(R.layout.main);

            mDbHelper = new DataBaseHelper(this);
            db = mDbHelper.getWritableDatabase();
            
            //あとは適当にクエリ投げたりできる
            Cursor textCursor = db.query("test_table", null, null, null, null, null, null);

}

こちらはY.A.M さんの 雑記帳をメインに書き写しましたが、若干修正しています
これでassets内に入っているDBファイルを内部で作成したDBのように使うことができます

ただ、Androidのassetsにはファイルの要領制限があるらしく、1M以上の物は入れられません
入れるとエラーがでます
そこの解決法もできたら記事にしたいと思います

一応こんなやり方でできるみたいですけどよくわかりませんw
http://d.hatena.ne.jp/itog/20091228/1262016898