LoginSignup
8
10

More than 5 years have passed since last update.

キーイベントを発行する話

Posted at

いろいろやっていると、ハードキーを使わずに
任意のタイミングでキーイベントを発行したくなることがあると思います。

手段はいくつかありますが、状況によって可否が変わります。
セキュリティ的な観点も含めて、
できること、できないことをメモしていこうと思います。

目次

1.adbコマンドから発行する
1-1.inputコマンド
1-2.sendeventコマンド
2.プログラムコードから発行する
2-1.大前提(セキュリティ的な話)
2-2.dispatchKeyEvent
2-3.inputコマンドを使って発生させる
3.おわりに

参考

キーコード:ソース(KeyEvent.java)AndroidDeveloper
スキャンコード:ソース(input.h)

1.adbコマンドから発行する

USB経由でイベントを発生させる場合がこれにあたります。
ある程度スクリプトを組めば、放置テストする際に便利ですね。

1-1.inputコマンド

$ adb shell input keyevent [key code]

キーコードは10進数でもいいですし、KEYCODE_VOLUME_UPなどの定数名でもOKです。
定義名やキーコードは参考からどうぞ。

なお、蛇足ですがinputコマンドはタッチイベントやマウスなど、
様々なイベントを発生させることが可能です。

1-2.sendeventコマンド

これはデバイスに入力される情報を擬似的に発生させるので、ちょっと面倒です。
まず、実際にデバイスに入力されるイベントを見てみましょう。

$ adb shell getevent
add device 1: /dev/input/event5
name: "msm8974-taiko-mtp-snd-card Headset Jack"
add device 2: /dev/input/event4
name: "msm8974-taiko-mtp-snd-card Button Jack"
add device 3: /dev/input/event3
name: "hs_detect"
add device 4: /dev/input/event1
name: "touch_dev"
add device 5: /dev/input/event0
name: "qpnp_pon"
add device 6: /dev/input/event2
name: "gpio-keys"
/dev/input/event2: 0001 0073 00000001
/dev/input/event2: 0000 0000 00000000
/dev/input/event2: 0001 0073 00000000
/dev/input/event2: 0000 0000 00000000

これはgetevent後に音量下キーを押して離したときのログです。
/dev/input/event2 というデバイス(gpio-keys)に対して、
音量下キーを押した、離した、というイベントが送られているログです。

音量下が「押された」
/dev/input/event2: 0001 0073 00000001
/dev/input/event2: 0000 0000 00000000
音量下が「離された」
/dev/input/event2: 0001 0073 00000000
/dev/input/event2: 0000 0000 00000000

詳しくは、ここでは解説しません。

この「押された」「離された」のイベントを偽装するのがsendeventになります。

$ adb shell sendevent [device] [cmd] [scancode] [value]

[device] : ここでいうと /dev/input/event2 になります
[cmd]、[scancode]、[value]はログに表示されている3つの数字を 16進数 にしたものです。
キーコードは10進数でもいいですし、KEYCODE_VOLUME_UPなどの定数名でもOKです。

scancodeはキーコードとはまた違ったもので、
参考のスキャンコードを参照して何を入れればよいか選んでください。

あとはログにあるように、4回sendeventを実行すればOKです。
inputコマンドで十分ですね。w

2.プログラムコードから発行する

これはアプリ側からキーコードを発行する場合がこれにあたります。

2-1.大前提(セキュリティ的な話)

私はこれでやろうとしたことを諦めたのですが…
基本的に、自分のアプリが全面に出てる場合しか使えません。

例えば、サービス上で使ってみたり、
ステータスバーを下に引っ張った状態だったり、
パネルセーブした状態だと利用できません。

おそらく、勝手にバックグラウンドで動かれると
セキュリティ的に問題があるからでしょう。(そりゃそうだ)

2-2.dispatchKeyEvent

例えば、音量下イベントを発生させる場合はこうなります。

dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_VOLUME_UP));
dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_VOLUME_UP));

2-3.コマンドを発行して発生させる

例えば、inputコマンドを発行する場合はこうなります。

Runtime.getRuntime().exec("input keyevent " + keyCode);

3.おわりに

イヤホンジャックを挿したら音楽が再生される。。。
ようなアプリを作ろうと思って調べていたんですが、
セキュリティ的な話でダメでした。

rootをとってinjectKeyEventなどを使えば使えるのかもしれませんが、
市場への公開を目標にする人にとっては意味がありません。

8
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
10