モバイルアプリの操作を自動化したいけれど、「ボタンや入力欄をどう指定すればいいの?」と迷ったことはありませんか。
Appiumを使ってネイティブアプリを操作するには、画面の要素を正しく特定することが欠かせません。
そのための基本が「ui.xml」を取得して要素の属性を読み解く方法です。
この記事では、Android端末からui.xmlを取り出して要素を特定する手順と、アプリのパッケージ名やアクティビティ名の調べ方を初心者向けに丁寧に解説します。
これを理解すれば、Appiumでのネイティブアプリ操作の第一歩を安心して踏み出せるはずです。
前提とゴール
対象はWindows環境でAndroid端末を操作するケースです。
ADBが使える状態で、端末はUSBデバッグがオンになっている前提です。
ゴールは、ui.xmlを取得して要素属性を読み取り、実戦的なロケータを設計できるようになることです。
Appiumにおける「要素」とは
テストコードから操作する一つひとつのUI部品のことです。
ボタンや入力欄、テキストなどを指します。
Appiumは画面のUI階層を解析して「要素」を見つけ、タップや入力などの操作を実行します。
ui.xmlとは
端末上の現在表示中の画面を、ツリー構造で表現したXMLです。
各ノードがUI部品を表し、resource-id
、content-desc
、text
、class
、bounds
、package
などの属性を持ちます。
この属性を手がかりにロケータを設計します。
ui.xmlの取り方
1.端末を認識させる
adb devices
device
と表示されれば接続OKです。
2.調査したいアプリ画面を端末で表示する
調べたい画面を開いた状態にしておきます。
3.UIツリーをダンプしてPCへ取得する
adb shell uiautomator dump /sdcard/ui.xml
adb pull /sdcard/ui.xml .
プロジェクト直下に ui.xml
が取得できれば成功です。
もし ERROR: null object
などが出たら、画面が点灯しているか、管理者権限の制限がないかを確認します。
4.XMLをエディタで開く
VS Codeやお好みのエディタで ui.xml
を開きます。
ノードを上から追い、該当コンポーネントの属性を読み取ります。
ui.xmlの読み方とロケータ設計
XML内の <node .../>
が一つのUI部品を表します。
特に以下の属性を優先して使います。
resource-id
。
例:com.example.app:id/loginButton
。
最も安定しやすいIDで、基本はこれを第一候補にします。content-desc
。
アクセシビリティ用の説明文です。
Androidでは「アクセシビリティID」として取得できます。text
。
表示文字列です。
多言語で変わる可能性があるため、多用は避けます。class
。
例:android.widget.Button
。
型の絞り込みに使います。package
。
その要素が属するアプリのパッケージ名です。
画面混在時の切り分けに役立ちます。
Pythonでの指定例
from appium.webdriver.common.appiumby import AppiumBy
# resource-idを使う例
driver.find_element(AppiumBy.ID, "com.example.app:id/loginButton")
# content-descを使う例
driver.find_element(AppiumBy.ACCESSIBILITY_ID, "ログイン")
# やむを得ずXPathで指定する例(安定性は要注意)
driver.find_element(AppiumBy.XPATH, "//android.widget.Button[@text='ログイン']")
IDやアクセシビリティIDを最優先にし、XPathは最後の手段にするのが実務の定石です。
パッケージ名とアクティビティ名の取得
これは何に使うのか
appPackage
と appActivity
はAppiumが起動時にどのアプリのどの画面から開始するかを指定するための情報です。
パッケージ名はアプリの一意識別子で、アクティビティ名はアプリ内の画面を表すエントリポイントです。
この二つがわかると、Appiumからアプリをダイレクトに立ち上げられます。
今表示中のアプリから取得する方法
アプリを前面に出した状態で以下を実行します。
adb shell dumpsys window | findstr mCurrentFocus
出力例。
mCurrentFocus=Window{... u0 com.example.app/com.example.MainActivity}
com.example.app
がパッケージ名で、com.example.MainActivity
がアクティビティ名です。
機種やOSによっては次のコマンドの方が確実です。
adb shell dumpsys activity | findstr mResumedActivity
または。
adb shell dumpsys activity activities | findstr Resumed
APKから取得する方法(APKが手元にある場合)
aapt dump badging app-debug.apk | findstr package
aapt dump badging app-debug.apk | findstr launchable-activity
package
と launchable-activity
の行から読み取れます。aapt
はAndroid SDKのビルドツールに含まれます。
Appiumの起動指定例(参考)
appPackage
と appActivity
を使ってアプリを起動します。
from appium import webdriver
from appium.options.android import UiAutomator2Options
caps = {
"platformName": "Android",
"appium:automationName": "UiAutomator2",
"appium:deviceName": "Android Emulator",
"appium:appPackage": "com.example.app",
"appium:appActivity": "com.example.MainActivity",
"appium:noReset": True
}
options = UiAutomator2Options().load_capabilities(caps)
driver = webdriver.Remote("http://127.0.0.1:4723", options=options)
起動後に ui.xml
を更新して再取得すれば、目的要素の属性が最新状態で確認できます。
うまくいかない時のチェックリスト
adb devices
にdevice
が出ていない。
ケーブルやドライバを確認し、adb kill-server && adb start-server
を試します。uiautomator dump
が失敗する。
画面が消灯していないかを確認し、パスに/sdcard/
を含めて再実行します。- ui.xml内に目当ての要素が見当たらない。
WebView内の可能性があります。
その場合はChrome DevToolsでの要素確認や、コンテキスト切り替えの検討が必要です。 - XMLの
text
でロケータを組んだら他言語で落ちる。resource-id
やcontent-desc
を優先し、文字列依存を避けます。
まとめ
要素特定はui.xmlで属性を読むところから始まります。resource-id
と content-desc
を最優先にして、安定したロケータを作ります。
パッケージ名とアクティビティ名を押さえれば、Appiumから狙いどおりにアプリを起動できます。