【マルチデバイスチーム ブログリレー5日目】
マルチデバイスチームの小林(@bakobox)です。
2026年4月に Android CLI が公開されました。プロジェクトの作成から実機デバイス / エミュレータの操作までを行える CLI で、AI エージェントによるアプリ開発の操作を容易にすることを目的に開発されています。
この Android CLI と、昔からある ADB コマンドの使い方を AI エージェントに教えるだけで、公式ツールのみで Android 実機 / エミュレータを操作できます。
本記事では、Android CLI と ADB を使って Android 実機 / エミュレータを操作するエージェントスキルを、実際のコマンドとあわせて紹介します。

AI エージェントによる Android デバイス操作で何が変わるか
AI を使ったアプリ開発では、次のようなループが起こります。
AI が実装 -> 人間が動作確認 -> AI が修正 -> 人間が動作確認 -> AI が修正 -> ...
このループの中で、動作確認は人間が担う必要があり、そこがボトルネックになっていました。 AI エージェントが Android デバイスを操作できるようになると、このループは次のように変わります。
AI が実装 -> AI が動作確認 -> AI が修正 -> AI が動作確認 -> AI が修正 -> ...
動作確認も含めたループを AI だけで回せるようになります。
次の動画は、ガジェット EC アプリのサンプルで Claude Code に動作確認をしてもらっている様子です。

商品一覧の表示・検索・カルーセルのスクロール・商品のカートへの追加といった操作を、人間が介入することなく自律的に行っています。
使用する Android CLI コマンド
デバイスの UI 情報を取得するために使う Android CLI コマンドを紹介します。
layout
android layout [--pretty] [--output] [--diff]
このコマンドは、現在接続されている実機またはエミュレータのアクティブなアプリの UI レイアウトを JSON 形式で返します。

例えば、このサンプルアプリで layout コマンドを実行すると、次のようなデータが返されます。
[ { "interactions": [ "scrollable" ], "center": "[540,1335]", "bounds": "[0,310][1080,2361]", "resource-id": "product_list", "key": 3506402 }, { "interactions": [ "clickable", "focusable", "long-clickable" ], "center": "[540,404]", "resource-id": "search_field", "key": 3506402 }, { "text": "Featured", "center": "[151,710]", "resource-id": "header_Featured", "key": 3506402 }, { "interactions": [ "scrollable" ], "center": "[540,1095]", "bounds": "[42,774][1038,1417]", "resource-id": "featured_carousel", "key": 3506402 }, { "text": "All Products", "center": "[193,1491]", "resource-id": "header_All_Products", "key": 3506402 }, { "content-desc": "Search gadgets", "center": "[540,404]", "key": 3506402 }, ... ]
返される JSON は UI 要素の配列で、配列の各要素が画面上の1つの UI 要素に対応します。各要素には次のようなフィールドが含まれます。
text- 要素が持つテキストresource-id- 要素を参照するための Android リソース IDcontent-desc- アクセシビリティツール向けの UI 要素の説明interactions- 要素がサポートするユーザー操作の種類。checkable、clickable、focusable、scrollable、long-clickable、passwordのいずれか、または複数state- 要素の現在の状態。checked、focused、selectedのいずれか、または複数bounds- 要素のバウンディングボックスの画面座標。[最小X,最小Y][最大X,最大Y]形式center- 要素の中心の画面座標。[x,y]形式off-screen- true の場合、要素は UI 階層に存在するが表示されていない。スクロールすることで表示される可能性がある
これらのフィールドを手がかりに、目的の UI 要素の座標を特定して操作します。例えば次のように活用できます。
resource-id が search_field の要素は center が [540,404] なので、検索フィールドをタップしたい場合はこの座標を操作すればよいとわかります。このように、 UI 要素の座標さえ取得できれば、あとはその座標に対してタップなどを実行するだけです。
このコマンドは、 Jetpack Compose で構築した UI はもちろん、 Flutter で描画した UI でも使えます。
ただし、 WebView 内の要素は取得できない点に注意が必要です。アプリ内 WebView の要素の座標を特定したい場合は、次のコマンドを使います。
screen capture / screen resolve
android screen capture [--output] [--annotate]
このコマンドを使って、接続されたデバイスのスクリーンショットをキャプチャできます。この出力を AI が読むようにすれば、見た目の確認作業を AI に任せられます。
さらに --annotate オプションを付けて実行すると、画像内の UI 要素の周りに数字付きのバウンディングボックスを描画します。

