input text
端末を変えるいまフォーカスがある入力欄に文字列を打ち込みます。
- コマンド
- adb shell input text
- コマンド
- 入力とタッチ
- リスク
- 端末を変える
構文
input text <string>使用例
input text 'hello world'引用してください。シングルクォートの中ではシェルは何にも手を出しません。
input text 'user@example.com'端末側ではなく本物のキーボードからログイン欄を埋めます。
input keyevent 66`input text` は改行を打たないので、後で Enter を押します。
出力の読み方
何も出ません。文字が端末に現れるか、現れないかで、どちらの報告もないので画面を見てください。
出力フィールド
| フィールド | 意味 |
|---|---|
| (no output) | コマンドは実行されました。文字が届いたかどうかは端末の画面でしか分かりません。 |
必要な権限
認可済みの `adb` 接続だけで足ります。root も `adb root` も `su` も、USB デバッグ以外に開発者向けオプションで入れるものもありません。`input` は `cmd input "$@"` を実行するだけの 1 行のシェルスクリプト(AOSP の `cmds/input/input.sh`)なので、文字は `shell` ユーザーの身元で注入され、その背後に立つプラットフォーム権限は `android.permission.INJECT_EVENTS`、`com.android.shell` が自身のマニフェストで与えられているものです。この付与が意図して含んでいないのは、狙いを付ける手段です。`runText` が受け取るのは入力ソース、任意の `-d <displayId>`、そして文字列だけで、対象のアプリや activity や入力欄を名指しする引数は存在しません。文字は、届いた瞬間にそのディスプレイでフォーカスを持っている場所に落ちます。だからスクリプトでは、アクセス権よりも間合いと順序のほうがはるかに重要になります。目を離した隙に出たダイアログは、あなたのパスワードが打ち込まれる場所として完全に正当です。しかも待てる応答がありません。`sendText` は各イベントを注入側に渡すだけで結果を見ないので、下流が 1 打鍵でも消費したかを知らないままコマンドは終了します。正直な確認手段は `screencap` だけです。
エラーメッセージの読み解き
| メッセージ | 意味 |
|---|---|
| java.lang.IllegalArgumentException: Argument expected after "text" | `runText` が必須の引数を要求したのに何もなかったので、`input text` の後ろが空だと例外になります。行は `Exception occurred while executing 'text':` のバナーとスタックトレースを伴って、すべて標準エラーに届きます。これが「空文字列ではない」ことに注意してください。`input text ''` は合法な、引用された空の引数で、静かに何もしません。 |
| Exception occurred while executing 'text': | shell command のハンドラが `Throwable` を捕まえ、バナーの次の行がそれを名指しします。非 ASCII の場合はここで終わります。`KeyCharacterMap.getEvents` は、現在のキー文字マップでは生成できない文字配列に対して null を返すと文書化されていて、このページのために読んだソースは null を確認せずに `events.length` を辿ります。つまり `é` や `日本語` を含む文字列は、途中まで打つのではなく `NullPointerException` を投げます。古いビルドではもっと静かに失敗すると報告されていて(下の注意を参照)、このページが非 ASCII を試す前に断るのはまさにそのためです。 |
| Error: Invalid arguments for display ID. | `-d` に整数でも `DEFAULT_DISPLAY` でも `INVALID_DISPLAY` でもないものが渡されました。1 文字も送る前、解析の段階で投げられるので、何も打たれていません。見るべきは文字列ではなく `-d` の次のトークンです。 |
| cmd: Can't find service: input | `input.sh` は `cmd input` の薄い包みでしかないので、`cmd` がサブコマンドを渡す先の `input` サービスを見つけられませんでした。起動途中、`system_server` がそれを公開する前なら想定内で、同じ時点で `settings` や `window` のサービスが返すのと同じ形の失敗です。 |
何が変わるか、そして戻る道
端末上のものが削除されることはありませんが、入力した文字はその瞬間フォーカスを持っているものすべてに届きます。チャットのメッセージ、検索ボックス、ログインやパスワードの欄、あるいは最後に画面を見てから出てきた確認ダイアログなどです。いったん送信されると取り消せません。まだ送信されていなければ、`input keyevent 67`(Delete)で 1 文字ずつ消せます。フォームを送信するのは `input keyevent 66`(Enter)です。入力する前に画面を確認し、欄に残っては困る秘密の文字列は送らないでください。
バージョンとメーカーに関する注意
- ASCII のみで、これはケーブルやシェルではなくプラットフォームのコマンドの制限です。`input text` は印字可能な ASCII にしかキーを持たない仮想キーボードの文字マップで終わるので、日本語・中国語・アクセント付き文字はキーイベントを何も生みません。デスクトップの adb でも打てません。
- 引数の中の `%s` は、キーボードが見る前に `input` 自身が空白に変えます。しかも `%%s` はパーセント記号と空白になるので、逃げ道はありません。1 回の呼び出しの中で `%` と `s` が隣り合わないように文字列を分けてください。
- シングルクォートはアポストロフィを運べません。そこで文字列を切り、アポストロフィは `input keyevent 75` で送ります。`'\''` のような細工は、写し間違いが起きる類のものです。
- 引数を引用していれば空白に `%s` は不要です。シェルが 1 つの語の中に空白を保ち、キーボードがそれをスペースキーに対応させます。
これには UI があります
Android ADB Toolbox はこのコマンドを USB 経由で実行し、返ってきたものを解析します。Chromium 系ブラウザだけで、SDK も不要、どこにもアップロードしません。
関連コマンド
input text と同じ作業で出てくるコマンド。
| コマンド | 何をするか |
|---|---|
| input keyevent | ハードウェアキーや仮想キーを押します。Home、Back、電源、音量、Enter など。 |
| getevent | カーネルから生の入力イベントを流し読みします。各入力デバイスが何を報告できるかの一覧も取れます。 |
| am start | コンポーネント指定または intent 指定でアクティビティを起動します。ディープリンクの解決を確かめる最短経路です。 |
Web ADB ツール群のパーサを書きながら、AOSP・toybox・カーネルのソースに突き合わせて確認しています。バージョンやメーカーで本当に挙動が変わるところは、世界の半分の端末で間違いになる数値を出す代わりに、そう書いてあります。