mcpField
C
connecting-to-devices

connecting-to-devices

github.com/skydoves開発33969 回インストール22 週間前に更新
リポジトリ

connecting-to-devices について

Android Debug Bridge(ADB)を扱う開発者向けの実践スキルです。デバイスの検出や選択、起動待ち、複数台接続や Linux の権限に関する問題を説明します。

主な機能

  1. 01デバイス一覧と状態の確認
  2. 02シリアル番号や transport ID で選択
  3. 03接続と起動完了の待機
  4. 04認証と USB 権限の問題に対処
  5. 05複数デバイスでコマンドを実行

活用シーン

  1. 01複数接続時に対象デバイスを指定
  2. 02CI テスト前に Android の起動を待機
  3. 03unauthorized や offline の状態を診断
  4. 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 手順:

    1. adbd が、新しいクライアントから RSA 公開鍵が提示されたことを検知します。
    2. OS が「Allow USB debugging?」ダイアログを表示し、ワークステーションの鍵のフィンガープリントを示します。
    3. ユーザーが Allow をタップするまで、adb devices は unauthorized と報告します。
    4. 承認後、公開鍵がデバイス上の /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

コメント