初期データの投入方法

いやお久しぶりです。

データの管理にSQLiteを使うとして、初期データを作るのに、数テーブル、数件程度のデータであれば
SQLiteOpenHelperのonCreate内に直接SQLを書いてやれば良いですが、
数百件にもなるとそうも言ってられなくなります。

方法としては、SQLiteファイルを予め用意しておき、直接コピーして使う方法がありますが、
参考:http://y-anz-m.blogspot.com/2011/01/android-sqline-database.html


SQLiteからdumpしたデータを流し込む方法を紹介したいと思います。
前提条件として、予め必要なデータの入ったSQLiteデータベースは用意されているとします。
こんな感じの、「test.sqlite」を用意しておきました。

sqlite> .schema
CREATE TABLE test_table( _id integer primary key, name text, total int);
sqlite> select * from test_table;
1|hogehoge|100
2|fugafuga|200
3|foo|300
4|bar|400

こいつをdumpしてsqlファイルにします。dumpの方法はMac、Linuxでsqlite3コマンドを使うなら

> sqlite3 test.sqlite .dump > dump.sql

これでdump.sqlが出来ます。中身は

> cat dump.sql 
PRAGMA foreign_keys=OFF;
BEGIN TRANSACTION;
CREATE TABLE test_table( _id integer primary key, name text, total int);
INSERT INTO "test_table" VALUES(1,'hogehoge',100);
INSERT INTO "test_table" VALUES(2,'fugafuga',200);
INSERT INTO "test_table" VALUES(3,'foo',300);
INSERT INTO "test_table" VALUES(4,'bar',400);
COMMIT;

こうなってました。
このファイルから必要無い行を削除して、Androidプロジェクトのassetsディレクトリに保存します。
必要な行だけというのは場合にもよりますが、SQLiteOpenHelperのonCreateでデータを作成する場合、
onCreate自体がトランザクション内部で行われるため、dumpファイルからトランザクションに関係する部分を消す必要があります。

CREATE TABLE test_table( _id integer primary key, name text, total int);
INSERT INTO "test_table" VALUES(1,'hogehoge',100);
INSERT INTO "test_table" VALUES(2,'fugafuga',200);
INSERT INTO "test_table" VALUES(3,'foo',300);
INSERT INTO "test_table" VALUES(4,'bar',400);

このファイルを「dump.sql」で保存して、assets直下に保存したとします。

SQLiteOpenHelperのonCreate()をこんな感じで実装しました。

@Override
public void onCreate(SQLiteDatabase db) {
    InputStream is;
    BufferedReader bfReader;
        try {
            is = mContext.getAssets().open("dump.sql");
            bfReader = new BufferedReader(new InputStreamReader(is));
            StringBuilder sb = new StringBuilder();
            String line;
            while(( line = reader.readLine() ) != null){
                if(! line.equals("") ){
                    line.append(str);
                    line.append("\n");
                }
            }
            sb.deleteCharAt(sb.length()-1);
            for(String sql: sb.toString().split(";")){
                db.execSQL(sql);
            }
        } catch (IOException e) {
             e.printStackTrace();
    }
}

全部読み込んで、「;」で分割して1文ずつexecSQLをかけてやります。
データ中に改行が含まれている場合も上手く登録出来るように考慮したつもりですが、
データ中に「;」が現れたらどうするの?とか、細かい部分はよしなに考える必要があるかと。

CUIのみでAndroidの開発環境を作る

何の役に立つのか疑問ですが、一貫した情報が無くハマりポイントが多かったので書いときます。
環境はさくらのVPS上に作りました。正真正銘のCUIです。
http://vps.sakura.ad.jp/
最小構成でインストールしたCentOSに、カーネルは2.6.18-194.8.1.el5 x86_64です。古い・・・

Javaの環境

まずはJavaの実行環境が必要です。openjdkを使えば良いと思います。
yumに「java-1.6.0-openjdk.x86_64」があったのでインストールしました。

Android SDK

Linux用のAndroid SDKをダウンロードしてきます。
http://developer.android.com/sdk/index.html
適当なディレクトリに展開。
ここでダウンロードしたAndroid SDKはtoolsだけで、platformsやadd-onsなどの開発に必要なコンポーネントを下記ドキュメントを参考に整えていくのですが、これがGUIが前提になっているので厄介でした。
http://developer.android.com/sdk/adding-components.html
コマンドラインから./tools/androidを起動しても、GUIを立ち上げようとするので当然エラーになります。

