2011年06月21日
Androidでkeyイベントを発生させるinputコマンドをサクサクにする
inputコマンドの使い方
コンソールかadbのshellから単にinputと打ってみます。
# input usage: input [text|keyevent] input text <string> input keyevent <event_code>
このinputコマンドを使うと任意のキーイベントをコマンドラインから発行することができます。
実際のキーイベントのコードはandroid.view.KeyEvent.javaに定義されています。
便利そうなものをピックアップすると
public static final int KEYCODE_HOME = 3; public static final int KEYCODE_BACK = 4; public static final int KEYCODE_DPAD_UP = 19; public static final int KEYCODE_DPAD_DOWN = 20; public static final int KEYCODE_DPAD_LEFT = 21; public static final int KEYCODE_DPAD_RIGHT = 22; public static final int KEYCODE_DPAD_CENTER = 23; public static final int KEYCODE_ENTER = 66; public static final int KEYCODE_MENU = 82; public static final int KEYCODE_SEARCH = 84;
メニューキーのイベントを発行したいときには
# input keyevent 82
起動後のロック画面はこれで解除することができます。
検索窓を開いて"kmckk"を検索するには
# input keyevent 84 # input text kmckk # input keyevent 66
inputコマンドを改良してサクサクにする
実際に試してみるとわかりますが、このinputコマンドはけっこう重いです。
/system/bin/input は以下のようなshell scriptでした。
# Script to start "input" on the device, which has a very rudimentary # shell. # base=/system export CLASSPATH=$base/framework/input.jar exec app_process $base/bin com.android.commands.input.Input $*
app_process はDalvikVMそのものです。つまり毎回DalvikVMを新たに起動していました。そのためにこのコマンドは起動に時間がかかるのです。
これを以前紹介したdvzコマンドを使って書き直してみます。以下のようになりました。
input2
# base=/system exec dvz -classpath $base/framework/input.jar com.android.commands.input.Input $*
これはDalvikVMを新たに起動するのでなく、待機中のZygoteに依頼して、そこからforkした子プロセスで指定したクラスを実行します。
修正したinput2コマンドを使ってさきほどと全く同じことができます。
# input2 keyevent 84 # input2 text kmckk # input2 keyevent 66
今度はさっきよりもずっと軽快です。
自作のコマンドを作る
com.android.commands.input.Inputのソースを見てみましょう。
frameworks/base/cmds/input/src/com/android/commands/input/Input.java
特に参考になるのは以下の箇所です。
/** * Send a single key event. * * @param event is a string representing the keycode of the key event you * want to execute. */ private void sendKeyEvent(String event) { int eventCode = Integer.parseInt(event); long now = SystemClock.uptimeMillis(); Log.i("SendKeyEvent", event); try { KeyEvent down = new KeyEvent(now, now, KeyEvent.ACTION_DOWN, eventCode, 0); KeyEvent up = new KeyEvent(now, now, KeyEvent.ACTION_UP, eventCode, 0); (IWindowManager.Stub .asInterface(ServiceManager.getService("window"))) .injectKeyEvent(down, true); (IWindowManager.Stub .asInterface(ServiceManager.getService("window"))) .injectKeyEvent(up, true); } catch (RemoteException e) { Log.i("Input", "DeadOjbectException"); } }
つまり、"window"サービスのinjectKeyEventをリモートで呼び出せば、キーイベントを発行できることがわかります。これを利用すれば、自動でキーイベントを発行するロボットプログラムが作れますね。(必要なPermissionについては別途調査してください。)
トラックバックURL
コメント一覧
この記事をみてinputコマンド書き換え、dvzコマンドを追加して実行してみると、
u0_a290@SC-04F:/ $ dvz
/system/bin/dvz[1]: /acct: can't execute: Is a directory
/system/bin/dvz[2]: syntax error: '(' unexpected
となり実行できません。
試した環境はNexus7 2013でCM11を焼いて使用しています。
dvzはGBの端末から抜き出しました。
この場合の解決方法はあるのでしょうか?
アドバイスいただけると幸いです。
この記事は3年以上前の記事ですので、現在とは状況が異なることが多々あると思います。当時この記事を書いた担当者は、現在は弊社に在籍しておりませんので、質問への回答等は難しい状況になっております。お役に立てず、申し訳ありません。