この画像とバウンディングボックスの数値を次のコマンドで指定することで、対象要素の座標を特定できます。
android screen resolve --screenshot=<path> --string=<string>
例えば、先ほどのキャプチャの9番の要素の座標を特定する場合、
android screen resolve --screenshot=screenshot.png --string="input tap #9"
を実行すると、
input tap 539 404
と出力されます。
これで、 WebView 内の目的の要素の座標も得られます。
まずは layout コマンドで UI 要素の座標の特定を試み、取得できなかったら screen capture / screen resolve ベースの手法にフォールバックすることで、ほぼすべての要素の座標を特定できます。
使用する ADB コマンド
入力操作に使う ADB コマンドを紹介します。
いずれも adb -s <serial> shell input から始まるコマンドです。-s <serial> で操作対象のデバイスを指定します(adb devices で確認できるシリアル番号)。複数のデバイスやエミュレータが接続されている場合に、どれを操作するかを明示するために付けています。
adb -s <serial> shell input tap <x> <y>
指定した座標 (x, y) をタップします。先ほどの layout コマンドや screen resolve で調べた座標を渡せば、目的の要素をタップできます。
adb -s <serial> shell input text '<text-with-%s-for-spaces>'
フォーカスされている入力欄に文字列を入力します。スペースはそのままだと扱えないため、%s に置き換えて渡す点に注意が必要です(例: hello world → hello%sworld)。
adb -s <serial> shell input swipe <x1> <y1> <x2> <y2> <ms>
(x1, y1) から (x2, y2) へスワイプします。最後の <ms> はスワイプにかける時間(ミリ秒)で、リストのスクロールやページめくりに使えます。
adb -s <serial> shell input keyevent <KEYCODE>
キーイベントを送出します。<KEYCODE> には キーコード を指定します。例えば KEYCODE_BACK で戻る、KEYCODE_ENTER でエンターといった、画面上の要素に依らないシステム操作を実行できます。
スキル
以下が実際のスキルファイルの内容です。
--- name: android-device-interactor description: Android 実機 / エミュレータを操作して動作確認を行う。UI レイアウトの取得、要素座標の特定、タップ・テキスト入力・スワイプ・キーイベント送出を Android CLI と adb を使って実行する。 --- # ツール `android layout --help` および `android screen --help` を実行して詳細を確認してください。 ## UI ダンプ `android layout` は、画面上の UI 要素をフラットな JSON リストで返します。 `android layout --diff` は、前回の `layout` または `layout --diff` 呼び出し以降に変化した UI 要素のみをフラットな JSON リストで返します。 各 JSON オブジェクトは Android アプリの UI 要素を表します。次のプロパティが含まれます: - `text` - 要素が持つテキスト - `resource-id` - 要素を参照するための Android リソース ID - `content-desc` - アクセシビリティツール向けの UI 要素の説明 - `interactions` - 要素がサポートするユーザー操作の種類。`checkable`、`clickable`、`focusable`、`scrollable`、`long-clickable`、`password` のいずれか、または複数 - `state` - 要素の現在の状態。`checked`、`focused`、`selected` のいずれか、または複数 - `bounds` - 要素のバウンディングボックスの画面座標。`[最小X,最小Y][最大X,最大Y]` 形式 - `center` - 要素の中心の画面座標。`[x,y]` 形式 - `off-screen` - true の場合、要素は UI 階層に存在するが表示されていない。スクロールすれば見える可能性がある Android アプリの動作確認の主な手段として `layout` を使用してください。変化点の把握やコンテキストを小さく保つには `layout --diff` を使用してください。 例:電卓に数字を入力するとき、`layout --diff` を使うと数字表示の要素のみ出力されます。 WebView やアニメーションが表示されている場合、`layout` が失敗することがあります。その場合は `android screen --annotate` を使用してください。 現在の画面から別の画面へ移動したら、この問題は解消される可能性があります。 ## スクリーンショット `android screen capture -o <ファイルパス>` は、現在のデバイス画面の PNG を `<ファイルパス>` に保存します。 Android アプリの動作確認の補助的な手段として `screen capture` を使用してください。 使用例: - 画面上の画像の内容を理解したい場合 - `WebView` を確認したい場合(Web コンテンツは UI ダンプに表示されないことがあります) - UI 要素を見た目から探したい場合 **重要**:`android screen` から返された PNG 画像は、他の操作をする前に必ず*目視で*確認してください。 ## アノテーション付きスクリーンショット `android screen capture --annotate -o <ファイルパス>` `android screen resolve --screen <パス> --string <文字列>` `--annotate` コマンドは UI 要素の周囲に数字ラベルとバウンディングボックスを追加します。`layout` の出力から特定できない UI 要素を見つけるために使用してください。 **重要**:`android screen --annotate` を使用した場合は、生成された PNG ファイルを必ず*目視で*確認してください。 入力コマンドでこれらのラベルを参照するには、`screen resolve` を使ってラベルを座標に変換してください: `android screen resolve --screen <ファイルパス> --string "#3"` は `<region 3 の x 座標> <region 3 の y 座標>` を返します。 ターン数を節約するため、シェルコマンドを組み合わせて使えます: `adb shell input $(android screen resolve --screen screen.png --string "tap #34")` このコマンドは `screen.png` の #34 の領域をタップします。 ## 入力操作 Android デバイスとのインタラクションには `adb shell input` を使用してください。 特定の要素に対してどの操作が実行できるかは、要素の `"interactions"` プロパティを参照してください。 UI 要素は `center` 座標または `bounds` 座標を使って操作してください: { "key": -248568265, "class": "android.widget.Button", "bounds": "[138,9][167,38]", "center": "[152,23]" } このボタンをタップするには `adb shell input tap 152 23` を実行します。中心座標をタップします。 { "key": 12487234, "class": "com.example.ui.ScrollableList", "bounds": "[100,200][400,600]", "center": "[250,400]" } このリストを下にスクロールするには `adb shell input swipe 250 400 600 500` を実行します。中心から下方向へ 500ms かけてスワイプします。 # Android 操作ルール 1. テキスト入力フィールドに文字を入力する前に、必ず `"state"` リストに `"focused"` が含まれていることを確認してください 2. 要素の `"interactions"` リストに `"scrollable"` が含まれている場合、見つからない UI 要素を探すためにスクロールを試みてください 3. スクロール操作は常にゆっくり実行してください。`adb shell input swipe` の第5引数でスクロール時間を制御できます 4. コンテンツの読み込みに時間がかかる場合があります。操作後に `layout` で情報が不足している場合は、数秒待ってから `layout --diff` を実行して変化を確認してください
これで、冒頭のデモ動画のように AI エージェントが Android 実機 / エミュレータを操作できるようになりました!
実はこれ、 android/skills で公開されているスキルを日本語に翻訳したものです(frontmatter部分は変更しています)。 これほどシンプルなスキルで動作します。これを自分用にカスタマイズしていくのも楽しいです!
まとめ
公式のツールのみを使用して Android 実機 / エミュレータを操作できるエージェントスキルを紹介しました。
今回紹介したスキルは簡易版です。業務では、これを拡張したものをチーム内のプラグインマーケットプレイスで公開し、開発に活用しています。生のコマンドを AI エージェントに直接叩かせるのではなく、Python でラップしています。これにより、コマンドの出力を加工して必要な情報のみを渡したり、エージェントとのやり取りの回数を節約したり、操作前後のスクリーンショットを連番保存したりといった工夫を入れています。
機能面でも、adb shell input tap <x> <y> のような座標指定だけでなく、tap --text "ログイン" のように表示テキストや resource-id を指定して要素をタップできるようにしたり、終端まで自動でスクロールする機能、アプリの起動/強制停止、ランタイム権限の付与/取消、ディープリンク起動、Logcat の取得といった、動作確認に必要な操作を一通り追加しています。
今回は簡易的なスキルの紹介でしたが、コマンドの組み合わせ次第で動作確認の自動化の幅はまだまだ広がりそうです。アプリ開発のループを AI だけで回せる世界に向けて、今後もアプリ開発に役立つプラグインを作っていきたいです!
We are hiring!
エムスリーでは、 AI を駆使してアプリ開発をしていただけるモバイルアプリエンジニアを募集中です!ご興味がありましたら、ぜひこちらからご応募ください!