Celeste Engineer

Androidとか自転車とか

dex.fm: Hacks in Drivemode というお題でポッドキャストにゲスト参加しました

dex.fm という Android をテーマにしたポッドキャストにゲスト参加し、会社のプロダクトで培われている技術について話をしました。

http://dex.fm/post/151298631133/10-hacks-in-drivemode
dex.fm

今回の話題は、WindowManager に View を書くということと、それに関連したアプリケーションのフレームワーク、省メモリ・省電力、プロセス間通信や複雑なモデルの構成、状態遷移についてです。

いくつか、補足として書いておきたいことがあったのでブログの記事にしておきます。

TransactionTooLargeException

AIDL などプロセス間通信を多用する際にはお目にかかる場面も出てくる例外です。その Javadoc によると、プロセス間通信で使用できるメモリは 1Mb と定められているようです。 この 1Mb というのは、一回の通信で使用できるメモリの上限ではなく、アプリケーションのプロセス全体に割り当てられる、全プロセス間通信で使用できるメモリの上限ということがポイントで、一回のプロセス間通信で巨大なデータをやり取りした場合だけでなく、小さなデータをやり取りする複数のプロセス間通信をドカッと一気にやったりした場合でも、小さなデータの総量が 1Mb を超えたら例外が飛んできます。

プロセス間通信でデータの交換に使う仕組みといえば Parcel です。Intent や Bundle のような、特段プロセス間通信ということを意識しない場所でも使われる Parcel ですので、Intent や Bundle に巨大なデータを詰めて他のアプリに送りつけるということをした場合でもやはり、TransactionTooLargeException が飛びますし、PackageManager でいろんなデータをクエリするときにもやはりデータ量が多すぎると例外が飛んでくるので、アプリの機能がそこそこ豊富になってくると見かけるようになると思います。

このような背景があるため、特に画像データの交換に関しては、出来得る限り Uri など文字情報になおして提供することが推奨となるわけです。

ちなみに、ポッドキャストでは Cursor にも言及しましたが、Cursor に関しては CursorWindowAllocationException というのが別にあるようで、TransactionTooLargeException とは違うものでした。いずれにせよ、あまり巨大なデータを持たせることはお行儀が良くないので、クエリの方法を変えるなどの対策が必要です。

Android Auto

音楽系のアプリがシステムと連携して、ロックスクリーンに再生コントロールを表示したり、アルバムアートを表示したり…ということを実現する API は、Android Auto の登場で随分スッキリと整理され、かつシステムとの連携だけにとどまらない汎用的なフレームワークになりました。どんな API になっているかについては、TechBooster から出ている「アンドロイドアカデミア」に詳しく書いてありますが、Android Auto に至るまでにもいくらかの変遷があります。

もともとは、ICS で導入された RemoteControlClient が最初に登場した音楽系アプリ向けの API です。実態としては、AIDL に基づいてロックスクリーンと音楽系アプリが連携するためにしくみになっています。音楽系アプリが RemoteControlClient を使って再生コントロールの状況や楽曲情報をロックスクリーンに渡すと、ロックスクリーンがいい感じに表示を更新してくれます。

その後 RemoteController という別のクラスが Kitkat で導入されました。これを使うのはシステムや音楽系アプリと連携したい他のアプリです。このクラスが登場するまでは、 RemoteControlClient が内部でやり取りしていた AIDL をパクって借りて来る必要があったのですが(ちなみにこの AIDL を借りてくる話は TechBooster から出ている「AZ異本」に詳しく書きました)、RemoteController を使えばそれをすることなく簡単に音楽系アプリと連携が取れるようになります。ただし少し癖があり、NotificationListenerService で使わないと動かないようです。

簡単にできるといいつつも微妙に使いづらかったり、Android Auto の仕組み上 Android システムではないアプリとの連携が必要な点(Android Auto は "Android Auto" という名前のアプリが中心になっている)があったりした上で、Android Auto の音楽系アプリ向けの API は整備されたんだなぁということが伺えます。 ポッドキャストでも言及したとおり、サポートライブラリにバックポートされているので、使おうと思えばこの仕組を ICS や JB などでも使うことができます。もちろん、音楽系アプリと連携したいアプリの両方が対応しないとダメなんですが。

ちなみに、NotificationListenerService が動いている最中に例外をはいて死ぬと、NotificationListenerService が復活しなくて(==システムの再バインドが走らなくなって)次に端末を再起動するまで通知が受け取れない、という事が稀によくあります。