公式 Android アプリは Google Play で入手できます。これはコンパニオンノードであり、実行中の OpenClaw Gateway が必要です。ソース: apps/android(ビルド手順)。
サポート状況
- 役割: コンパニオンノードアプリ(Android は Gateway をホストしません)。
- Gateway が必要: はい(macOS、Linux、または WSL2 経由の Windows で実行します)。
- インストール: アプリは Google Play、Gateway は はじめに、その後 ペアリング。
- Gateway: ランブック + 設定。
- プロトコル: Gateway プロトコル(ノード + コントロールプレーン)。
リモート Mac から Android をミラーリングして制御する
scrcpy は、Android 画面を macOS ウィンドウにミラーリングし、 Android Debug Bridge (ADB) 経由でキーボードとポインター入力を転送します。これはオペレーター側の ワークフローであり、OpenClaw ノード接続とは別です。Android デバイスと Mac が異なる場所にあり、同じプライベート Tailscale ネットワークを共有している場合に便利です。始める前に
- Android デバイスと Mac に Tailscale をインストールし、両方を同じ tailnet に接続します。
- Android で 開発者向けオプション と USB デバッグ を有効にします。Android 16 では ワイヤレス デバッグ は 設定 > システム > 開発者向けオプション の下にあります。Android 開発者向け オプション を参照してください。
-
Mac に scrcpy と ADB をインストールします:
- 初回接続時は Android デバイスを操作できる状態にしておきます。その Mac がデバイスを制御できるようになる前に、Android は各 Mac の ADB キーを承認する必要があります。
TCP 経由の ADB を有効にする
初期セットアップでは、Android デバイスを USB で信頼済みコンピューターに接続し、その デバッグプロンプトを承認します。その後、次を実行します:adb pair で初期信頼を確立することもできます。
コントローラー Mac のみを許可する
制限的な grants を持つ tailnet では、コントローラー Mac が Android デバイス上の TCP ポート 5555 に到達できるよう明示的に許可する必要があります。 tailnet ポリシーに狭いルールを追加し、例のアドレスを 2 台のデバイスの安定した Tailscale IP に置き換えます:接続してミラーリングを開始する
リモート Mac で:adb connect では、Android に認証ダイアログが表示されます。デバイスのロックを解除し、
キーのフィンガープリントを確認し、Mac が信頼できる場合にのみ このコンピューターから常に許可 を選択します。
成功した adb devices エントリは device で終わります。unauthorized は、デバイス上のプロンプトが
承認されていないことを意味します。
scrcpy ウィンドウが開いたら、直接使用するか、Peekaboo などの macOS 画面自動化ツールで
対象にします。scrcpy は表示と入力を運びます。Tailscale はプライベート
ネットワーク経路だけを提供します。
トラブルシューティング
Connection timed out: TCP 5555 の tailnet grant を確認します。成功したtailscale pingは ピア到達性を証明しますが、この TCP ポートがポリシーで許可されていることは証明しません。Mac からnc -vz <android-tailnet-ip> 5555でテストします。unauthorized: Android のロックを解除してリモート Mac の ADB キーを承認するか、ワイヤレス デバッグ > ペア設定済みデバイス の下にある古いワークステーションを削除して 再度ペアリングします。Connection refused: ローカルで再接続し、adb tcpip 5555をもう一度実行します。- 複数のデバイスが表示される: 明示的な
--serial <android-tailnet-ip>:5555引数を維持します。
接続ランブック
Android ノードアプリ ⇄ (mDNS/NSD + WebSocket) ⇄ Gateway Android は Gateway WebSocket に直接接続し、デバイスペアリング(role: node)を使用します。
Tailscale または公開ホストの場合、Android にはセキュアなエンドポイントが必要です:
- 推奨:
https://<magicdns>/wss://<magicdns>を使う Tailscale Serve / Funnel - 併用可能: 実際の TLS エンドポイントを持つその他の
wss://Gateway URL - 平文
ws://は、プライベート LAN アドレス /.localホストに加えて、localhost、127.0.0.1、Android エミュレーターブリッジ(10.0.2.2)で引き続きサポートされます
前提条件
- 別のマシンで Gateway が実行中(または SSH 経由で到達可能)。
- Android デバイス/エミュレーターが Gateway WebSocket に到達できる:
- mDNS/NSD を使う同一 LAN、または
- Wide-Area Bonjour / ユニキャスト DNS-SD を使う同一 Tailscale tailnet(下記参照)、または
- 手動 gateway ホスト/ポート(フォールバック)
- Tailnet/公開モバイルペアリングでは、生の tailnet IP
ws://エンドポイントは使用しません。代わりに Tailscale Serve または別のwss://URL を使用します。 - ペアリングリクエストを承認するために、gateway マシンで
openclawCLI が利用可能(または SSH 経由で利用可能)。
1. Gateway を起動する
listening on ws://0.0.0.0:18789
wss:// / https:// エンドポイントが提供されます。別途 TLS を終端しない限り、単純な gateway.bind: "tailnet" セットアップだけでは初回のリモート Android ペアリングには十分ではありません。
2. 検出を確認する(任意)
gateway マシンから:local. と設定済みワイドエリアドメインを 1 回の実行で表示します。
ユニキャスト DNS-SD によるクロスネットワーク検出
Android の NSD/mDNS 検出はネットワークをまたぎません。Android ノードと gateway が異なるネットワーク上にあり、Tailscale で接続されている場合は、代わりに Wide-Area Bonjour / ユニキャスト DNS-SD を使用します。検出だけでは tailnet/公開 Android ペアリングには不十分です。検出された経路にもセキュアなエンドポイント(wss:// または Tailscale Serve)が必要です:
- gateway ホスト上に DNS-SD ゾーン(例:
openclaw.internal.)をセットアップし、_openclaw-gw._tcpレコードを公開します。 - 選択したドメインに対して、その DNS サーバーを指す Tailscale split DNS を設定します。
3. Android から接続する
Android アプリで:- アプリは フォアグラウンドサービス(永続通知)を介して gateway 接続を維持します。
- 接続 タブを開きます。
- セットアップコード または 手動 モードを使用します。
- 検出がブロックされている場合は、詳細コントロール で手動ホスト/ポートを使用します。プライベート LAN ホストでは
ws://が引き続き機能します。Tailscale/公開ホストでは、TLS を有効にし、wss:/// Tailscale Serve エンドポイントを使用します。
Presence alive ビーコン
認証済みノードセッションが接続した後、およびフォアグラウンドサービスがまだ接続中のままアプリがバックグラウンドに移動したとき、Android はevent: "node.presence.alive" で node.event を呼び出します。gateway は、認証済みノードデバイス ID が判明した後にのみ、これをペア済みノード/デバイスメタデータ上の lastSeenAtMs/lastSeenReason として記録します。
アプリは、gateway 応答に handled: true が含まれる場合にのみ、ビーコンが正常に記録されたものとして数えます。古い gateway は { "ok": true } で node.event を確認応答する場合があります。この応答は互換性がありますが、永続的な last-seen 更新としては数えません。
4. ペアリングを承認する(CLI)
gateway マシンで:role: node ペアリングにのみ適用されます。オペレーター/ブラウザのペアリング、およびロール、スコープ、メタデータ、公開鍵の変更は、引き続き手動承認が必要です。
5. ノードが接続されていることを確認する
6. チャット + 履歴
Android Chat タブはセッション選択をサポートします(デフォルトはmain、加えて他の既存セッション):
- 履歴:
chat.history(表示用に正規化済み — インラインディレクティブタグ、プレーンテキストのツール呼び出し XML ペイロード(<tool_call>、<function_call>、<tool_calls>、<function_calls>、および切り詰められたバリアント)、漏出した ASCII/全角モデル制御トークンは除去されます。正確なNO_REPLY/no_replyのような無音トークンの assistant 行は省略されます。過大な行はプレースホルダーに置き換えられる場合があります) - 送信:
chat.send - プッシュ更新(ベストエフォート):
chat.subscribe->event:"chat"
7. Canvas + カメラ
Gateway Canvas ホスト(Web コンテンツに推奨)
エージェントがディスク上で編集できる実際の HTML/CSS/JS をノードに表示させるには、ノードを Gateway canvas ホストに向けます。ノードは Gateway HTTP サーバー(
gateway.port と同じポート、デフォルトは 18789)から canvas を読み込みます。- gateway ホスト上に
~/.openclaw/workspace/canvas/index.htmlを作成します。 - ノードをそこに移動します(LAN):
.local の代わりに MagicDNS 名または tailnet IP を使用します。例: http://<gateway-magicdns>:18789/__openclaw__/canvas/。
このサーバーは HTML にライブリロードクライアントを注入し、ファイル変更時に再読み込みします。Gateway は /__openclaw__/a2ui/ も提供しますが、Android アプリはリモート A2UI ページをレンダリング専用として扱います。アクション可能な A2UI コマンドは、バンドルされたアプリ所有の A2UI ページを使用します。
Canvas コマンド(フォアグラウンドのみ):
canvas.eval、canvas.snapshot、canvas.navigate(デフォルトのスキャフォールドに戻るには{"url":""}または{"url":"/"}を使用します)。canvas.snapshotは{ format, base64 }を返します(デフォルトはformat="jpeg")。- A2UI:
canvas.a2ui.push、canvas.a2ui.reset(canvas.a2ui.pushJSONLはレガシーエイリアス)。これらは、アクション可能なレンダリングにバンドルされたアプリ所有の A2UI ページを使用します。
camera.snap(jpg)、camera.clip(mp4)。パラメーターと CLI ヘルパーについては カメラノード を参照してください。
8. 音声 + 拡張 Android コマンドサーフェス
- Voice タブ: Android には 2 つの明示的なキャプチャモードがあります。マイクは手動の Voice タブセッションで、各ポーズをチャットターンとして送信し、アプリがフォアグラウンドを離れるか、ユーザーが Voice タブを離れると停止します。Talkは継続的なトークモードで、オフに切り替えるかノードが切断されるまでリスニングを続けます。
- トークモードは、キャプチャ開始前に既存のフォアグラウンドサービスを
connectedDeviceからconnectedDevice|microphoneに昇格し、トークモード停止時に降格します。ノードサービスはCHANGE_NETWORK_STATEとともにFOREGROUND_SERVICE_CONNECTED_DEVICEを宣言します。Android 14 以降では、FOREGROUND_SERVICE_MICROPHONE宣言、RECORD_AUDIOランタイム許可、実行時のマイクサービス種別も必要です。 - デフォルトでは、Android Talk はネイティブ音声認識、Gateway チャット、設定済みの Gateway Talk プロバイダー経由の
talk.speakを使用します。ローカルシステム TTS は、talk.speakが利用できない場合にのみ使用されます。 - Android Talk は、
talk.realtime.modeがrealtimeで、talk.realtime.transportがgateway-relayの場合にのみ、リアルタイム Gateway リレーを使用します。 - Voice wake はソース内(
VoiceWakeMode)に実装されていますが、出荷版アプリのランタイムは接続時に常にoffを強制します。現時点でユーザー向けの切り替えはありません。 - 追加の Android コマンドファミリー(利用可否はデバイス、権限、ユーザー設定によって異なります):
device.status,device.info,device.permissions,device.health- 設定 > 電話機能 > インストール済みアプリが有効な場合のみ
device.apps。デフォルトではランチャーに表示されるアプリを一覧表示します(完全な一覧にはincludeNonLaunchableを渡します)。 notifications.list,notifications.actions(以下の通知転送を参照)photos.latestcontacts.search,contacts.addcalendar.events,calendar.addcallLog.searchsms.searchmotion.activity,motion.pedometer
アシスタントのエントリーポイント
Android は、システムアシスタントトリガー(Google Assistant)から OpenClaw を起動できます。ホームボタンの長押し(または別のACTION_ASSIST トリガー)でアプリが開きます。「Hey Google, ask OpenClaw <prompt>」と言うと、アプリで宣言された App Actions クエリパターンに一致し、プロンプトが自動送信されずにチャットコンポーザーへ渡されます。
これは、アプリマニフェストで宣言された Android App Actions(shortcuts.xml capability)を使用します。Gateway 側の設定は不要です。アシスタントインテントは Android アプリだけで処理されます。
App Actions の利用可否は、デバイス、Google Play Services のバージョン、ユーザーが OpenClaw をデフォルトのアシスタントアプリに設定しているかどうかによって異なります。
通知転送
Android は、デバイス通知をnode.event 項目として Gateway に転送できます。これは gateway/openclaw.json 設定ではなく、アプリの設定シート内でデバイス上に設定します。
| 設定 | 説明 |
|---|---|
| 通知イベントを転送 | マスタートグル。デフォルトではオフです。先に Notification Listener Access を付与する必要があります。 |
| パッケージフィルター | 許可リスト(一覧にあるパッケージ ID のみ転送)またはブロックリスト(デフォルト: 一覧にある ID 以外のすべてのパッケージ)。転送ループを防ぐため、OpenClaw 自身のパッケージはブロックリストモードで常に除外されます。 |
| サイレント時間 | 転送を抑制するローカル HH:mm 開始/終了ウィンドウ。デフォルトでは無効で、有効化すると 22:00-07:00 がデフォルトになります。 |
| 最大イベント数 / 分 | 転送通知のデバイス単位のレート制限。デフォルトは 20 です。 |
| ルートセッションキー | 任意。転送された通知イベントを、デバイスのデフォルト通知ルートではなく特定のセッションに固定します。 |
通知転送には Android Notification Listener 権限が必要です。アプリはセットアップ中にこれを求めます。