驚いたこと以外も書いちゃってますが、 太字のところをみていただけると
デバイス操作はAIエージェントの時代へ。mobile-mcpを活用したAndroid UI/E2Eテストの挑戦
最初にデモがあった: 楽譜を書けるアプリでカエルの歌をAIが作る。
→ 時間はかかるが現地デモで動いた。
Case1: 実装後のテスト
Case2: バグ調査にAIのデバイス操作を使う。怪しいところにLog.dを入れて監視させたり、実装を切り替えながら試させたりする。
Case3: Assetを作ってくれる。PlayStore向けの画像を作ったりなど
あんまりAIを現状使わないほうが良いかもという領域
- リリース判断に使うのはあんまりかも: 勘違いしてしまうことがある
- 繰り返しのテストに使うのも良くないかも: 遅くて高い
- レイアウトの検証: アラインなど、時間がかかったり見逃したり
- 主観的なUX検証: 主観的なものは難しい。アニメーションなども難しい
(多分人間は必要だろうけどリリース判断に近いところまでできればビジネスインパクト出るからなんとかしたい)
mobile-mcp、android-cli、sim-useなどがある。
Android CLIにレイアウトdiff機能があってトークンが節約できる
LINEヤフーが作っている sim-use トークン効率が良いように作られているそう
LINEヤフーのライブラリはレイアウト情報をtop content bottomなどをわけて見せていて、AIがツールバーなどの情報をいつも見なくて良いように作られている。
コストがかかるので、スクショではなくViewTreeメインでやっている。
Evidenceとしてスクリーンショットを使う。
画面ごとのリファレンスファイルを作って、そのマップを作る。クラス名などのキーワードを入れておいて検索してたどり着けるようにしている。
Debugでpreference書き込めるようなBroadcastReceiverを作っちゃうと楽。
感想: 画面をドキュメント化するのは良さそうなんだけど、これをコードを見れば分かるか、コードから自動生成とかにできないだろうかと気になった。
楽しみながら作るマルチプラットフォームウィンドウマネージャー
Windows XPのWindowを再現するマネージャーを実作するというセッション。
多分このセッションはWindowが提供しなくちゃいけない、いろんなProviderとかComposeのAPIパターンを学ぶというの多いかもしれない。
テーマの実装などで、9patchの仕組みを作って使ったりなど。
ViewModelをサポートするためのコードなどを紹介。
どうやってminimiseをサポートするか?rememberSaveableをサポートするためにrememberSaveableStateHolderを作って提供するだけで基本できる。
Lifecycleのサポート。LifecycleRegistryを使ってフォーカスがあるかどうかで分けたりなど。
出来上がったものの完成度が高く(本当にWindows XPっぽい)面白そうでした。割とAndroidのComposeとかの中身を理解したい人におすすめ
Gradle Managed Devicesに手持ちの端末を持ち込む
狭い範囲の話かと思ったら、物理デバイスをSTFというデバイスを繋いでを自動テストにつなぎ込んで自分でDevice Farm作る手順が紹介されていました。知らない話が多くめちゃ勉強になりました
公式でFirebase Test LabもエミュレーターもGradle Managed Device(GMD)で設定できる。その拡張する実装が使っているAPIを外部から利用して拡張できる。
GMDのAPIは@Incubatingなので変わり得るので注意。
- Device APIをカスタマイズして利用する。
- シャーディングの実現方法
- (テストを分割して複数デバイスで並列化して高速化)
- AndroidJUnitRunnerはシャードの数(例えば4など)とシャードのインデックス(例えば2など)を渡されたらその2の部分のテストだけ走らせてくれる(つまり1デバイスのことしか面倒を見ない)。ShardingFilterでどのデバイスで何を走らせるのかが決まる(テスト名のhashCodeベース)。
- AGPには
numManagedDeviceShardsというフラグがあるが、標準の仮想デバイスでしか使えず、カスタムデバイスでは動かない。 - 複数デバイスに対して一個ずつ指定しても並行で走らせられないので、MyDeviceの代わりにMultipleDevicesみたいなのを作って、Coroutineのasyncとawaitなどを利用し、それぞれでシャードを渡したりして、待ち合わせを行う。テストレポートもAGPが統合してくれる。
- Device farmを作る
shared poolつまり、デバイスを待機しておいて、組織で共有する(開発者と CI パイプラインが同じ端末群を使う)。 One client per deviceなどの必要な性質がある。- Device broker: farmの前にデバイスのリストやデバイスの貸し出しを担当するWebサービス。STFがこれを担う。
- STFのREST APIを使う。GET /devices POST /user/devices serialで借りる。remoteConnectでコネクトURLとかがもらえる。
- MyDeviceなどの実装ではfinallyで返却する、タイムアウトで自動返却など、借りっぱなしにしない工夫が必要。
- STFはauth failedってなってしまう問題があるが、Dockerのstf:latestに署名検証をしないようパッチしたconnect.jsを上書きするとうまく動くそう。
- ADB 通信が暗号化されていないので、STFを外に公開するべきではない。つなぐときはVPNを使おう。
- STFのREST APIを使う。GET /devices POST /user/devices serialで借りる。remoteConnectでコネクトURLとかがもらえる。
- Device broker: farmの前にデバイスのリストやデバイスの貸し出しを担当するWebサービス。STFがこれを担う。
Ask the speaker
Q: これAPI変わったり消されたりしませんかね?
A: Incubatingでfinilizedされてはいないけどそんなに変わってないから大丈夫じゃないかな?
Q: 最後にredroidって出てきたけど、これ何のために必要なんですか?
A: emulator使うためのコンテナ
Q: つまりredroidはdevice farmingとは関係ない。。?
A: そう、関係ない
Q: Device farm作りたかったら、LinuxPC用意して、STF入れて、VPN作って、スマホつなげたら良いってこと?
A: それでいいけど、ローカルのデバイスをSTFにつなげたりもできる。
Android StudioからPSIを盗み出す方法: 大規模コードベースをAIにナビゲートさせる
https://github.com/mercari/kotlin-psi-mcp
これの話っぽい。
- 試した選択肢と、なぜダメだったか
- grep: モデル次第で件数がぶれるし、部分一致や import まで拾ってしまい、トークンも食う。
- Kotlin LSP: 精度は Android Studio と同じだが、裏で headless な IntelliJ がもう1つ立ち上がって重い(find usages だけで 2.6GB)。多言語向けなので import 件数のような Kotlin 固有の情報も出ない。
- JetBrains MCP Server: 50ツールあってもコード解析は4つだけで find usages が無い。AI に IDE を操作させる向けの設計。
- → Android Studio の裏にある PSI を直接 MCP で外に出す Kotlin PSI MCP を自作。
難しいポイント: 正確さ、IDEのバージョンによる挙動の違い、K2のアプデなど
(LSPのダメなポイントもわかるけど、最近はIDE使わない頻度が増えているので、IDE起動してないといけない依存がやっぱり気になる。うまくできれば良いんだけども。。)
Ask the speaker
ということで、Ask the speakerに聞きに行った
まあやっぱり必要だって言うことだった。ただメモリなどのトレードオフがあるので理解はできる感じだった。
行政アプリ全画面TalkBack対応を、デザイナー協業とAIエージェントで自動化していく実体験
AIエージェントで継続的にTalkBack対応を行っている。
TalkBackの読み上げ内容の管理はFigmaを使っている。
TalkBackをまず共通コンポーネントに対応した。
Figma MCP:
Figma MCPで深いレイヤーの探索がタイムアウトして止まる問題があり、これを何とかするコツとして先に探索するレイヤーの最大深さを指定して、それで取得する
FigmaMCPでレイヤーにannotationを付ける機能がなかったので、Figma pluginとブリッジサーバーを自作して、それと繋いでアノテーションを付けられるようにした。
実装:
Composeでsemantics{paneTitle=}でどの画面にいるか
Composeでsemantics{liveRegion=}で未読件数が分かったタイミングで読み上げるとかができる。
clearAndSetSemanticsを使うと子のアクセシビリティ情報を消して、新しく指定した情報だけで上書きする。
確認:
Component単位で検証用のアプリを作って、確認できるように。
Nav2、Nav3 ... はたまた自作? 〜 作って理解する Nav3 の設計意図 〜
セッションのコンセプトとしては、まずNavigationを自作して、問題を解決していって、その解決策とNav3を比較するというものでした。
で、戻るボタン -> MutableStateList (Nav3も)
画面回転 -> rememberSaveable (Nav3も)
プロセス死 -> rememberSaveable + KotlinX Serialization (Nav3も)
バックスタックの検索ボックスが消えてしまう -> SaveableStateProviderを使う
(ちょっとこれ昨日のJetBrainsの方のWindow Managerセッションに近いかも。ViewModelが使えるとかSavedStateとか。)
Nav3はこれをDecoratorパターンでラップする形で実現
ViewModel -> ViewModelStoreOwnerなど(2.11で自作が楽になったらしい)
デバイスファクター(list detailなど) -> 自作Nav3共にSceneStrategyというのを使って、画面側にメタデータを持ってListかDetailかみたいな情報を持たせてうまくやる
マルチモジュールの問題 ->
- 問題
- プロセス復帰などで画面遷移を保持する必要がある = Jsonなどにしておく必要がある
- Jsonから復元できないといけない。例えば
{ "type": "MemoListRoute" }などからインスタンスが作れる必要がある - KotlinX serializationはsealed interfaceなどからこの
when(type){ "MemoListRoute" -> MemoListRoute() }のようなものを自動生成し、それを使ってJsonからインスタンスを作る - マルチモジュールではモジュールをまたぐので、sealed interfaceにできないので、上記のwhen文のようなものがつくられず、インスタンス化ができない
- 対応方法
- JVM KSerializerの自作
- 保存時にクラス名を保存
- 復元時はクラス名からJVMのリフレクションで、クラスに対応するシリアライザを取得して、インスタンスを作る
- → 配線が必要ないが、リフレクションが使えるJVMでしか動かない。
- SerializersModuleで集める
- クラスとシリアライザの関係を自分で書いておく
- KMPでも動く
- (多分DIでIntoMapとかでなんとかする方法もあるかもしれない。MetroやDagger(現状KMP非対応)など)
- JVM KSerializerの自作
高パフォーマンスで表現力豊かなRemote UI: RemoteComposeの深掘り
- 目的: UIをアプリのプロセス外に出したいシーンがたくさんある(ウィジェット、通知、サーバードリブンUIなど)。そこでもリッチなUIを出したい。
- 解決したい問題: 今はRemoteViews、通知API、SurfaceControlViewHostなど用途ごとに別々のAPIで、それぞれ表現力かアプリ常駐かの制約がある。表示先も増えて辛い。
- 考え方: UIをドキュメントにする。1つのドキュメントをさまざまな場所のPlayerで再生できる。
- ドキュメントの形式: バイナリ形式。小さい(ウィジェット1個で4KB)。
例えば、RemoteComposeを使うとフラッピーバードっぽいのがウィジェットで動くみたいなのが実現できる。

