connecting-to-devices について
Android Debug Bridge(ADB)を扱う開発者向けの実践スキルです。デバイスの検出や選択、起動待ち、複数台接続や Linux の権限に関する問題を説明します。
主な機能
- 01デバイス一覧と状態の確認
- 02シリアル番号や transport ID で選択
- 03接続と起動完了の待機
- 04認証と USB 権限の問題に対処
- 05複数デバイスでコマンドを実行
活用シーン
- 01複数接続時に対象デバイスを指定
- 02CI テスト前に Android の起動を待機
- 03unauthorized や offline の状態を診断
- 04Linux で adb devices に表示されない問題を修正
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ skydoves/ android-testing-skills --skill connecting-to-devicesインストール後、Claude Code で/connecting-to-devicesを入力して読み込まれたか確認します。
詳細
デバイスへの接続 — トランスポートの一覧表示、選択、待機
adb devices は最もよく入力される adb コマンドです。その後に起こりがちな落とし穴は実際によくあります。デバイスがオンラインになる前にスクリプトが実行される、複数デバイスを接続したシェルで more than one device/emulator エラーが発生する、Linux で udev ルールが見つからない、チュートリアルで架空の wait-for-device-online 形式が紹介されている、といった問題です。このスキルでは、正確な情報をまとめています。
このスキルを使う場合
- ユーザーがデバイスを 2 台接続した状態で
adb shellを実行し、error: more than one device/emulatorが表示される場合。 - ユーザーから、
adb devicesでデバイスがunauthorized、offline、またはno permissionsと表示されると報告された場合。 - テストを実行する前にデバイスの起動が完了するまで待つ CI スクリプトを、ユーザーが作成したい場合。
- ユーザーがブログ記事から
adb wait-for-device-onlineをコピーして実行し、使用方法のテキストが表示される場合。 - ユーザーが Linux を使用しており、接続したばかりのスマートフォンが
adb devicesに表示されない場合。
このスキルを使わない場合
- ユーザーが概要レベルのアーキテクチャ/サーバーのライフサイクル/環境変数について知りたい場合は、
../../architecture/understanding-adb-architecture/SKILL.mdを使います。 - ユーザーが Wi-Fi/ワイヤレスデバッグについて知りたい場合は、
../connecting-over-wifi/SKILL.mdを使います。 - ユーザーが接続中のデバイスにアプリをインストールしたい、またはアプリの状態を消去したい場合は、
../../apps/installing-and-managing-apps/SKILL.mdを使います。
前提条件
- ADB サーバーが正常に動作していること(
../../architecture/understanding-adb-architecture/SKILL.mdを参照)。 Settings → System → Developer optionsでUSB デバッグを有効にしたデバイス。Android 4.2 以降では、About phoneで「Build number」を 7 回タップするまで開発者向けオプションは非表示です。- Linux の場合:sudo を使って
/etc/udev/rules.d/51-android.rulesに書き込めること。 - Windows の場合:メーカーの USB ドライバー(Pixel/Nexus には SDK Manager から Google USB Driver、その他のメーカーには OEM ドライバー)。
ワークフロー
-
1. 毎回、まず
adb devicesを実行します。 接続されたトランスポートごとに 1 行出力され、形式は<serial> <state> [details...]です。スクリプトでは必ず-lを追加します。adb devices -l # List of devices attached # emulator-5556 device product:sdk_google_phone_x86_64 model:Android_SDK_built_for_x86_64 device:generic_x86_64 transport_id:1 # 0a388e93 device usb:1-1 product:razor model:Nexus_7 device:flo transport_id:2-lを付けると、product、model、device、transport_id、および(USB の場合)USB バスのパスが追加されます。 -
2. 状況に合ったセレクターを選びます。
フラグ 意味 失敗する場合 -s <serial>シリアルを明示的に指定します。USB のシリアル( 0a388e93)、エミュレーター(emulator-5554)、TCP デバイス(192.168.1.42:5555)で使えます。$ANDROID_SERIALより優先されます。シリアルが接続されていない場合。 -dUSB デバイスを 1 台指定します。 USB デバイスが 0 台、または 2 台以上の場合。 -eTCP/IP デバイスを 1 台指定します(エミュレーターと adb connectで接続したスマートフォンが対象です)。TCP デバイスが 0 台、または 2 台以上の場合。 -t <transport_id>adb devices -lで確認できる数値のトランスポート ID。 同じポートに再接続した場合も変わりません。トランスポート ID が存在しない場合。 注:
-tはトランスポート IDであり、タイムアウトを指定するフラグではありません。コマンドごとの制限時間を設ける場合は、シェルのtimeout(macOS ではgtimeout)で囲みます。 -
3. スクリプトで「準備完了」のデバイスに絞り込みます。
adb devices | awk '$2=="device"{print $1}'単一デバイス向けのショートカット:
adb get-serialnoはシリアルを、adb get-stateはoffline | bootloader | deviceのいずれかを、adb get-devpathは USB パスを返します。状態をすべて確認するには、adb devicesの出力を直接解析します。 -
4. 正規の
wait-for-*形式を使ってください。見かけることのある別形式は誤りです。adb help(scriptingセクション)によると、有効な構文は次のものだけです。wait-for[-TRANSPORT]-STATE TRANSPORT ∈ { usb, local, any } (transport defaults to any) STATE ∈ { device, recovery, rescue, sideload, bootloader, disconnect }よく使われる形式:
コマンド 次の状態になるまで待機します adb wait-for-device任意のトランスポートで、状態が deviceになるまで待機します。デフォルトの形式で、CI スクリプトの開始時に使われます。adb wait-for-usb-deviceUSB 接続されたデバイスの状態が deviceになるまで待機します。adb wait-for-local-deviceTCP/IP デバイス(エミュレーターまたはワイヤレス)の状態が deviceになるまで待機します。adb wait-for-bootloaderデバイスが bootloader(fastboot)状態で現れるまで待機します。adb wait-for-recovery/wait-for-sideload/wait-for-rescueそれぞれのモードについても同様です。 adb wait-for-disconnect現在選択されているデバイスが切断されるまで待機します(例: adb rebootの後)。ドキュメントには
wait-for-device-online形式は定義されていません。wait-for-*が確認するのはトランスポートのみで、起動完了ではありません。sys.boot_completedのポーリングと組み合わせてください。adb wait-for-device until [[ "$(adb shell getprop sys.boot_completed | tr -d '\r')" == "1" ]]; do sleep 1 done adb shell input keyevent 82 # AOSP のスライドアップ画面をロック解除する再起動時の一連の処理:
adb shell reboot adb wait-for-disconnect adb wait-for-device -
5. デバイスの状態を正しく読み取ってください。 adb ページ(
Query for devices)とadb helpによると、次のとおりです。状態 意味 対処 deviceオンラインで、 adbdが応答しています。起動完了を意味するものではありません。sys.boot_completedを条件にしてください。該当なし offlineトランスポートは存在しますが、 adbdと通信できていません。サスペンド/レジューム後や USB ハブでよく発生します。adb reconnect offlineを実行し、必要に応じて再接続します。unauthorizedホストの RSA キーがまだデバイス上で承認されていません。 デバイスのロックを解除し、デバイス上のダイアログで Allow をタップします。ダイアログが表示されない場合は、別の USB ケーブルを試してください(一部の「充電専用」ケーブルではデータを転送できません)。 recoveryリカバリーで起動しています。使える adbの機能はごく一部です。該当なし sideloadOTA のサイドロードモードです。 adb sideload package.zipを使います。該当なし bootloaderブートローダー(fastboot)にいます。 adbでは通信できません。fastbootを使ってください。該当なし rescueRescue Party モード(Android 10 以降)です。 該当なし connectingワイヤレス接続時の一時的な TLS ハンドシェイク状態です。 待機します。 no permissions(Linux のみ)USB は認識されていますが、udev ルールがないためアクセスがブロックされています。 ルールをインストールします。手順 7 を参照してください。 -
6. 初回接続時に RSA フィンガープリントのダイアログを承認してください。
「Android 4.2.2(API レベル 17)以降を搭載したデバイスを接続すると、システムはダイアログを表示し、このコンピューター経由でデバッグを許可する RSA キーを承認するかどうかを尋ねます。」 — developer.android.com/tools/adb 手順:
adbdが、新しいクライアントから RSA 公開鍵が提示されたことを検知します。- OS が「Allow USB debugging?」ダイアログを表示し、ワークステーションの鍵のフィンガープリントを示します。
- ユーザーが Allow をタップするまで、
adb devicesはunauthorizedと報告します。 - 承認後、公開鍵がデバイス上の
/data/misc/adb/adb_keysに追加されます。Always allow from this computer にチェックを入れると、同じ~/.android/adbkeyからの次回以降の接続では確認が省略されます。
古いワークステーションのアクセス許可は、
Settings → Developer options → Revoke USB debugging authorizationsから取り消せます。 -
7.(Linux)udev ルールをインストールすることで、新たに接続したスマートフォンで
no permissionsのままになるのを防ぎます。標準のファイルは/etc/udev/rules.d/51-android.rulesです。最小限の例(OEM ごとに 1 行):# Google SUBSYSTEM=="usb", ATTR{idVendor}=="18d1", MODE="0660", GROUP="plugdev", TAG+="uaccess" # Samsung SUBSYSTEM=="usb", ATTR{idVendor}=="04e8", MODE="0660", GROUP="plugdev", TAG+="uaccess"再起動せずに適用するには、次のコマンドを実行します。
sudo udevadm control --reload-rules sudo udevadm trigger # デバイスを取り外して、再度接続しますほとんどのディストリビューションには、同じファイルを
/lib/udev/rules.d/に配置する包括的なandroid-udev/android-sdk-platform-tools-commonパッケージも用意されています。 -
8.(Windows)ベンダーの USB ドライバーをインストールする。 Pixel / Nexus / 汎用 AOSP デバイスでは、
SDK Manager → SDK Tools → Google USB Driverから Google USB Driver を使用します(ファイルはandroid_sdk\extras\google\usb_driver\にあります)。その他の OEM では、メーカーのドライバーが必要です。入手先:https://developer.android.com/tools/extras/oem-usb。macOS と Linux では、ベンダーのドライバーは不要です。 -
9. 複数デバイスへの一括処理。 ADB に組み込みの
--allフラグはありません。次の 2 つの方法があります。# 順次実行 for s in $(adb devices | awk '$2=="device"{print $1}'); do adb -s "$s" install -r app.apk done # 並列実行(同時に 4 ジョブ) adb devices | awk '$2=="device"{print $1}' \ | xargs -I{} -P 4 adb -s {} install -r app.apkそれぞれが 1 台のスマートフォンを所有するシャーディングされた CI ランナーでは、サーバーを 1 台のデバイスに固定します。
adb --one-device 0a388e93 start-server
パターン
パターン:誤った例と正しい例 — more than one device/emulator
# WRONG
adb shell getprop ro.product.model
# adb: more than one device/emulator
# WRONG because: with two transports attached (e.g. an emulator + a USB phone),
# every non-server adb command needs an explicit selector. The command did not
# fail; it never even ran.
# RIGHT
adb -s emulator-5554 shell getprop ro.product.model
# Or, if there is exactly one USB phone:
adb -d shell getprop ro.product.model
# Or set $ANDROID_SERIAL once and stop typing -s:
export ANDROID_SERIAL=emulator-5554
adb shell getprop ro.product.model
パターン:誤った例と正しい例 — 架空の wait-for-device-online
# WRONG
adb wait-for-device-online
# error: usage: ...
# WRONG because: this command does not exist. The canonical syntax is
# wait-for[-TRANSPORT]-<state> with state in {device, recovery, rescue,
# sideload, bootloader, disconnect}. There is no -online state.
# RIGHT
adb wait-for-device # any transport, state=device
# Then poll boot complete (transport up != system booted):
until [[ "$(adb shell getprop sys.boot_completed | tr -d '\r')" == "1" ]]; do
sleep 1
done
パターン:誤った例と正しい例 — エミュレーター起動時の競合
# WRONG
emulator -avd Pixel_API_34 &
adb install -r app.apk # races: emulator may not be online yet
# Often: error: device 'emulator-5554' not found
# RIGHT
adb start-server # important: see corner case below
emulator -avd Pixel_API_34 &
adb -s emulator-5554 wait-for-device
until [[ "$(adb -s emulator-5554 shell getprop sys.boot_completed | tr -d '\r')" == "1" ]]; do
sleep 1
done
adb -s emulator-5554 install -r app.apk
例外的なケース(adb のページからの原文):"
adbサーバーが実行されていない場合、5554 から 5584 の範囲内にある奇数ポートを指定する-portまたは-portsオプションを使ってemulatorコマンドを実行した場合、かつエミュレーターの起動後に adb サーバーを起動した場合など、すべての条件が当てはまると、起動中のエミュレーターがadb devicesに表示されないことがあります。" 回避策:エミュレーターより先にadb start-serverを実行します。
パターン:誤った例と正しい例 — transport_id と -t の混同
# WRONG
adb -t 60 shell getprop ro.product.model
# WRONG because: -t is transport_id, not a 60-second timeout. Either there is
# no transport with id=60 (error: device not found) or the command runs against
# the wrong device.
# RIGHT
# Real timeout via the shell tool:
timeout 60 adb -s emulator-5554 shell getprop ro.product.model # GNU timeout
gtimeout 60 adb -s emulator-5554 shell getprop ro.product.model # macOS (coreutils via brew)
# Use -t only with a transport_id from adb devices -l:
adb -t 2 shell getprop ro.product.model
必須ルール
- 必須: 複数のトランスポートが接続されている場合は、すべての adb コマンドにセレクター(
-s/-d/-e/-t)を追加するか、$ANDROID_SERIALを設定します。 - 必須: 文書化されている
wait-for[-TRANSPORT]-<state>構文を使用します。wait-for-device-onlineは存在しません。 - 必須: スクリプトで OS の完全な起動が必要な場合(APK のインストールや
am instrumentの呼び出し前など)は、wait-for-deviceの後にgetprop sys.boot_completedをポーリングします。 - 禁止:
-t TRANSPORT_IDをタイムアウト用のフラグと混同しないでください。実際のタイムアウトにはtimeout/gtimeoutでラップします。 - 禁止:
unauthorizedの「修正」のために~/.android/adbkey*を削除しないでください。正しい復旧方法については../../architecture/understanding-adb-architecture/SKILL.mdを参照してください。 - 推奨: 同じシリアル番号を持つデバイスが 2 台見つかる可能性のあるスクリプト(まれなハードウェアの不具合や AVD の重複)では、
adb devices -lとtransport_idを使用します。 - 推奨: Linux では
51-android.rulesを手動で管理する代わりに、ディストリビューションのandroid-udevパッケージをインストールします。
検証
-
adb devices -lに、接続されているすべてのトランスポートが状態deviceで表示されます(offline、unauthorized、no permissionsは表示されません)。 -
adb devices | awk '$2=="device"{print $1}'は、準備が完了したデバイスごとに1行を返します。 -
adb -s <serial> get-stateはdeviceを出力します。 - 少なくとも1つのトランスポートが状態
deviceであれば、adb wait-for-deviceはすぐに終了します。 - 新たに起動した後、
adb shell getprop sys.boot_completedは1を出力します。 -
adb -d shell echo ok(または-e、または-s)は、more than one device/emulatorと表示されずに成功します。 - Linux では、
lsusbにデバイスが表示され、udev ルールの適用後にadb devicesがno permissionsではなくdeviceを報告します。
参考資料
- ADB ユーザーガイド(
adb devices、wait-for-*、RSA ダイアログ):https://developer.android.com/tools/adb - デバイスでの実行設定(Linux の udev ルール、Windows ドライバー):https://developer.android.com/studio/run/device
- OEM USB ドライバー(Windows):https://developer.android.com/tools/extras/oem-usb
- AOSP
adbの man ページ:https://android.googlesource.com/platform/packages/modules/adb/+/refs/heads/main/docs/user/adb.1.md tasks/research/A1-adb-architecture-devices.md—wait-for-*の表、wait-for-device-onlineの修正、状態の全種類、udev ルールの設定手順をそのまま記載しています。docs/CORPUS.md§I.3(状態の正確な一覧)および §I.10(調査結果)。- 関連スキル:
- 高レベルアーキテクチャ:
../../architecture/understanding-adb-architecture/SKILL.md - ワイヤレス ADB:
../connecting-over-wifi/SKILL.md - アプリのインストール/データの消去:
../../apps/installing-and-managing-apps/SKILL.md - インストルメンテーションテストの実行:
../../tests/running-instrumented-tests-via-adb/SKILL.md
- 高レベルアーキテクチャ:
- 関連する別セットの項目:
AndroidJUnit4を使ったインストルメンテーションテストの実行:../../../instrumentation/runner/running-instrumented-tests-with-androidjunit4/SKILL.md- Android での JUnit4 の設定:
../../../jvm-tests/runner/configuring-junit4-on-android/SKILL.md - ソースセットの方針:
../../../fundamentals/strategies/organizing-test-source-sets/SKILL.md