# tools/android 

Starting Android SDK and AVD Manager
No command line parameters provided, launching UI.
See 'android --help' for operations from the command line.
Exception in thread "main" org.eclipse.swt.SWTError: No more handles [gtk_init_check() failed]
	at org.eclipse.swt.SWT.error(Unknown Source)
	at org.eclipse.swt.widgets.Display.createDisplay(Unknown Source)
	at org.eclipse.swt.widgets.Display.create(Unknown Source)
	at org.eclipse.swt.graphics.Device.<init>(Unknown Source)
	at org.eclipse.swt.widgets.Display.<init>(Unknown Source)
	at org.eclipse.swt.widgets.Display.<init>(Unknown Source)
	at org.eclipse.swt.widgets.Display.getDefault(Unknown Source)
	at org.eclipse.swt.widgets.Shell.<init>(Unknown Source)
	at org.eclipse.swt.widgets.Shell.<init>(Unknown Source)
	at com.android.sdkuilib.internal.repository.UpdaterWindowImpl.createContents(UpdaterWindowImpl.java:122)
	at com.android.sdkuilib.internal.repository.UpdaterWindowImpl.open(UpdaterWindowImpl.java:102)
	at com.android.sdkuilib.repository.UpdaterWindow.open(UpdaterWindow.java:113)
	at com.android.sdkmanager.Main.showMainWindow(Main.java:307)
	at com.android.sdkmanager.Main.doAction(Main.java:275)
	at com.android.sdkmanager.Main.run(Main.java:98)
	at com.android.sdkmanager.Main.main(Main.java:87)

ググるVNCを使ってインストールするとかの情報は見つかりましたが、CUIだけでも可能です。help見てると下のオプションを見つけたので、こいつをつけて起動します。他にも色々あるので、コマンドにhelp付けて確認してみてください。

  -u --no-ui    Update from command-line, without any UI
./tools/android update sdk -t platform -u
*2011/01/26追記:SDK2.3以上の場合、構造が変わってるので下のコマンドで。
./tools/android update sdk -u

実行するとplatformsの下に色々ダウンロードされていきます。

$ ls platforms/
android-3  android-4  android-7  android-8

これでとりあえずの開発環境は整いました。次はプロジェクトを作成してコンパイルまでしてみます。

プロジェクト作成

詳細は省略・・・

$ ./android create project -t 4 -p /home/matatabi/test -k "com.example.test" -a HelloWorld

ビルド

$ cd /home/matatabi/test
$ ls
AndroidManifest.xml  bin  build.properties  build.xml  default.properties  gen  libs  local.properties  res  src

build.xmlまで作成してくれてるのでantでビルドするだけですが、CentOSのパッケージに罠がありました。「yum install ant」でインストールしたantを使うとこんなエラーが出ます。

BUILD FAILED
java.lang.NoSuchMethodError: org.apache.tools.ant.types.FileSet.iterator()Ljava/util/Iterator;

CentOSのantのバージョンは1.6.5でした。古い・・・ソース確認しましたが、1.6.5のantにはFileSet.iterator()が無いのでエラーになったみたいです。
多分1.7以上が必要です。最新版をダウンロードしてきましょう。
http://ant.apache.org/bindownload.cgi
最新版のantでビルドします。

$ ant debug

成功するとbinの下にapkファイルが作成されます。
以上、CUIだけでAndroidの開発環境が整いました。

CopiPeバージョンアップ

Androidアプリの「CopiPe」バージョン2.0をリリースしました。http://www.matabii.com/copipe/
今回の目玉機能は現在日時のコピー機能です。Excelの日付書式のように「yyyy/MM/dd」等と登録しておけば、現在日時をその形に合わせてクリップボードにコピーします。

あと、評判がめちゃくちゃ悪かったアイコンも変えてみました。全部自分一人でやることに拘ってるけど、この辺りは誰かに頼んでも良いかもと思ってます。

日時コピー機能を追加したので、日付付きのゴム印をイメージしてみました。

ウインドウの最大化

