男子大学生の考えること

日々思ったこと。プログラミング、音楽、アニメなど、、、

自前のSQLiteDatabaseファイルをassetsからandroidで使えるようにする

androidではSQLiteが使えます。いろんな本なんかを読んでいると、androidの中で
テーブル定義して、データ挿入、削除、更新ができます。。。
みたいなことは書いてあるんですが、
あらかじめ自分で作ったDBファイルを使うことを書いた本がなかなかありません。
ググるといろいろな方法がありますが、
基本的にassetsフォルダに入れて、databaseフォルダにコピーする
ということです。無理やり感がありますがこれしかないみたい。
androidのdatabaseは
data/data/アプリのパッケージ/databases
にあります。
eclipseではファイルエクスプローラで見れますし、ファイルを保存することもできます。
ということで、ググった情報をもとにつくりました。

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

public class DatabaseOpenHelper extends SQLiteOpenHelper {
	
	private static final long serialVersionUID = 1L;
	private static final String DB_FILE_NAME = "database.sqlite"; //assetsにあるDBファイル名
	private static final String DB_NAME = "database.db"; //androidが使うDBファイル名
	private static final int DB_VERSION = 1;
	private Context context;
	private File dbPath;
	private boolean databaseExist = true; //適切なDBファイルが存在するか
	
	public DatabaseOpenHelper(Context context) {
		super(context, DB_NAME, null, DB_VERSION);
		this.context = context;
		this.dbPath = context.getDatabasePath(DB_NAME);
	}

	@Override
	public void onCreate(SQLiteDatabase db) {
		super.onOpen(db);
		databaseExist = false;
	}

	@Override
	public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
		String databasePath = this.dbPath.getAbsolutePath();
		File file = new File(databasePath);
		if(file.exists()){
			file.delete();
		}
		databaseExist = false;
	}
	
	@Override
	public SQLiteDatabase getWritableDatabase() {
		SQLiteDatabase database = super.getWritableDatabase();
		if(!databaseExist){
			try {
				database.close();
				database = copyDatabaseFromAssets();
				databaseExist = true;
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return database;
	}
	
	
	/**
	 * assetsにあるデータベースをdata/data/package/databasesにコピーする
	 * @throws IOException
	 */
	private SQLiteDatabase copyDatabaseFromAssets() throws IOException{
		InputStream inputStream = this.context.getAssets().open(DB_FILE_NAME);
		OutputStream outputStream = new FileOutputStream(dbPath);
		
		byte[] buffer = new byte[1024];
		int size;
		while ((size = inputStream.read(buffer)) > 0) {
			outputStream.write(buffer, 0, size);
		}
		outputStream.flush();
		outputStream.close();
		inputStream.close();
		
		return super.getWritableDatabase();
	}

}

といった感じです。つかう側は

DatabaseOpenHelper helper = new DatabaseOpenHelper(context);
SQliteDatabase database = helper.getWritableDatabase();

と書くだけで、DBフォルダになかったらコピーしてから、あるいはバージョンが異なれば削除した後コピーしてから、適切なDBファイルがあればそのまま取得できます。
assetsのDBファイルを更新した際はDatabaseOpenHelperのDB_VERSIONを+すればいいです。