injecting-input-and-state について
Android のテスト担当者向けに、ADB Shell で端末を操作するスキルです。入力のシミュレーション、画面やシステム設定、アプリ状態のリセット、Activity 起動を扱い、`cmd` と従来の方法の違いも説明します。
主な機能
- 01input によるジェスチャー、文字、キーの入力
- 02wm による画面サイズと密度の変更
- 03settings によるテスト状態の設定
- 04force-stop とアプリデータ消去の区別
- 05am と cmd による起動やサービス制御
活用シーン
- 01CI で端末操作をスクリプト化
- 02画面サイズ、密度、システム設定の違いをテスト
- 03テスト実行間のアプリ状態リセット
- 04Intent extras 付きのディープリンク起動
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ skydoves/ android-testing-skills --skill injecting-input-and-stateインストール後、Claude Code で/injecting-input-and-stateを入力して読み込まれたか確認します。
詳細
入力と状態の注入 — シェルからデバイスを操作する
このスキルでは、テスト/QA エンジニアが adb 経由で操作するオンデバイスのシェル機能を扱います。ユーザー操作のシミュレーション、画面構成の上書き、システム設定の切り替え、アプリ状態のリセット、Activity の起動ができます。トランスポート(adb devices、USB/TCP)については ../../architecture/understanding-adb-architecture/SKILL.md を、デバイス操作後の成果物のキャプチャについては ../../capture/capturing-screenshots-and-screenrecord/SKILL.md を参照してください。
このスキルを使う場面
- 開発者が、インストルメンテーションを書かずに、CI からユーザージャーニー(タップ、スワイプ、テキスト入力、ハードウェアキーの押下)をスクリプト化する必要がある場合。
- バグの再現に特定の画面サイズや密度(
wm size 411x731、wm density 320)が必要で、エミュレーター AVD を再作成したくない場合。 - アニメーションが有効なためにテストスイートが不安定になり、開発者が標準的な独立実行用の事前設定(
window_animation_scale = 0など)を求めている場合。 - 開発者が実行間にアプリデータを消去する必要があるものの、
am force-stopで十分かどうか分からない場合(十分ではありません)。 - スクリプトで
adb shell svc wifi disableを実行しても API 30 以降では何も起きず、最新のcmd wifi set-wifi-enabled disabledで解決する場合。 - 開発者が型付きの追加情報(
--ez、--ei、--es)を指定してディープリンク Activity を起動する必要がある場合。
このスキルを使わない場面
- バイト列をデバイスの外に取り出す必要がある場合(スクリーンショット、ログ、DB)。
../../capture/capturing-screenshots-and-screenrecord/SKILL.md、../../observability/extracting-logs-with-logcat/SKILL.md、../../transfer/extracting-test-artifacts/SKILL.mdを参照してください。 - ホストからではなく、インストルメンテーションテスト内からデバイスを操作する場合。
../../../instrumentation/scenarios/launching-activities-with-activityscenario/SKILL.mdまたは UiAutomator を使ってください。 - APK をインストールまたはアンインストールする場合。
../../apps/installing-and-managing-apps/SKILL.mdを参照してください。 - まずデバイスに接続する場合。
../../devices/connecting-to-devices/SKILL.mdまたは../../devices/connecting-over-wifi/SKILL.mdを参照してください。
前提条件
- 到達可能なデバイスまたはエミュレーター(
adb get-stateがdeviceを返すこと)。 - ホストに Platform Tools 23 以降がインストールされていること。Platform Tools 23 以降では、
adb shellを介したクォートは(ssh 形式の)二重シェルになるため、スペースを含む文字列では重要です(developer.android.com/tools/adb#shellcommands)。 cmdラッパー API と信頼性の高いシェル終了コードを使うには、デバイスが API 24 以降であること(cmdは API 24 で導入)。
input — 合成ユーザーイベント
input は、デバイス上で InputManager.injectInputEvent() を呼び出すラッパーです。完全な文法は次のとおりです。
input [<source>] <command> [<arg>...]
<source> はコマンドごとに既定値が異なります(tap/swipe はタッチスクリーン、text/keyevent はキーボード)。
タップ、スワイプ、ドラッグアンドドロップ
adb shell input tap <x> <y>
adb shell input swipe <x1> <y1> <x2> <y2> [<duration_ms>]
adb shell input draganddrop <x1> <y1> <x2> <y2> [<duration_ms>]
adb shell input roll <dx> <dy> # rotary/trackball axes
adb shell input motionevent <DOWN|UP|MOVE|CANCEL> <x> <y>
<duration_ms> を省略した場合、swipe の既定値は約 300 ms です。長押しを合成するには、長押しタイムアウトの間、同じ位置でスワイプします。例:input swipe <x> <y> <x> <y> 1000。draganddrop は swipe と異なり、View.OnDragListener が受け取れるドラッグアンドドロップのジェスチャーシーケンス(DOWN → MOVE → UP)を発生させます。swipe と同じイベントストリームではありません。
テキスト入力 — クォートの落とし穴
adb shell input text "<string>"
注意点(developer.android.com/tools/adb より):
- スペースは必ず
%sとしてエンコードする必要があります。input text "hello world"を実行すると、helloと入力された後、何も入力されません。 - シェルのメタ文字(
'、"、&、(、)、<、>、|、;、\、バッククォート)は、ローカルシェルとデバイス側シェルのそれぞれで、一度ずつ、合計二度エスケープする必要があります。 - 非 ASCII 文字/Unicode は
input textでは正常に動作しないことがあります。その場合は UiAutomator のUiObject2.setText(...)を使ってください。
キーイベント
adb shell input keyevent [--longpress|--doubletap] <KEYCODE> [<KEYCODE>...]
adb shell input keyevent <NUMERIC_CODE>
テストに関連する KEYCODE_*(frameworks/base の KeyEvent 定数。全一覧は調査ノート A2 を参照してください):
| ニーモニック | 数値 | 備考 |
|---|---|---|
KEYCODE_HOME | 3 | ホームボタンを押します(画面が常に点灯するとは限りません)。 |
KEYCODE_BACK | 4 | 戻るボタンです。 |
KEYCODE_DPAD_UP/DOWN/LEFT/RIGHT/CENTER | 19-23 | テレビ/フォーカス移動用です。 |
KEYCODE_VOLUME_UP/DOWN/MUTE | 24/25/164 | |
KEYCODE_POWER | 26 | 画面のオン/オフを切り替えます。 |
KEYCODE_TAB | 61 | |
KEYCODE_ENTER | 66 | |
KEYCODE_DEL | 67 | バックスペースです。 |
KEYCODE_MENU | 82 | |
KEYCODE_APP_SWITCH | 187 | 最近使ったアプリボタンです。 |
KEYCODE_WAKEUP | 224 | ロックを解除せずに画面を点灯します。 |
KEYCODE_SLEEP | 223 | 強制的にスリープ状態にします。 |
ロックのないエミュレーターで画面を点灯し、キーロックを解除します:
adb shell input keyevent KEYCODE_WAKEUP
adb shell input keyevent 82 # menu, dismiss the AOSP swipe-up
ソースプレフィックス
input <source> <command> は InputDevice.SOURCE_* に対応します。画面に複数の入力リスナーがある場合や、タッチ以外のハードウェアを対象とする場合は、ソースプレフィックスを指定します:
| ソース | 主な用途 |
|---|---|
touchscreen | tap、swipe、draganddrop のデフォルトです。 |
touchpad | 外付けタッチパッド(Chromebook/Android タブレットのキーボード)用です。 |
dpad | テレビ/フォーカス移動用です:input dpad keyevent KEYCODE_DPAD_DOWN。 |
keyboard | text、keyevent のデフォルトです。 |
mouse | マウスボタンとスクロール用です。 |
trackball | トラックボールの回転用です。 |
gamepad / joystick | ゲームパッドのボタン/ジョイスティックの軸用です。 |
stylus | 筆圧対応タッチ(S-Pen)用です。 |
wm — ディスプレイサイズと密度のオーバーライド
wm は IWindowManager のシェルラッパーです。テストに関連するサブコマンドは次のとおりです:
adb shell wm size # read current logical size
adb shell wm size 1080x1920 # override
adb shell wm size reset # restore device default
adb shell wm density # read current dpi
adb shell wm density 320 # override
adb shell wm density reset
adb shell wm dismiss-keyguard # insecure keyguard only
adb shell wm user-rotation [free|lock [<rotation>]] # 0,1,2,3 = 0/90/180/270
使用例 — エミュレーターを再作成せずに、画面サイズ/密度の組み合わせをテストします:
# Per configuration in the matrix
adb shell wm size 411x731
adb shell wm density 240
# … run tests …
adb shell wm size reset
adb shell wm density reset
注意事項:
- 必ず
@AfterClass/スイートのティアダウンでresetを呼び出してください。呼び出さないと、実行後もデバイスが変更後の構成のままになり、後続の実行や人間のユーザーに影響します。 wm size/wm densityは構成変更を引き起こし、フォアグラウンドの Activity を再作成します。テスト中ではなく、テスト間で使用してください。am display-size/am display-densityは同等の旧式の表記です。wmの使用を推奨します。
settings — テスト状態の分離
adb shell settings [--user <id>] get <namespace> <key>
adb shell settings [--user <id>] put <namespace> <key> <value> [<tag>] [default]
adb shell settings [--user <id>] delete <namespace> <key>
adb shell settings [--user <id>] reset <namespace> [<package>] [untrusted_defaults|untrusted_clear|trusted_defaults]
adb shell settings [--user <id>] list <namespace>
<namespace> は global、system、secure のいずれかです。
分離されたテストの前処理 — アニメーション設定
計測テストとスクリーンショットテストを安定させるため、3 つすべてを 0 に設定します:
adb shell settings put global window_animation_scale 0
adb shell settings put global transition_animation_scale 0
adb shell settings put global animator_duration_scale 0
または、Gradle で testOptions.animationsDisabled = true を指定します。
その他のテスト関連キー
| 名前空間 | キー | 目的 |
|---|---|---|
system | font_scale | 浮動小数点数(例:1.0、1.3)。文字サイズのテストに使用します。 |
secure | accessibility_enabled | ユーザー補助機能を有効にするには 1 を指定します。enabled_accessibility_services と組み合わせてください。 |
secure | enabled_accessibility_services | ユーザー補助機能のテスト用に pkg/.Service を CSV 形式で指定します。 |
secure | default_input_method | 既知の IME を強制的に使用します。 |
secure | show_ime_with_hard_keyboard | エミュレーターで IME を表示したままにするには 1 を指定します。 |
secure | long_press_timeout | 長押しテストを安定させます。 |
global | airplane_mode_on | am broadcast android.intent.action.AIRPLANE_MODE と組み合わせてください。 |
global | policy_control | 例:immersive.full=* を指定するとシステムバーを非表示にします。 |
アプリの状態 — am force-stop と pm clear の違い
| コマンド | プロセスを終了しますか? | データ/キャッシュ/設定を消去しますか? | ランタイム権限をリセットしますか? |
|---|---|---|---|
am force-stop <pkg> | はい | いいえ | いいえ |
pm clear <pkg> | はい(暗黙的に) | はい | はい |
cmd activity stop-app <pkg> | はい(新しい API 28 以降) | いいえ | いいえ |
テスト間で状態を分離してリセットするには、pm clear を使用します。「プロセスを終了して次回の起動をコールドスタートにする」だけなら、am force-stop で十分です。pm の全コマンドについては ../../apps/installing-and-managing-apps/SKILL.md を参照してください。
アクティビティの起動 — am start
# Most reliable for tests: explicit component.
adb shell am start -n com.example.app/.MainActivity
# Force-stop first, then launch (clean cold start).
adb shell am start -S -W -n com.example.app/.MainActivity
# Launch by action + URI (default handler for https://).
adb shell am start -a android.intent.action.VIEW -d 'https://example.com'
# Pass typed extras.
adb shell am start -n com.example.app/.MainActivity \
--es screen "settings" --ez debug true --ei count 42
# Return to launcher between tests.
adb shell am start -a android.intent.action.MAIN -c android.intent.category.HOME
Intent 指定子フラグ(developer.android.com/tools/adb#IntentSpec から抜粋):
| トークン | 効果 |
|---|---|
-a action | Intent アクション(例:android.intent.action.VIEW)。 |
-d data_uri | データ URI。 |
-t mime_type | MIME タイプ。 |
-c category | カテゴリ。 |
-n component | 明示的なコンポーネント(pkg/.Activity)。 |
-f flags | 16 進数の setFlags() 値。 |
| `--es | -e key value` |
--ez key bool | ブール値の追加データ。 |
--ei key int | 整数の追加データ。 |
--el key long | long 型の追加データ。 |
--ef key float | float 型の追加データ。 |
--eu key uri | URI の追加データ。 |
--ecn key component | ComponentName の追加データ。 |
--eia/--ela/--efa key v[,v...] | 配列の追加データ。 |
--activity-clear-top など | FLAG_ACTIVITY_* に対応します。 |
-S | 起動前に対象を強制停止します。 |
-W | 起動が完了するまで待機します。 |
cmd <service> — 最新のラッパー
cmd は、バインダーサービスの onShellCommand を呼び出す汎用ラッパーです。API 24 以降で利用できます。サービスを一覧表示するには、adb shell cmd -l(または dumpsys -l)を実行します。テストで関連するエントリーポイントは次のとおりです。
| 呼び出し | 効果 |
|---|---|
cmd activity stop-app <pkg> | am force-stop に相当する最新のコマンドです。 |
cmd activity broadcast … | am broadcast と同じです。 |
cmd package install -r -t -g <path> | pm install に相当します。 |
cmd package compile -m speed -f <pkg> | AOT コンパイルを強制します。 |
| `cmd appops set allow | deny |
cmd jobscheduler run -f <pkg> <jobId> | JobService をただちに実行するよう強制します。 |
| `cmd uimode night yes | no |
cmd locale set-app-locales <pkg> --locales en-US | アプリごとのロケールを設定します(Android 13 以降)。 |
cmd statusbar expand-notifications / collapse | 通知シェードを展開/折りたたみます。 |
| `cmd wifi set-wifi-enabled enabled | disabled` |
| `cmd connectivity airplane-mode enable | disable` |
cmd testharness enable | デバイスを隔離されたテストハーネス状態にリセットします(Android 10 以降)。 |
API 30 以降での svc の非推奨化
svc data、svc wifi、svc bluetooth は、特権シェルから実行しない限り、API 30 以降では何もしません(corpus §I.10)。推奨される代替手段は、上記の cmd ラッパーです。
パターン
パターン:誤り — API 30 以降での svc wifi disable
# WRONG
adb shell svc wifi disable
# WRONG because: silently no-ops on API 30+ since the svc CLI was demoted from a privileged
# helper to an ordinary shell command. Exit code 0, Wi-Fi still on. The script proceeds
# under a wrong assumption — exactly the worst kind of failure mode.
# RIGHT
adb shell cmd wifi set-wifi-enabled disabled
adb shell cmd wifi status # verify
パターン:誤り — テスト間のリセットに am force-stop を使う
# WRONG
adb shell am force-stop com.example.app
./run-next-test.sh
# WRONG because: am force-stop kills the process but leaves shared prefs, databases, the
# image cache, and granted runtime permissions intact. The "next test" inherits state
# from the previous run.
# RIGHT
adb shell pm clear com.example.app
adb shell pm clear com.example.app.test # also reset test process state
./run-next-test.sh
(Gradle 内では、clearPackageData: 'true' を指定した Test Orchestrator が同等の処理です。../../tests/running-instrumented-tests-via-adb/SKILL.md を参照してください。)
パターン:誤り — input text "hello world"
# WRONG
adb shell input text "hello world"
# WRONG because: spaces in `input text` MUST be encoded as %s. The above types only "hello".
# RIGHT
adb shell input text 'hello%sworld'
パターン:隔離されたテスト用の前処理 + Activity の起動
adb shell settings put global window_animation_scale 0
adb shell settings put global transition_animation_scale 0
adb shell settings put global animator_duration_scale 0
adb shell pm clear com.example.app
adb shell am start -S -W -n com.example.app/.MainActivity
-S は最初に強制停止します。-W は起動が完了するまで処理をブロックします。
パターン:D-pad によるテレビ/フォーカス操作
adb shell input dpad keyevent KEYCODE_DPAD_DOWN
adb shell input dpad keyevent KEYCODE_DPAD_DOWN
adb shell input dpad keyevent KEYCODE_DPAD_CENTER
dpad をソースとして指定することで、イベントがタッチスクリーンの処理経路ではなく、テレビ向けのフォーカスハンドラーに送られます。
必須ルール
- API 30 以降では、必ず
cmd wifi set-wifi-enabled/cmd connectivity airplane-mode/cmd bluetooth_manager enableを使用してください。svc wifi/svc bluetooth/svc dataに依存してはいけません。これらは最新リリースでは何もせず、エラーも出ません。 - テスト間で完全に隔離された状態にリセットする場合は、必ず
pm clear <pkg>を使用してください(am force-stopではありません)。force-stopはプロセスを終了するだけで、データには触れません。 input textの空白は必ず%sとしてエンコードしてください。シェルのメタ文字を含む文字列は、(ssh 形式で)必ず二重にシェルクォートしてください。Platform Tools 23 以降(developer.android.com/tools/adb#shellcommands)。- スイートの後処理では、スイート内で上書きした場合、必ず
wm size resetとwm density resetを呼び出してください。上書きが残ると、そのデバイスで後続の実行がすべて失敗します。 - UI を検証するテストを実行する前に、3 つのアニメーションスケールを
0に設定するか、Gradle でtestOptions.animationsDisabled = trueを使用してください。 - UI が追いつくのを待つために、
adb shell inputの呼び出し間でThread.sleepを使用してはいけません。インストルメンテーションテスト内では、Compose のアイドル同期を使用してください(../../../compose/synchronization/synchronizing-with-idle/SKILL.md)。ホストスクリプトからは、Activity の起動を待つためにadb shell am start -Wを使用し、再起動の合間にはadb shell wait-for-deviceを使用してください。 -wを付けずにadb shell am instrumentが意味のある終了コードを返すと想定してはいけません。../../tests/running-instrumented-tests-via-adb/SKILL.mdおよび../../automation/scripting-adb-for-ci/SKILL.mdを参照してください。- 推奨: テストでコールドスタートする場合は
am start -S -W -n pkg/.Activityを使用してください。-Sはリセットし、-Wは準備が完了するまで待機します。
検証
- テスト実行前に
adb shell settings get global window_animation_scaleが0(または0.0)を返すこと。transition_animation_scaleとanimator_duration_scaleについても同様です。 -
scripts/または.github/workflows/内のスクリプトでsvc wifi/svc bluetooth/svc dataを使用していないこと。 - テスト間のすべての
am force-stopがpm clearと組み合わせて実行されているか、pm clearに置き換えられていること。 -
input text "<string with spaces>"が存在せず、すべての空白が%sになっていること。 - セットアップにあるすべての
wm size <override>に対し、後処理でwm size resetが実行されていること。 - CI が「device entered prior config」による不安定な失敗なしで、連続 50 回の実行に成功すること。
参考資料
- developer.android.com/tools/adb —
am、pm、input、wm、settings、インテントの仕様(https://developer.android.com/tools/adb)。 - developer.android.com/tools/adb#shellcommands — Platform Tools 23 以降の
adb shell経由の引用符の扱い。 - developer.android.com/reference/android/view/KeyEvent —
KEYCODE_*定数の一覧表。 - developer.android.com/training/testing/instrumented-tests/stability — アニメーションスケールをゼロにする標準的な手順。
- developer.android.com/studio/test/advanced-test-setup#use-gradle-managed-devices —
testOptions.animationsDisabled。 - 調査メモ
tasks/research/A2-adb-shell-commands.md—input/wm/settings/am/pm/cmd/svcの全テーブルと原文引用。 - 関連スキル:
../../architecture/understanding-adb-architecture/SKILL.md— 3 つの要素からなるアーキテクチャ、サーバー、デーモン。 - 関連スキル:
../../devices/connecting-to-devices/SKILL.md—adb devicesの状態、wait-for-device。 - 関連スキル:
../../devices/connecting-over-wifi/SKILL.md—adb pair/adb connect。 - 関連スキル:
../../apps/installing-and-managing-apps/SKILL.md—pm install/pm uninstall/pm grantの全機能。 - 関連スキル:
../../tests/running-instrumented-tests-via-adb/SKILL.md—am instrument -w -r。 - 関連スキル:
../../capture/capturing-screenshots-and-screenrecord/SKILL.md— デバイスを操作した後の成果物のキャプチャ。 - 関連スキル:
../../observability/extracting-logs-with-logcat/SKILL.md— デバイスログの読み取り。 - 関連スキル:
../../transfer/extracting-test-artifacts/SKILL.md—adb pull/adb push/run-as。 - 関連スキル:
../../automation/scripting-adb-for-ci/SKILL.md— bash の慣用表現、再試行、ポート転送。 - 関連セット:
../../../instrumentation/scenarios/launching-activities-with-activityscenario/SKILL.md— インストルメンテーションテスト内からの起動。 - 関連セット:
../../../fundamentals/strategies/applying-testing-strategies/SKILL.md—adbとインストルメンテーションのどちらを使って操作するか。