ずっとLinux使ってて久しぶりにMacに戻って戸惑ったのがウインドウサイズの変更でした。WindowsやLinuxだったら大抵F11のショートカットで画面が最大化するんだけど、Macだとやり辛い。
不便なのでショートカットの設定出来ないか調べてたら、割り当て方法がちょっと特殊だったので紹介します。

環境設定のキーボードからキーボードショートカットを選択。
ここから各アプリケーションにショートカットを設定出来るのですが、機能に対してキーを割り当てるのではなく、メニュー名に対して割り当てるのです。

試しに「拡大/縮小」というメニュー名にF11を割り当ててみました。すると

Terminal.appに「拡大/縮小」のショートカットは無いのですが、F11が割り当てられました。これでF11だけでウインドウの最大化と縮小が出来るようになりました。
FinderやXcodeも同じメニュー名なので、同じショートカットが使えるってのが面白いです。
Chromeには「拡大/縮小」のメニューは無いので使えません。代わりに、「全画面表示にする」と「全画面表示を終了」を割り当てておけば、F11だけで切り替えられてハッピーになります。

ちなみにMacの機能ではないけど、Carbon Emacsなら下のlispを追加しとけばF11で全画面表示の切り替えが出来ます。これは前からやってたんだけどね!

(defun mac-toggle-max-window ()
  (interactive)
  (if (frame-parameter nil 'fullscreen)
      (set-frame-parameter nil 'fullscreen nil)
    (set-frame-parameter nil 'fullscreen 'fullboth)))

(global-set-key [f11] 'mac-toggle-max-window)

そういえばExposeでF11がデスクトップ表示に割り当てられてるけど、MacBookならタッチパッドを4本指で上になぞれば良いので迷わず無効化しましょう。

シンプルなフッターレイアウトの作り方

設定画面やダイアログで、下のようなボタンが2つ並んだフッターを付ける時に使ってるレイアウトxmlを紹介します。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
<LinearLayout
    android:id="@+id/bottom"
    android:layout_width="fill_parent"
    android:layout_height="54dip"
    android:layout_alignParentBottom="true"
    android:background="@android:drawable/bottom_bar"
    >    
    <Button
      android:id="@+id/ok"
      android:layout_width="fill_parent"
      android:layout_height="wrap_content"
      android:layout_marginTop="4dip"
      android:layout_weight="1"
      android:text="OK"
    />
    <Button
      android:id="@+id/cancel"
      android:layout_width="fill_parent"
      android:layout_height="wrap_content"
      android:layout_marginTop="4dip"
      android:layout_weight="1"
      android:text="CANCEL"
    />
</LinearLayout>
<LinearLayout
    android:layout_above="@id/bottom"
    android:layout_height="fill_parent"
    android:layout_width="fill_parent"
    android:orientation="vertical"
    >
</LinearLayout>

</RelativeLayout>

CopiPeバージョン1.4

AndroidアプリのCopiPeをバージョンアップしました。変更点は以下の通りです。

Xperia等、画面サイズの大きな端末でフリーズする現象を修正(半透明なウインドウが原因だったので止めました)

Xperiaで頻繁に固まると言う情報をいただいており原因を調査したところ、どうやら半透明のウインドウが原因だったと分かりました。Xperiaの解像度は高く、描画するのにメモリを多く消費します。透明のウインドウは後ろの画面も描画するためにメモリオーバーを起こしてフリーズしてしまったようです。

Android1.5→Android1.6へ移行し、複数の画面サイズをサポート

今までAndroid1.5を用いてコンパイルしていました。Android1.6からは画面サイズが多岐に増えていて、新しいオプションを追加しないとマーケットに表示されない問題がありました。詳しくはこちらの記事が詳しいです。http://android.asai24.com/archives/51378321.html

インポート、エクスポート機能をサポート

これは自分で使っていてもかなり便利です。PCでさーっと作ったデータをメールで送信してAndroidに取り込んだり出来ます。

フォントサイズの変更機能を追加

ヘルプの追加

Webから見れるマニュアルを作成しました。http://www.matabii.com/copipe/index.html

CopiPeその後

去年に制作したAndroidアプリの「CopiPe」が窓の杜で紹介されました。
http://www.forest.impress.co.jp/docs/special/20100126_344804.html
使ってくれる人も1万人に近づいていて要望メールなども頂いているので、smart.fmのアプリと合わせてバージョンアップを積極的にしていきたいなと。