PCのキーボードで端末を操作する
Androidアプリの開発をする場合、PCに接続したAndroid端末にビルドしたアプリを転送して動作を確認することが少なくない。
アプリを開発してみるとわかると思うが、微調整段階になるとその転送して確認することが頻繁になり、PCのキーボードから手を離すのが面倒になってくる。
そこでPCからAndroid端末を操作できるアプリはないものかと探したところ、「Wifi Keyboard」というのが見つかり、世の中にはあるものだと関心してしまった。
早速使ってみたところ、Bluetoothキーボードと同様に何事もなくAndroid端末が操作できる。
Wifiだけではなく、ADK付属のadbコマンドを使えば、USB接続でも利用できる。
おまけに、PCの日本語入力がそのまま利用できる。
ただし、Terminal IDEではCtrlキーが効かないので、相性が悪いアプリが存在するようだ。
ある人の記事では笑いがしばらく止まらないと評価していたが、その通りだと思うので、是非試してみて欲しい。
iOS8は重いから、色々と調整!
iOS8になったら、iPod Touch 5のレスポンスが悪くなった。
特に入力の開始直後は文字を打っても、画面に出るまで数秒かかることが頻繁に発生するようになった。
iOSはメジャーバージョンアップする度に必ず遅くなる。
最新のデバイスでしか動作検証していないものと想像している。
iPod touchユーザには勘弁して欲しい点だ。
文句を言っても始まらないので、設定で軽減することにした。
- Siriをオフ
- Handoffと候補のApp以下をすべてオフ
- キーボードの音声入力、自動大文字入力、自動修正、予測、ピリオドの簡易入力をオフ
- Appのバックグラウンド更新で不要なものをオフ
- iCloudと連携しないアプリをオフ
- プライバシーの位置情報サービスを使用しないアプリ、システムサービスのSpotlightの検索候補、時間帯の設定、利用頻度の高い位置情報 、この近くで人気、診断/使用状況をオフ
- プライバシーの診断/使用状況で自動送信をオフ
- 通知の不要なアプリをオフ
- 一般のSpotlight検索をすべてオフ
これで大分軽くなった。
Terminal IDEでアプリ開発!?(その2)
前回はサンプルのビルドを行ったが、今回は世の中にアップされているオープンライブラリを使用して、簡単なアプリを開発してみようと思う。
実際に使用するのは、テスティングフレームワークで有名なJUnitである。
JARファイルをDEXファイルに変換
Android端末ではJARファイルのオープンライブラリをそのまま使用できないので、DEXファイル(Dalvik仮装マシンのバイトコード)に変換する必要がある。
メモり不足となるので、残念ながらTerminal IDE上では変換できないため、PC上で変換する。
実際の変換はdxコマンドを使用する。
今回使用したAndroid SDK 23.0.2では、dxコマンドは以下に存在する。
ZIP展開先\android-sdk\build-tools\20.0.0\dx.bat
以下のコマンドを実行し、JUnitライブラリをDEXファイルに変換する。
dx --dex --no-srtict --output=junit-4.11.dex.jar junit-4.11.jar dx --dex --no-srtict --output=hamcrest-core-1.3.dex.jar hamcrest-core-1.3.dex.jar
JARファイルとDEXファイルをAndroid端末にコピーする。
コピーしたファイルをTerminal IDEにおいて「~/work/libs/」以下に配置する。
サンプルプログラムの作成
以下のサンプルプログラムを「~/work/src/」に作成する。
- Thing.java
public class Thing { private String name; // 3 characters or over public String getName() { return this.name; } public void setName(String newName) { if (newName == null || newName.length() < 3) { throw new IllegalArgumentException("illegal name"); } this.name = newName; } }
- ThingTest.java
import org.junit.Test; import static org.junit.Assert.*; public class ThingTest { @Test public void instanciate() { Thing thing = new Thing(); assertNull(thing.getName()); } @Test public void setNameOk() { Thing thing = new Thing(); thing.setName("abc"); assertEquals(thing.getName(), "abc"); } @Test public void setNameOk2() { Thing thing = new Thing(); thing.setName("鱗田太郎"); assertEquals(thing.getName(), "鱗田太郎"); } @Test public void setNameNull() { boolean hasError = false; Thing thing = new Thing(); try { thing.setName(null); } catch (IllegalArgumentException e) { hasError = true; } assertEquals(hasError, true); } @Test public void setNameNullString() { boolean hasError = false; Thing thing = new Thing(); try { thing.setName(""); } catch (IllegalArgumentException e) { hasError = true; } assertEquals(hasError, true); } @Test public void setNameTooShort() { boolean hasError = false; Thing thing = new Thing(); try { thing.setName("12"); } catch (IllegalArgumentException e) { hasError = true; } assertEquals(hasError, true); } }
Makefileの作成
makeコマンドでビルド&実行を行うために、以下のMakefileを「~/work/src/」に作成する。
CLASSPATH=../libs/junit-4.11.jar:../libs/hamcrest-core-1.3.jar CLASSFILES=Thing.class ThingTest.class DEXFILE=Thing.dex.jar .SUFFIXES: .class .java .java.class: javac -cp $(CLASSPATH) $< all: $(DEXFILE) run $(DEXFILE): $(CLASSFILES) dx --dex --verbose --no-strict --output=$@ $(CLASSFILES) LIBFILES=../libs/junit-4.11.dex.jar:../libs/hamcrest-core-1.3.dex.jar MAIN=org.junit.runner.JUnitCore ARGS=ThingTest run: java -jar $(LIBFILES):$(DEXFILE) $(MAIN) $(ARGS)
makeコマンドで実行
makeコマンドを実行すると、必要に応じてコンパイルが行われ、ビルドされた単体テストが実行される。
$ cd ~/work/src $ make javac -cp ../libs/junit-4.11.jar:../libs/hamcrest-core-1.3.jar Thing.java javac -cp ../libs/junit-4.11.jar:../libs/hamcrest-core-1.3.jar ThingTest.java dx --dex --verbose --no-strict --output=Thing.dex.jar Thing.class ThingTest.class processing Thing.class... processing ThingTest.class... writing classes.dex; size 1972... java -jar ../libs/junit-4.11.dex.jar:../libs/hamcrest-core-1.3.dex.jar:Thing.dex.jar org.junit.runner.JUnitCore ThingTest JUnit version 4.11 ...... Time: 0.013 OK (6 tests) $
Terminal IDEでアプリ開発?!(その1)
Android端末のみでアプリ開発ができると言うTerminal IDEで、実際に何がどこまで出来るのかを試してみた。
結論から言うと、C、C++、Javaのコンソールアプリと、JavaのAndroidアプリが開発できるようだ。
また、bashやawkなどがあるので、ある程度のスクリプトも書ける。
インストール
インストールは以下の3段階の手順となる。
なお、現時点のバージョンは2.02である。
オススメの設定
最低限、以下の設定をオススメする。
- 付属のソフトウェアキーボードを使用
コンソール操作ではTabキーやCtrlキーなどの特殊キーを何かと使用するが、多くのAndroid用ソフトウェアキーボードではそれらの特殊キーを打つことができないので、Terminal IDEに付属のソフトウェアキーボードに変更する。 - フォントサイズの変更
デフォルトの12ポイントでは少し小さいので14ポイント程度にオプションで変更する。 - プロンプトの簡略化
画面が狭いため、「~/.bashrc」で定義されているプロンプトの環境変数を変更する。
PS1='\w\$ ' - vim使用時はBACKキーをESCキーに変更
ハードウェアキーボードのESCキーは戻るボタンに割り当てられているが、vimではコマンドモードに移行するため、ESCキーとして動作するようにメニューで変更する。
サンプルのビルド
「~/system/src/」以下にサンプルが保存されているので、これらをビルドしてみる。
なお、README.txtを読めば、概ねのことが分かる。
- 「c_examples/」以下は次の通りである。
- 「chello/」以下では「make」を実行すると、「hello」がビルドできる。
- 「cpphello/」以下では「make」を実行すると、「rect」がビルドできる。
- 「clib/」以下では「make all install」を実行すると、「capp/」以下で利用するライブラリがビルドできる。
- 「capp/」以下では「make」を実行すると、「tester」がビルドできる。
- 「helloworld/」以下では「./builder.sh」を実行すると、「hello.jar」がビルドできるので、これを「./run.sh」で実行できる。
- 「demo_lib/」以下では「./builder.sh」を実行すると、「dist/」に「demolib.jar」や「demolib.dex.jar」がビルドできる。
これらは既に「demo_console/libs/」や「demo_android/libs/」に保存されている。 - 「demo_console/」以下では「./builder.sh」を実行すると、「dist/」に「demo_console.dex.jar」がビルドできるので、これを「./run.sh」で実行できる。
- 「demo_android/」以下では「./builder.sh」を実行すると、「dist/」に「demo_android.apk」や「demo_android_signed.apk」がビルドできる。ただし、「./run.sh」や「./install.sh」の実行にはSuperSUの「su」コマンドを使用するなどで、root権限を取得する必要がある。
Bluetooth接続の英語キーボードを刻印通りに打つ
以前、写真のASUS MeMO Pad HD 7 (ME173X)対応のジャケット付きBluetoothキーボードを購入したのだが、キートップの刻印通りに打てないキーが存在する。
この問題を解決した時の経緯を以下に記載する。
なお、以下に記載のコマンドはAndroid上のTerminal IDEのコンソールで実行した。
コマンドの実行に必要なroot権限はSuperSUの「su」コマンドで取得した。
デバイス情報の取得
デバイス情報は「dumpsys input」コマンドで得られる。
INPUT MANAGER (dumpsys input) Event Hub State: BuiltInKeyboardId: -2 Devices: 7: hid-keyboard Classes: 0x0000014b Path: /dev/input/event5 Descriptor: e6829a71d080dbf7cc1317c4cc5515a23611afd2 Location: UniqueId: Identifier: bus=0x0019, vendor=0x0000, product=0x0000, version=0x0000 KeyLayoutFile: /system/usr/keylayout/hid-keyboard.kl KeyCharacterMapFile: /system/usr/keychars/Generic-ja_JP.kcm ConfigurationFile: /system/usr/idc/hid-keyboard.idc HaveKeyboardLayoutOverlay: true
キーコードの取得
上記「デバイス情報」の「Path」から、不正な文字が表示されるキーのキーコードを「getevent /dev/input/event5」コマンドで取得した。
刻印 | 表示 | キーコード(10進数) |
---|---|---|
[ | @ | 26 |
] | [ | 27 |
\ | ] | 43 |
| | } | 42 43 |
{ | @ | 42 26 |
} | { | 42 27 |
~ | なし | 42 41 |
` | 半角/全角 | 41 |
※上記の「42」は左シフトキー
キーと文字の割り当て
上記「デバイス情報」の「Generic-ja_JP.kcm」を見ると、以下の記述があるため、今回の現象が発生していることが分かる。
map key 26 AT map key 27 LEFT_BRACKET map key 41 ZENKAKU_HANKAKU map key 43 RIGHT_BRACKET
IDCファイルの変更
上記「デバイス情報」の「hid-keyboard.idc」を以下のように変更した。
【変更前】 keyboard.layout = hid-keyboard keyboard.characterMap = Generic-ja_JP 【変更後】 keyboard.layout = hid-keyboard keyboard.characterMap = Generic
実際の変更は以下の手順で行う。
クラスのフィールドやメソッドを表示する
Apache Commons Langのorg.apache.commons.lang3.builderパッケージには、必要に応じてオーバーライドする以下のObjectクラスのメソッドを実装するためのヘルパークラスが存在する。
メソッド | ヘルパークラス | 説明 |
---|---|---|
public boolean equals(Object o) | EqualsBuilder | 等価確認 |
public String toString() | ToStringBuilder | 文字列変換 |
public int hashCode() | HashCodeBuilder | ハッシュ値変換 |
public int compareTo(Object o) | CompareToBuilder | 大小比較 |
上記のToStringBuilderを使用した一般的なtoStringメソッドの実装方法は以下となる。
import org.apache.commons.lang3.builder.*; public class MyClass { private String str1 = "hello world"; private int num1 = 123; private double val1 = 456.789; @Override public String toString() { return ToStringBuilder.reflectionToString(this); } public static void main(String[] args) { MyClass myInst = new MyClass(); System.out.println(myInst.toString()); } }
上記の実行結果から以下の出力が得られる。
MyClass@7ea987ac[str1=hello world,num1=123,val1=456.789]
上記の出力結果を見て、ToStringBuilder.reflectionToStringメソッドはどのようにしてフィールド名を列挙し、その値を得ているのだろうかと不思議に思ったので、調べて見ることにした。
Classクラスの役割
Object.getClassメソッドを使用すると、Classクラスのインスタンスを得ることができる。
Classクラスはクラスをモデル化するクラスであるが、このClassクラスのメソッドを使用して、インスタンス化されたクラスのフィールドやメソッドを列挙することができる。
【オブジェクトのフィールド名と値の表示】
public void printFields(Object o) { for (Field f : o.getClass().getDeclaredFields()) { System.out.println(f.getType().toString() + " " + f.getName() + " = " + f.get(o).toString() + ";"); } }
【オブジェクトのメソッド名とパラメータの列挙】
public void printMethods(Object o) { for (Method m : o.getClass().getDeclaredMethods()) { System.out.print(m.getReturnType().getName() + " " + m.getName() + "("); String comma = ""; for (Class<?> c : m.getParameterTypes()) { String name = c.getName(); if (name.charAt(0) == '[') { switch (name.charAt(1)) { case 'B' : name = "byte"; break; case 'S' : name = "short"; break; case 'I' : name = "int"; break; case 'J' : name = "long"; break; case 'C' : name = "char"; break; case 'F' : name = "float"; break; case 'D' : name = "double"; break; case 'L' : name = name.substring(2, name.length() - 1); break; default : name = name.substring(1); break; } name += "[]"; } System.out.print(comma + name); comma = ", "; } System.out.print(");\n"); } }
終わりに
ObjectクラスやClassクラスは重要な基本クラスなので、これらについて学ぶことはJavaを深く知るために必要なことだと思った。
JDK付属のDerbyを試して見る
「スッキリわかるJava入門 実践編」の第9章「データベースアクセス」には、Apache DerbyはJava 6から標準添付されていると記載されていたので、実際に試して見た。
PATH環境変数の設定
現在、PCにインストールされているのはJava 8で、以下のフォルダにインストールされている。
JDKのインストールフォルダを確認すると、以下のフォルダが存在するのが分かる。
- Derbyフォルダ
- C:\Program Files\Java\jdk1.8.0_05\db
先ずはコマンドプロンプトでDerbyのコマンドを実行しやすいように、PATH環境変数に以下のパスを追加する。
- Derbyコマンドフォルダ
- C:\Program Files\Java\jdk1.8.0_05\db\bin
初期設定の確認
コマンドプロンプトを開いて、以下のコマンドを実行する。
なお、カレントディレクトリは「C:\work」としたので、予め同フォルダが存在しているものとする。
C:\work> sysinfo ------------------ Java情報 ------------------ Javaバージョン: 1.8.0_20 Javaベンダー: Oracle Corporation Javaホーム: C:\Program Files\Java\jre1.8.0_20 Javaクラスパス: C:\Program Files\Java\jdk1.8.0_05\db\bin\../lib/derby.jar;C:\Program Files\Java\jdk1.8.0_05\db\bin\../lib/derbynet.jar;C:\Program Files\Java\jdk1.8.0_05\db\bin\../lib/derbyclient.jar;C:\Program Files\Java\jdk1.8.0_05\db\bin\../lib/derbytools.jar OS名: Windows 7 OSアーキテクチャ: amd64 OSバージョン: 6.1 Javaユーザー名: pochi Javaユーザー・ホーム: C:\Users\pochi Javaユーザー・ディレクトリ: C:\work java.specification.name: Java Platform API Specification java.specification.version: 1.8 java.runtime.version: 1.8.0_20-b26 --------- Derby情報 -------- [C:\Program Files\Java\jdk1.8.0_05\db\lib\derby.jar] 10.10.1.3 - (1557168) [C:\Program Files\Java\jdk1.8.0_05\db\lib\derbytools.jar] 10.10.1.3 - (1557168) [C:\Program Files\Java\jdk1.8.0_05\db\lib\derbynet.jar] 10.10.1.3 - (1557168) [C:\Program Files\Java\jdk1.8.0_05\db\lib\derbyclient.jar] 10.10.1.3 - (1557168) ------------------------------------------------------ ----------------- ロケール情報 ---------------- 現行ロケール: [日本語/日本 [ja_JP]] ロケールのサポートが見つかりました: [cs] バージョン: 10.10.1.3 - (1557168) ロケールのサポートが見つかりました: [de_DE] バージョン: 10.10.1.3 - (1557168) ロケールのサポートが見つかりました: [es] バージョン: 10.10.1.3 - (1557168) ロケールのサポートが見つかりました: [fr] バージョン: 10.10.1.3 - (1557168) ロケールのサポートが見つかりました: [hu] バージョン: 10.10.1.3 - (1557168) ロケールのサポートが見つかりました: [it] バージョン: 10.10.1.3 - (1557168) ロケールのサポートが見つかりました: [ja_JP] バージョン: 10.10.1.3 - (1557168) ロケールのサポートが見つかりました: [ko_KR] バージョン: 10.10.1.3 - (1557168) ロケールのサポートが見つかりました: [pl] バージョン: 10.10.1.3 - (1557168) ロケールのサポートが見つかりました: [pt_BR] バージョン: 10.10.1.3 - (1557168) ロケールのサポートが見つかりました: [ru] バージョン: 10.10.1.3 - (1557168) ロケールのサポートが見つかりました: [zh_CN] バージョン: 10.10.1.3 - (1557168) ロケールのサポートが見つかりました: [zh_TW] バージョン: 10.10.1.3 - (1557168) ------------------------------------------------------
チュートリアル
以下のサイトに記載の手順にしたがってチュートリアルを実行して見る。
[Create a database]
C:\work>ij ijバージョン10.10 ij> connect 'jdbc:derby:MyDbTest;create=true'; ij> exit; C:\work>type derby.log ---------------------------------------------------------------- Mon Sep 15 12:52:01 JST 2014: DerbyバージョンThe Apache Software Foundation - Apache Derby - 10.10.1.3 - (1557168): インスタンスa816c00e-0148-7770-4ce1-000006e860f8を file:/C:/Program%20Files/Java/jdk1.8.0_05/db/lib/derby.jarからロードされたクラス・ローダーsun.misc.Launcher$AppClassLoader@66d3c617により データベース・ディレクトリC:\work\MyDbTest上でブートしています java.vendor=Oracle Corporation java.runtime.version=1.8.0_20-b26 user.dir=C:\work os.name=Windows 7 os.arch=amd64 os.version=6.1 derby.system.home=null データベース・クラス・ローダーが開始されました - derby.database.classpath='' ---------------------------------------------------------------- Mon Sep 15 12:52:08 JST 2014: Derbyエンジンを停止しています ---------------------------------------------------------------- Mon Sep 15 12:52:08 JST 2014: クラス・ローダーsun.misc.Launcher$AppClassLoader@66d3c617を持つデータベース・ディレクトリC:\work\MyDbTestのインスタンスa816c00e-0148-7770-4ce1-000006e860f8を停止しています ----------------------------------------------------------------
上記の通り、「C:\work\MyDbTest」にデータベースフォルダが作成され、その下に各種データベースファイルが保存されていることが確認できる。
[Connect to a database]
C:\work>ij ijバージョン10.10 ij> connect 'jdbc:derby:MyDbTest';
[Execute SQL statements]
ij> create table derbyDB(num int, addr varchar(40)); 0行が挿入/更新/削除されました ij> insert into derbyDB values (1956,'Webster St.'); 1行が挿入/更新/削除されました ij> insert into derbyDB values (1910,'Union St.'); 1行が挿入/更新/削除されました ij> update derbyDB set num=180, addr='Grand Ave.' where num=1956; 1行が挿入/更新/削除されました ij> select * from derbyDb; NUM |ADDR ---------------------------------------------------- 180 |Grand Ave. 1910 |Union St. 2行が選択されました
[Disconnect from a database]
ij> disconnect;
[Exit]
ij> exit; C:\work>
[Run SQL Scripts]
予め、以下のSQLファイルを作成する。
- ファイル名
- my_file.sql
connect 'jdbc:derby:MyDbTest'; create table OpenDB(name varchar(20),url varchar(50)); insert into OpenDB values ('MySQL', 'http://www.mysql.com'); insert into OpenDB values ('PostgreSQL', 'http://www.postgresql.org'); insert into OpenDB values ('sqlite', 'http://www.sqlite.org'); insert into OpenDB values ('Apache Derby', 'http://db.apache.org/derby'); select * from OpenDB; disconnect;
以下のrunコマンドを実行すると、
C:\work>ij ijバージョン10.10 ij> run 'my_file.sql';
想定通り、手入力と同様にSQLコマンドが実行される。
ij> connect 'jdbc:derby:MyDbTest'; ij> create table OpenDB(name varchar(20),url varchar(50)); 0行が挿入/更新/削除されました ij> insert into OpenDB values ('MySQL', 'http://www.mysql.com'); 1行が挿入/更新/削除されました ij> insert into OpenDB values ('PostgreSQL', 'http://www.postgresql.org'); 1行が挿入/更新/削除されました ij> insert into OpenDB values ('sqlite', 'http://www.sqlite.org'); 1行が挿入/更新/削除されました ij> insert into OpenDB values ('Apache Derby', 'http://db.apache.org/derby'); 1行が挿入/更新/削除されました ij> select * from OpenDB; NAME |URL ----------------------------------------------------------------------- MySQL |http://www.mysql.com PostgreSQL |http://www.postgresql.org sqlite |http://www.sqlite.org Apache Derby |http://db.apache.org/derby 4行が選択されました ij> disconnect;