Androidアプリ開発でSQLiteへデータ保存するときのTips

androidのGPSで取得した位置情報を、ローカルのデータベース(SQLite)に保存してみたときに、ちょっと悩まされたので、基本的なところをメモ。

保存したい内容は次の3つ

◆時刻(GPS情報取得した時間)
◆経度
◆緯度

今使ってる開発環境
AndroidSDK r20.0.3
Eclipse IDE for Java EE Developers_ Juno (4.2)64Bit版


(1)テーブル設計
まず、SQLiteで使用できるデータ型はどうなっているかというと、

INTEGER 符号付整数
REAL   浮動小数点
TEXT   テキスト
BLOB   バイナリデータ
NULL   NULL

Date型がないので、時刻として、「1970/1/1 00:00:00 UTC からのミリ秒」を使うことにする。SQLiteには、INTEGER型で保存。
経度・緯度については、小数点が含まれるため、SQLiteにはREAL型で保存。
また、主キーとして、「id」カラムをつけておく。
テーブル作成時のSQLは、以下のような感じになった。

        private static final String CREATE_TABLE_SQL =
          "create table gpsRawData"
          + "(id         integer primary key autoincrement,"
          + " dateMillis integer not null,"
          + " latitude   real    not null,"
          + " longitude  real    not null"
          + ")";
          :  :  :
      (以下省略)

(2)データ投入

データinsertするやり方としては、ContentValuesを使うやり方、SQLiteDatabase.execSQL()、の2通りあるらしい。

execSQLは、SQL文をそのまま実行できる。ただし、insert、update、deleteの時にしか使えない。(検索(select文)をしたいときは、rowQuery()メソッドやquery()メソッドでできるらしい)

SQL文をEclipseが構文チェックしてくれない気がするので、今回は、ContentValuesを使うことにした。
コードは以下のような感じになった(lat、lotは、それぞれ緯度、経度の値が入っています)

        // DBへデータ保存
        DatabaseHelper dbhelper = new DatabaseHelper(this);
        SQLiteDatabase db = dbhelper.getWritableDatabase();

        ContentValues values = new ContentValues();
        values.put("dateMillis", mStartTimeMillis);
        values.put("latitude", lat);
        values.put("longitude", lon);

        try {
            db.insert("gpsRawData", null, values);
        } catch (Exception e) {
            Toast.makeText(this, "データの保存に失敗しました", Toast.LENGTH_SHORT).show();
        } finally {
            db.close();
        }

(3)データ検索

SQLで言うところのselect文を実行したいときは、SQLiteDatabaseの、rawQuery()メソッドやquery()メソッドで行う。
rawQueryメソッドはSQL文をそのまま実行できるとのこと。

で、query()メソッドの書き方を見てみると、

Cursor query(boolean distinct, String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit)

groupByとか、orderByってところで、条件指定できる模様。ただ、where句が無さそう。
今回の場合、時刻で条件を指定したいと思っている。「12:00~今」といった感じの条件をwhere句で指定したい。
なので、rawQueryメソッドを使うことにした。

コードは以下のような感じにした。
str_fromDateに昔の時刻が入っていて、過去の○時○分から現在までのデータを取得しています。
きちんとデータ取得できているか確認するために、ログにデータを表示させています(Log.dのところ)

        // DBからデータ読み込み
        DatabaseHelper dbhelper = new DatabaseHelper(this);
        SQLiteDatabase db = dbhelper.getReadableDatabase();

        String str_sql = "select * from gpsRawData where dateMillis > " + str_fromDate;

        try {
            Cursor c = db.rawQuery(str_sql, null);

            while( c.moveToNext() ){
                Log.d("result",":" + c.getLong(1) + " " + c.getDouble(2) + " " + c.getDouble(3));
            }

        } catch (Exception e) {
            Toast.makeText(this, "データの検索に失敗しました", Toast.LENGTH_SHORT).show();
        } finally {
            db.close();
        }

---------------
12/15追記
上記のソースコードの、ミスプリ修正しました。
「時刻、緯度、経度」をログ出力しているところの、引数が違っていました。

Log.d("result",":" + c.getLong(0) + " " + c.getDouble(1) + " " + c.getDouble(2));
Log.d("result",":" + c.getLong(1) + " " + c.getDouble(2) + " " + c.getDouble(3));

---------------

(4)SQLiteの操作

Android Debug Bridge (adb)をつかって、SQLiteに接続(ログイン)できる。
これで、直接DBのテーブルの中身を見ることができる。テーブルが作成できているか、データが保存されているか、直接確認できる。

Androidエミュレータが起動している状態で、Windowsのコマンドプロンプトから、「adb shell」を実行する。そうするとコマンドプロンプト「#」が返ってくる。

 C:\~\~>adb shell
 #

(adbにパスが通っていない場合は、以下の場所にあるadbを直接実行するか、Pathを通してください。
C:\[AndroidSDKインストール先]\android-sdk\platform-tools )

cdコマンドでディレクトリ移動して、lsコマンドでデータベースを確認します

 # cd /data/data/[パッケージ名]/databases
 cd /data/data/[パッケージ名]/databases
 # ls
 ls
 [DB名].db

sqlite3コマンドでデータベースに接続します。

 # sqlite3 (データベース名)
 sqlite3 (データベース名)
 SQLite version 3.5.9
 Enter ".help" for instructions
 sqlite>

ここからさらに以下のコマンドで、テーブル一覧とテーブル定義をチェックできる。

「.tables」 テーブルの一覧表示
「.schema [テーブル名]」 テーブルの定義を表示

テーブル内のデータは、SQL文で見る

「select * from [テーブル名];」

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s