小さい + サーバーとの通信を最低限で良いようにしている
で、ドキュメントはどういう感じか?opcodeの列でループや関数として呼び出したりなどができる。
Specificationがあったり
https://camaelon.github.io/remotecompose-experiments/RemoteComposeSpec/

JSONはAIから変更できて、普通に変更がうまくできるっていうデモがあった。
DroidKaigi Timetable 42KBになって、普通にフィルターとか動く

Ask the speaker
- iOSでも動く。 C++のユニバーサルプレイヤー(描画はSkia)をSwiftUIで包む形。サイズは最近測っていないそうだが、Skiaを使わないWebプレイヤーで300〜400KBくらい。Compose MultiplatformならSkiaが二重にならず、GitHubにCompose向けのプレイヤーもある。
- InspectorにMCPサーバーがある。 LLMにInspectorのツールを使わせてドキュメントを解析させ、レポートを出させたりしているそう。
- プレイヤーの中身はComposeではない。 名前に反して、高レベルの概念を似せているだけ。ただ今、ドキュメントから本物のComposeツリーを合成する新しいComposeプレイヤーを作っていて、それが入ればアクセシビリティ含めてComposeとして一番良い形になるはず、とのこと。
- サーバードリブンUIならライブラリ側のプレイヤーを使うべき。 最近のAndroidならプラットフォーム側にプレイヤーが入っていて、ウィジェットにも通知にもRemoteComposeを送れる。ただしそれはOSに入っているものをそのまま使うということ。バージョンとプロファイルの概念があって古いドキュメントも新しいドキュメントも動くようにはしているが、自分でバージョンを握りたいならライブラリ側。
- alphaなのは技術的な理由ではなく手続き上の理由で、年内にはbetaになる見込みだそう(これは他の人の質問)。
後から調べたこと
プラットフォーム側のプレイヤーが入ったのはAndroid 15から。
https://developer.android.com/reference/android/widget/RemoteViews.DrawInstructions
RemoteViewsに描画命令が入っていると、レイアウトを組み立てる代わりにRemoteComposeのプレイヤーを作ってそれを返している。Android 14のソースにはこのプレイヤーが無い。
https://cs.android.com/android/platform/superproject/+/android-latest-release:frameworks/base/core/java/android/widget/RemoteViews.java;l=8612-8615;drc=6ca8ebb6b91ad2bae4e36812e74bc7687a722fb0
Android StudioからSlackへと移行した方法
Slackでメンションすると、エージェントが修正・検証までしてPRを出してくれる仕組み(Phantom)を作って運用しているという話。QAなどが直接お願いして、開発者はレビューだけする形。
使われ方が質問が多かったりなどかなり数字から話してくれていて分かりやすかったです。
人間が後から直す必要があるものも結構あったそう。
Dockerでジョブごとに使い捨てのコンテナを作ってAgent(Claude Code SDK)を動かしている。コンテナにはSlackのトークンや鍵を渡さず、それらはAIではない決定的なJavaScriptのオーケストレーターだけが持つ。Agentは「ステータス更新・Slackへの投稿・PR作成」をMCPサーバー経由でオーケストレーターに頼み、実際の操作はオーケストレーターが行う。
オーケストレーターでどこからでも起動できるようにして汎用化。
Ask the speaker
Q: Slackからオーケストレーターってどう起動してる?何か特別な仕組みがある?
A: 普通のSlack bot。Slack側のサーバーに繋いでいるだけ。
他の人の質問で、モデルはSonnetを使っていてコストが低いのはそのため。Opusに変えても結果はほとんど変わらなかったそう(対象が小さいバグに絞られているから)。課金はサブスクリプションではなくAPI。ClaudeをGitHubに直接繋ぐこともできるが、その環境ではテストが走らせられず検証ができないので、自前のマシンでDockerとテストを含めて動かしているとのこと。
動画配信アプリでの Engage SDK 導入 — TVer Android が Play ストアにコンテンツを届けるまで
Engage SDKは今Preview
アプリ外でコンテンツそのものを訴求できる手段の一つ。
-
出てくる場所
導入するとPlayストアのアプリ、ウィジェットなどとエンターテイメントスペース。
プレイストアの中で探しているときにアプリが目に入る形になる。
プレイストア長押し -> ウィジェットで、コレクションっていうのが出てきてアプリ内のコンテンツが出てきたりする -
使うには?
ライブラリは50KBぐらい、開発は1週間程度。申請フォームがあって申請することで使うことができる。サンプルアプリを見て理解する。 -
SDKのメソッドを使うタイミング
アプリ任意のタイミング + Engage ServiceからIntentを受け取ったタイミング。任意はいつか?24時間ごとに1回程度が推奨。 -
内容について
- クラスターというのでRecommendationなどいくつかのコンテンツリストを設定する。色んなクラスターで設定したほうがユーザーの接触面が増えるのでおすすめだそう。
- PublishStatusでアプリが正常にpublishできているか、想定内で送っていないだけか、エラーなのかを設定する。
-
情報を送るだけなので割と簡単にできる
-
デバッグについて
- 専用検証アプリがある。
- 検証apkをインストールし、そのアプリでパッケージ名を入れるとアプリがpublishしたクラスターやエンティティの情報が出る。アプリ内のエラーがないかをそれで見ていく。
- 検証アプリではEngage ServiceからのIntent受信を検証するbroadcastも送れる。
-
終わったら
- Googleにメールで知らせるとPlayストアで掲載されたりする
-
注意点
- アプリ内でロールアウト設定を行えるようにしておくと良いかも
- Googleからレビューをしてもらうのをはやめに?
- 画像サイズは正確である必要がある(エラーになる)
- Intentを受け取ったら即時publishした方が良い。
-
EngageSDKリリース後
- Google からレポートが毎週届く
- インプレッション、CTRが見られる
- 安定してインプレッションがある
- Google からレポートが毎週届く
-
Engage SDKを導入するためのAndroidスキルが最近公開されたので、それを使うとより早く実装できそう
UI仕様を「見えるもの」にする 〜 Compose Screenshot Testing とギャラリーで支える、AIエージェント時代のAndroid UI開発 〜
自分はRoborazziの開発者ではあるので、割とメモ飛ばしちゃってるので見たほうが良いと思います。
ASのPreviewとの差分を揃えるためにCSTにした
確かにRoborazziだと違いは出ると思う。
内部的にはどっちも確か最終的には同じAndroidのFrameworkのバイナリがあってそこで描画されているので一緒ではあるんですが、ASのPreviewとの近さはCompose Screenshot Testingが高いというのはありそう。(元々Roborazziのほうが画像を生成し始めたのは先なので違いがあったりもして、若干最近この違いと戦ったりしている)
手元のMacとLinuxで差が出る。これCSTもそうなのか(Robolectricもそう)
DockerでLinux x86環境を持ってきて使っている
遅いのでは? -> warmなら23秒で回るそう。
コンポーネントカタログ、この画面のこの状態。みたいなのをURLで直接指定できるようにしているのはコミュニケーションはかどりそう。
開発ループの高速化:Android StudioとAndroid CLIにおけるエージェントワークフローの探求
(ちょっと自分は割と全部知ってるかもしれん)
GooglerのセッションでClaude Codeがでてきてびっくりした。(Android CLIとSkillでCCからも使えるよっていうことだと思う。「any agent of your choice」がAndroid CLIのミッションとのこと。)
Journeysでテーマの変更をチェックするデモがあった。Claudeにhtmlレポート作ってもらったりしていた。
Android StudioのModel ProviderにClaudeが追加されている。
App Quality Insightsの確認でクラッシュの確認、Android Device Streaming、がAndroid CLIでできるように。 Claudeにバグ再現から修正まで行わせるデモがあった。
Play Policy Insights
https://github.com/android/skills/tree/main/play/play-policy-insights
マルチエージェントを使うフローになっているそう。
チェックしてクリティカルとか出してくれる。
Android Studio から Google Play へ publish できますが、送れるのは internal test track だけ。うっかり本番に出さないためだそう。
立ち話
立ち話1
DroidKaigiのアプリについて、きたっくんさんに聞きました。
なぜDetektやKtLintではなくコンパイラプラグインにしたんですか?シフトレフトのような狙いですか?
→ AIエージェントはlintとか走らせないことがあるし、速いっていうのがある。
今年はデザインもやったと聞きましたが、Figmaを直接操作したんですか?
→ Figma MCPでウェブサイトを見せながらやった。
結構DroidKaigiのアプリは実装が先に進んだり、デザインが先に進んだりしているみたいで、将来はどっちがシングルソースになるんだろうねぇ、という話をしました。
立ち話2
HotSwanなど、たくさんOSSを作られている方とランチ。
iOS(Kotlin/Native)ではどうやってHot Reloadを実現しているんですか?
→ コンパイル時にそのためのものを色々入れたりしているみたいな話。
(最近のRoborazziの話やMaven Centralの有料化の話など。。)
立ち話3
(他社ブースで)
E2Eテストはどうしていますか?
→ Emulatorでテスト自動化してる。
サーバーはどうしていますか?
→ Fixtureで固定してる。
それで自信を持ってリリースできていますか?
→ いい質問ですね。
まとめ
ちょっとだいぶDroidKaigiから時間経ってしまいましたが、書きました。
全体としては、AIエージェントにAndroidの端末やIDEを触らせて、自分で確認させる話がとても多かったです。mobile-mcpやAndroid CLIでの端末操作、PSIのMCP、SlackのPhantomの検証ループ、Screenshot Testingの画像など、どれも「エージェントが自分の変更を確かめられるようにする」方向でした。
その中でRemoteComposeのセッションは一番面白かったし可能性を感じました。A2UIなどに比べてできることが多い印象で、しかもサイズを小さくでき、仕様が公開されているのでAndroidに限定されずに使えそうです。サーバードリブンUIや、Agentに出力させて使うなど、いろいろな使い道がありそうです。




