Android TV のアプリケーションをリモート操作する (Apptium 2)

# はじめに

Android TV OS上で動作するブラウザアプリケーションをリモート操作する方法を調査した。
Seleniumを利用してPC上のChromeを自動操作していた。同等の自動操作をAndroid上のブラウザアプリケーションに対しても実現したい。

## 調査結果
- Seleniumの[AndroidDriver](https://oscasierra.net/2012/07/androiddriver/)は[ディスコン](https://iti.hatenablog.jp/entry/2014/07/04/095612)
- Selenium AndroidDriverの代わりに[appiumを使うべし](https://www.selenium.dev/documentation/legacy/selenium_2/mobile/)
- appiumは[2.xが最新](https://appium.io/docs/en/2.1/guides/migrating-1-to-2/)

世の中には AndroidDriver や appium 1.x系のドキュメントが溢れている。appium2を明示して検索しないと欲しい情報にたどり着かない。

# リモート操作方法

## Appium2のインストール
```terminal
$ npm i --location=global appium
$ pip install Appium-Python-Client
$ appium driver install uiautomator2
```

- appium のインストール: https://appium.io/docs/en/2.1/quickstart/install/
- python 用インストール: https://appium.io/docs/en/2.1/quickstart/test-py/
- Android操作ドライバインストール: https://appium.io/docs/en/2.1/quickstart/uiauto2-driver/

## Aappium2のテスト

https://appium.io/docs/en/2.1/quickstart/test-py/

エラーが発生する場合は[下記を参照](#テストプログラムの問題)

## Appium2でウェブブラウザを起動するサンプルプログラム
AndroidTVで動作するChrome互換ブラウザをリモート操作して`https://www.google.com`を表示させる

```python:remote_android.py
from appium import webdriver
from appium.options.android import UiAutomator2Options
import time

class RemoteTest:
	capabilities = dict(
		platformName='Android',
		automationName='UiAutomator2',
		deviceName='ADT-3',
		appPackage='<your browser application package name>',
		appActivity='<your application activity>',
		language='en',
		locale='US',
		noReset=True,#Falseだとインストール直後の初期状態にリセットされる
	)
	appium_server_url = 'http://localhost:4723'

	def __init__(self):
		capabilities_options = UiAutomator2Options().load_capabilities(self.capabilities)
		self.driver = webdriver.Remote(command_executor=self.appium_server_url, options=capabilities_options)

	def __del__(self):
		if self.driver:
			self.driver.quit()

	def start(self):
		self.driver.get("https://www.google.com")
		time.sleep(10)

if __name__ == '__main__':
	test = RemoteTest()
	test.start()
```

## 動作結果

Android TV を[ホストPC(Mac)に接続する](https://qiita.com/hamup/items/d0757af393a5462b686a)
```terminal:
$ adb connect <IP ADDRESS>:5555
```

```terminal: Macの場合
$ export ANDROID_HOME=${HOME}/Library/Android/sdk
$ appium
```
```terminal: 
$ python3 ./remote_android.py
```

![b.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1017489/6b1a2ebd-5678-2b5d-2051-3d63824801c7.gif)


# 知っておくと便利なこと

## パッケージ名一覧
adb shell pm list packages

https://maku77.github.io/p/ghtgxgw/

## Activityを調べる
- 実際にアプリを起動させてActivityを表示する
- ログで filter を cmp=<アプリのパッケージ名> で検索
- Activity名がわかる
![スクリーンショット 2023-10-09 21.38.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1017489/fa5afe77-0044-51c8-90ba-a736f73444ab.png)


# 解決に時間を要した内容

## appium2 から /wd/hub は必要なくなった
appium だけで起動すれば良い [`--base-path /wd/hub` などの指定は必要はない](https://appium.io/docs/ja/2.1/guides/migrating-1-to-2/)

```terminal: 
$ appium
```

`command_executor=`の指定でも [`http://localhost:4723/wd/hub` などの指定は必要なし](https://appium.io/docs/ja/2.1/guides/migrating-1-to-2/)

```python: dummy program
appium_server_url = 'http://localhost:4723'
self.driver = webdriver.Remote(command_executor=self.appium_server_url, options=capabilities_options)
```

## 環境変数ANDROID_HOMEの設定
appiumサーバーを動作させるシェルで環境変数`ANDROID_HOME`を設定する。
ANDROID_HOMEが未設定だとpythonプログラムとappiumサーバーの両方にログにエラーが表示される。appiumのシェルが裏に回っていたため、pythonプログラムのエラーログだけ気が付き、pythonプログラムを実行するシェルではANDROID_HOMEが設定されているはずなのに... と悩む羽目になった。

https://appium.io/docs/en/2.1/quickstart/uiauto2-driver/#set-up-android-automation-requirements

## テストプログラムの問題
Official site の [test.py](http://appium.io/docs/en/2.1/quickstart/test-py/) で発生する不具合対策
```terminal
AttributeError: 'NoneType' object has no attribute 'to_capabilities'　
```
Import Appium UiAutomator2 driver for Android platforms (AppiumOptions)
`from appium.options.android import UiAutomator2Options`
https://stackoverflow.com/questions/77118636/attributeerror-nonetype-object-has-no-attribute-to-capabilities-getting-th