This document written: 2013-07-30 .. 2014-05-28
日本語情報で SQLDroid を JDBC ドライバーとして利用している具体例が見つからず、否定的な情報(使えない等)しか見かけなかったので、少々不安ではあったが、実際にやってみたらちゃんと使えた。
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import android.os.Bundle;
import android.app.Activity;
import android.util.Log;
import android.view.Menu;
public class MainActivity extends Activity {
private static final String dbFile = "Question.db";
private static final int dbFileId = R.raw.question;
private File dbPath;
private InputStream inFile;
private OutputStream outFile;
private byte[] buffer = new byte[1024];
private String url = "jdbc:sqldroid:";
private static final String sqldroidDriver = "org.sqldroid.SQLDroidDriver";
private Statement statement;
private ResultSet result;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
/*
* 予め用意した SQLite データベースファイルを res/raw 以下からコピーする。
* res/raw に配置するファイルには拡張子(やサブフォルダーも?)は使えないようだ。
*
* Android 用の SQLite データベースファイルを PC の SQLite3 で作成するにあたって注意すべき点は、
* _id (Integer)をプライマリーキーとする点(これは必須ではなく、特定の Android の SQLite API で
* プライマリーキー= _id と決め付けている問題児が存在するという話。SQLDroid を使う場合どうでもいいと思う)
* android_metadata (locale TEXT) という名前のテーブルを作成し、
* そこに 'ja_JP' というエントリーを含めておくことである(存在しなければ、自動的に作成されるようだ)。
*/
dbPath = getDatabasePath(dbFile);
try {
//inFile = getAssets().open("databases/" + dbFile);
inFile = getResources().openRawResource(dbFileId);
if (!dbPath.getParentFile().exists()) {
dbPath.getParentFile().mkdir();
}
outFile = new FileOutputStream(dbPath);
int length;
while ((length = inFile.read(buffer)) > 0) {
outFile.write(buffer, 0, length);
}
} catch (IOException e) {
Log.e("File", e.getMessage());
} finally {
try {
outFile.flush();
outFile.close();
inFile.close();
} catch (IOException e) {
Log.e("File", e.getMessage());
}
}
/*
* SQLDroid を JDBC ドライバーとして利用する。
* 不思議なことに、現時点で SQLDroid を使っているという日本語の情報が存在せず、
* Android の独自 API を直接利用しているサンプル情報しか見付からないので、
* 少々不安になったが、普通に使えるようになっている。
* もちろん、Java Build Path で Library として SQLDroid の jar を含めることが必要なのは
* 言うまでもない。(jar はプロジェクトフォルダーの libs 辺りに置いておいておけばよし)
*/
url += dbPath;
try {
Class.forName(sqldroidDriver).newInstance();
statement = DriverManager.getConnection(url).createStatement();
result = statement.executeQuery("select question from Question");
while (result.next()) {
Log.d("DB", "Q: " + result.getString("question"));
}
} catch (InstantiationException e) {
Log.e("DB", e.getMessage());
} catch (IllegalAccessException e) {
Log.e("DB", e.getMessage());
} catch (ClassNotFoundException e) {
Log.e("DB", e.getMessage());
} catch (SQLException e) {
Log.e("DB", e.getMessage());
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
このサンプルでは、Question という表を持つ SQLite データベースファイルから question という列の値を検索して、LogCat に表示している。
最初ハマったのは、そもそも res や assets からのファイルのコピーが正しくできず、それが原因で「データベースが破損しているので、空のデータベースファイルを作成し直した」というエラーが発生し、データベースの操作のあたりに問題があるのかと思って延々悩んでいたら、実は、「単にファイルコピー自体に失敗していて、空ファイルをコピーしていた」というオチ。.read(buffer) を .read() としていたのが原因だった。
俄 Android 開発者なため、DDMS の使い方(存在)すら知らなかったので、この原因を突き止めるために、DDMS というものが使える(エミュレーター上のファイルなどを色々と覗いたりできる)こと自体を知ったのは実に(!)、大きな収穫だった。
《Android》