Android用sqliteデータベースを外部で作成する-その2

前回はAndroidで生成されたDBファイルをLinux Boxに取り出して調べてみたが、今回は逆にLinux Boxで作ったDBファイルをAndroidにコピーして読み込めるか調べてみる。

スポンサーリンク

データベース生成用PHPスクリプト

sqlite3をコマンドラインで直接操作してもDBファイルは作れる。けれど、投稿のカテゴリなど属性情報のテーブルはデータを予め入れておきたいし、スクリプトである程度自動化したい。そこで、PHPはsqliteをネイティブサポートしていることもあって、PHPでDBファイル生成用スクリプトを作成することにした。

#! /usr/bin/php -q
<?php
/**
 * CSVデータからテーブル定義を抽出してSQL化、同時にデータも抽出してテーブルに追加する
 */

$db = new MyDB();

$tables = array('android_metadata', 'category', 'subcategory', 'record');

foreach($tables as $tbl) {
    $csvfile = $tbl . '.csv';
    $file = new SplFileObject($csvfile); 
    $file->setFlags(SplFileObject::READ_CSV);
    $lineCount = 0;
    foreach ($file as $line) {
        $lineCount++;
        if(!is_null($line[0])){
            $linmb = mb_convert_encoding($line, 'utf-8', 'sjis');
            switch($lineCount) {
            case 1:
                $fieldName = $linmb;
                break;
            case 2:
                $fieldType = $linmb;
                $fieldList = createSQLtable($db, $tbl, $fieldName, $fieldType);
                break;
            default:
                $fldCnt = count($linmb);
                $sql = 'INSERT INTO ' . $tbl . ' ' . $fieldList . " values ('" . $linmb[0] . "'";
                for($n = 1; $n < $fldCnt; $n++) {
                    $sql .= ',' . "'$linmb[$n]'";
                }
                $sql .= ')';
                $db->exec($sql);
                print "$sql\n\n";
            }
        }
    } 

}

function createSQLtable($db, $tableName, $fieldName, $fieldType)
{
    $sql = 'create table ' . $tableName;
    $fldCnt = count($fieldName);
    if ( $fldCnt == count($fieldType) ) {
        $fldList = '(' . $fieldName[0];
        $sql .= ' (' . $fieldName[0] . ' ' . $fieldType[0];
        for($n = 1; $n < $fldCnt; $n++) {
            $sql .= ', ' . $fieldName[$n] . ' ' . $fieldType[$n];
            $fldList .= ', ' . $fieldName[$n];
        }
        $sql .= ')';
        $fldList .= ')';
        $db->exec($sql);
        return $fldList;
    } else {
        print $tableName . ":Field Count Mismatch\n";
        return null;
    }
}

class MyDB extends SQLite3
{
    function __construct()
    {
        $this->open('myLog.db');
    }
}

?>

$tables配列にテーブル名を入れておき、’テーブル名.csv’という名前のCSVファイルを別途用意しておく。このCSVは、以下のフォーマットでカンマ区切りテキストでデータを入れておく(次節で実データも挙げます)。

  • 1行目:カラム名
  • 2行目:カラムのデータ型
  • 3行目〜:テーブルのデータ

そして、createSQLtable関数が上記CSVファイルを読み込んだうえで、以下の操作を行う。

  1. データベースにcreate table文でテーブルを作成する
  2. CSVの3行目以降の値をテーブルにデータ登録する

テーブル作成用CSVファイル

上記スクリプトで用いるCSVファイルも挙げておく。

  • android_metadata.csv
locale
TEXT
ja_JP
  • category.csv
CatID,CatName
INTEGER,TEXT
1,仕事
2,日本酒
3,旅
  • subcategory.csv
CatID,SubID,SubName
INTEGER,INTEGER,TEXT
1,1,仕事1
1,2,仕事2
1,3,仕事3
2,1,美味かった
2,2,不味かった
3,1,ハワイ2019
3,2,ヨーロッパ2020
  • record.csv
ID,DateTime,CatID,SubID,Comment,Photo1,Photo2,Photo3,Photo4,Link
INTEGER,TEXT,INTEGER,INTEGER,TEXT,TEXT,TEXT,TEXT,TEXT,INTEGER
1,2019/3/26 12:34,1,1,テスト,,,,,0

作ったDBファイルをコマンドラインで確認

コマンドラインのsqliteを使って作成したDBファイルをチェックする。

$ sqlite3 myLog.db
SQLite version 3.22.0 2018-01-22 18:45:57
Enter ".help" for usage hints.
sqlite> .tables
android_metadata  category          record            subcategory     
sqlite> .schema record
CREATE TABLE record (ID INTEGER, DateTime TEXT, CatID INTEGER, SubID INTEGER, Comment TEXT, Photo1 TEXT, Photo2 TEXT, Photo3 TEXT, Photo4 TEXT, Link INTEGER);
sqlite> select * from record;
1|2019/3/26 12:34|1|1|テスト|||||0

特に問題無さそう。

作ったDBファイルをAndroid端末で読み込む

上記で作ったファイルをSDカード経由でadb shellによってアプリの管理領域にコピーする。実際のアプリではSDカード経由だと色々面倒なので別途方法を考える必要があるが、とりあえず今回はテストのために簡単な方法で。

$ adb shell
shell@SC-03E:/ $ su
su
root@SC-03E:/ # ls /storage/extSdCard/Temp
ls /storage/extSdCard/Temp
myLog.db
root@SC-03E:/ # cd /data/data/com.example.androidtest/databases
cd /data/data/com.example.androidtest/databases
root@SC-03E:/data/data/com.example.androidtest/databases # cp /storage/extSdCard/Temp/myLog.db .
e/extSdCard/Temp/myLog.db .                                                   <
root@SC-03E:/data/data/com.example.androidtest/databases # ls
ls
myLog.db

上記データベースを扱うためには、SQLiteOpenHelperの派生クラスを作ってやる必要がある。詳細は別記事に譲るとして、今回はテストコードの断片だけ挙げておく。

    public void getDbTableDetails() {
    Cursor c = db.rawQuery("SELECT name FROM sqlite_master WHERE type='table'", null);
    int count = 0;
    Log.i("DBA","*** Table List of '" + DATABASE_NAME + "' ***");
    for (c.moveToFirst(); !c.isAfterLast(); c.moveToNext()) {
        String temp = c.getString(0);
        count++;
        Log.i("DBA","Table" + count + ":" + temp);
    }
    }

上記を実行すると、LogCatのinfoセクションにテーブル一覧が表示される。

05-19 09:28:56.796 9055-9055/com.example.androidtest I/DBA: *** Table List of 'myLog.db' ***
05-19 09:28:56.801 9055-9055/com.example.androidtest I/DBA: Table1:android_metadata
05-19 09:28:56.801 9055-9055/com.example.androidtest I/DBA: Table2:category
05-19 09:28:56.801 9055-9055/com.example.androidtest I/DBA: Table3:subcategory
05-19 09:28:56.801 9055-9055/com.example.androidtest I/DBA: Table4:record

コメント