クラウドを一切介さずデバイス内で完結するため、機密情報の漏洩リスクがゼロで、なおかつ通信費もかかりません。 この記事の手順通りに進めれば、あなたのPythonスクリプトから実機のスマホを自律操作できるようになります。
所要時間: 約45分 | 難易度: ★★★★☆
この記事で作るもの
- Androidスマホの画面をリアルタイムで解析し、AIが「次にどこをタップすべきか」を判断して自律操作するPythonシステム
- 前提知識:Pythonの基本的な読み書き、ADB(Android Debug Bridge)の基礎知識
- 必要なもの:Android端末(開発者モードON)、USBケーブル、Python 3.10以上のPC(RTX 30シリーズ以上推奨、Macも可)
📦 この記事に関連する商品
MINISFORUM UM780 XTXローカルLLMを24時間稼働させるなら、Ryzen 7搭載で省電力かつ高性能なこのミニPCが最適です
※アフィリエイトリンクを含みます
なぜこの方法を選ぶのか
これまでスマホの自動化といえば、AppiumやSeleniumを使って「要素のID」を指定する泥臭い作業が主流でした。 SIer時代、アプリのアップデートでIDが変わるたびに数千行のテストコードを修正させられたのは、今思い出しても悪夢です。 しかし、このPokeClawが採用している「VLM(視覚言語モデル)による直接操作」は、人間と同じように画面を見て判断します。
OpenAIのOperatorやAnthropicのComputer Useが話題ですが、それらはすべて「画面のスクリーンショットをクラウドに投げる」のが前提です。 パスワード入力画面や個人情報の塊であるスマホの操作をクラウドに預けるのは、実務レベルではセキュリティ要件をクリアできません。 Gemma 4のような軽量かつ強力なローカルモデルを端末内(または自宅サーバー内)で完結させるこの手法こそが、業務自動化の本命だと確信しています。
Step 1: 環境を整える
まずはAndroid端末と通信するための橋渡し役であるADBと、画面キャプチャを高速化するためのライブラリを揃えます。
# Android Debug Bridgeのインストール(Macならbrew、Windowsなら公式からバイナリを取得)
brew install android-platform-tools
# 必要なライブラリのインストール
pip install opencv-python pillow adbutils
pip install llama-cpp-python # Gemma 4の推論に使用
llama-cpp-pythonは、Gemma 4をローカルで動かすためのコアライブラリです。
GPU(CUDA)を使いたい場合は、インストール時にCMAKE_ARGS="-DGGML_CUDA=on"といったオプションが必要になります。
私の環境(RTX 4090 2枚挿し)では、量子化されたGemma 4ならレスポンス0.5秒以下で動作します。
⚠️ 落とし穴: Android側で「USBデバッグ」だけでなく「USBデバッグ(セキュリティ設定)」もONにしてください。これを行わないと、ADB経由での「タップ操作」が許可されず、画面を見ることはできても操作できないという状態でハマります。
Step 2: 基本の設定
スマホの画面を取得し、AIが理解できる形式にリサイズして渡す準備をします。
import os
import time
import subprocess
from PIL import Image
import adbutils
class AndroidController:
def __init__(self):
# 接続されているデバイスを自動認識
self.adb = adbutils.adb.device()
self.temp_img = "screen.png"
def get_screenshot(self):
# 高速にスクリーンショットを取得するためにADBコマンドを直接叩く
subprocess.run(["adb", "shell", "screencap", "-p", "/sdcard/screen.png"])
subprocess.run(["adb", "pull", "/sdcard/screen.png", self.temp_img])
# モデルの入力サイズに合わせてリサイズ(Gemma 4の視覚プロンプトに最適化)
with Image.open(self.temp_img) as img:
img = img.resize((448, 448)) # モデルが期待する解像度
img.save("processed.png")
return "processed.png"
def click(self, x, y):
# パーセント指定された座標を実際のピクセル座標に変換
# モデルは0-1000の範囲で座標を返してくることが多い
info = self.adb.window_size()
real_x = int(x * info.width / 1000)
real_y = int(y * info.height / 1000)
self.adb.click(real_x, real_y)
ここで重要なのは、座標を「パーセント(0-1000)」で管理する点です。 スマホによって画面の解像度(1080pや1440pなど)がバラバラなため、AIには常に相対的な座標で思考させ、スクリプト側で実際のピクセルに変換するのが最も汎用性が高くなります。
Step 3: 動かしてみる
次に、Gemma 4(VLM)に対して「今の画面を見て、設定アプリを開いて」といった命令を出すコアロジックを実装します。
from llama_cpp import Llama
from llama_cpp.llama_chat_format import Llava15ChatHandler
# Gemma 4のマルチモーダルモデルをロード
# モデルファイル(GGUF形式)は別途HuggingFace等からダウンロードしておく必要があります
chat_handler = Llava15ChatHandler(clip_model_path="mmproj-model-f16.gguf")
llm = Llama(
model_path="gemma-4-vlm-q4_k_m.gguf",
chat_format="llava-1-5",
chat_handler=chat_handler,
n_ctx=2048,
n_gpu_layers=-1 # 全レイヤーをGPUに載せる
)
def ask_ai(image_path, task):
with open(image_path, "rb") as f:
import base64
base64_image = base64.b64encode(f.read()).decode('utf-8')
response = llm.create_chat_completion(
messages=[
{"role": "system", "content": "You are an Android assistant. Output clicks as [click, x, y]."},
{"role": "user", "content": [
{"type": "text", "text": f"Goal: {task}"},
{"type": "image_url", "image_url": {"url": f"data:image/png;base64,{base64_image}"}}
]}
]
)
return response["choices"][0]["message"]["content"]
# 実行
controller = AndroidController()
img = controller.get_screenshot()
action = ask_ai(img, "設定アプリをタップして")
print(f"AIの判断: {action}")
期待される出力
[click, 250, 480]
モデルが画面内のアイコンを認識し、その座標を返してくれば成功です。 「なぜGGUF形式なのか」と疑問に思うかもしれませんが、これはメモリ消費を抑えつつ民生用GPUやMacのメモリで高速推論するためです。 FP16だとVRAMを32GB以上食うモデルでも、Q4(4ビット量子化)なら8GB〜12GB程度で快適に動きます。
Step 4: 実用レベルにする
単発のクリックだけでは「自動化」とは言えません。 失敗したときにリトライし、目的の画面に到達するまでループさせる構造が必要です。 また、AIが「変な場所」をクリックして無限ループに陥るのを防ぐため、履歴を保持させます。
def autonomous_loop(goal):
history = []
for i in range(10): # 最大10ステップ
img_path = controller.get_screenshot()
# 過去の履歴もプロンプトに含めることで、同じ場所を叩き続けるミスを防ぐ
prompt = f"Goal: {goal}. History: {history}. What is the next step?"
raw_res = ask_ai(img_path, prompt)
# 正規表現などで[click, x, y]を抽出して実行
import re
match = re.search(r"\[click,\s*(\d+),\s*(\d+)\]", raw_res)
if match:
x, y = map(int, match.groups())
controller.click(x, y)
history.append(f"Clicked at {x}, {y}")
print(f"Step {i+1}: Clicking {x}, {y}")
time.sleep(2) # 画面遷移待ち
else:
print("完了、または解析不能")
break
autonomous_loop("Wi-Fiをオフにして")
実務で使うなら、ここに「画面が変わらなかったらスワイプを試す」というフォールバック処理を入れるのがコツです。 私が以前、社内の勤怠管理アプリ(UIが非常に古臭い)の自動化を試した際は、ボタンの認識率が低かったため、特定の色を検出するOpenCVの処理と組み合わせて精度を補完しました。
よくあるトラブルと解決法
| エラー内容 | 原因 | 解決策 |
|---|---|---|
device not found | ADBが端末を認識していない | USBケーブルを交換するか、端末側で「USBデバッグを許可」のポップアップを承認する |
CUDA error | VRAM不足またはドライバ不整合 | n_gpu_layersの値を下げるか、量子化ビット数の低いモデル(Q2_Kなど)を試す |
| 座標がズレる | 画面比率の計算ミス | スクリーンショット取得時の解像度と、モデル入力時の解像度の比率を再確認する |
次のステップ
ここまでできれば、あとは「どんな指示を出すか」というプロンプトエンジニアリングの世界です。 例えば、「インスタグラムを開いて、特定のハッシュタグを検索し、上位3つの投稿にいいねする」といった、従来のツールでは複雑なスクリプトが必要だった動作が、日本語の指示だけで完結します。
次は、スマホの音声を録音してWhisperでテキスト化し、それをGemma 4に渡すことで「声で操作するスマホ」に挑戦してみてください。 また、PokeClawのGitHubリポジトリ(もし公開されていれば)にある最新の微調整(Fine-tuning)済みモデルを試すのも面白いでしょう。 UI操作に特化したモデルは、一般的なチャットモデルよりもはるかに正確に「ボタンの端」ではなく「中心」を捉えてくれます。 自分でサーバーを立てて、複数のAndroid端末を並列で動かす「自律スマホファーム」を構築するのも、エンジニアとしての醍醐味ですね。
よくある質問
Q1: 処理速度(レスポンス)はどのくらいですか?
私のRTX 4090環境では、1アクションの判断に約0.8秒です。M2 MacBook Airでも2〜3秒程度で動きます。リアルタイムのゲーム操作は厳しいですが、設定変更やSNS投稿、フォーム入力といった業務自動化には十分な実用性があります。
Q2: 画面がスクロールしないと見えない要素はどうすればいいですか?
プロンプトに「目的の要素が見当たらない場合は [swipe, 500, 800, 500, 200] を実行してください」と指示を含めるのが定石です。モデルが現在の画面にターゲットがないと判断すれば、自律的にスクロールを行います。
Q3: セキュリティ面で注意すべきことは?
ローカル実行なので外部へのデータ送信はありませんが、ADBを有効にした端末はPC側からのフルアクセスを許容します。信頼できないPCに接続したままにしない、また、自動化スクリプトが意図しない課金ボタンなどを押さないよう、最初は監視下で動かすことを強く推奨します。






