LoginSignup
28
29

More than 5 years have passed since last update.

RemoteViews から様々な情報を読み取る

Last updated at Posted at 2015-05-26

RemoteViews の内部構造

AppWidget や Notification のカスタム View に用いられる RemoteViews は、実際のところ View そのものは内包しておらず、View に関する情報(レイアウトのリソース ID やホストアプリケーションの情報など)と、View の操作を説明する情報を保持しています。

たとえば、RemoteViews を使って TextView に文字列をセットする場合、内部では、「setTextを指定された引数で呼び出す」という情報が RemoteViews の中に記録されます。この操作に関する情報はリスト形式ですべて RemoteViews の中に記録されており、RemoteViews#apply()を呼び出すことでそれらが実行され、View が展開されるという仕組みになっています。

RemoteViews でのイベントハンドリングではPendingIntentを使います。Viewのクリックに反応してPendingIntentに指定したIntentが発行されるようになっています。

RemoteViews を活用する

これらを用いることで、他のアプリが今何をしているのか、ヒントを掴むことができるようになります。

ではどのようにそれらの情報を読み取るのかというと、公開された API は存在しないので、リフレクションで読むことになります。

RemoteViewsmActionsには、操作の記録が残ります。リストに含められる情報はすべてParcelableで、RemoteViews.Actionクラスを継承しています。操作の種類によって実際の具象クラスは異なりますが、概ねどのクラスであっても、どの View に対する操作かを明示するためのリソース ID が入ります。その他、リフレクションでメソッドを呼び出すのに必要な情報を持つクラスがあったり、Drawable のリソース ID を保持するクラスがあったりします。中には、RemoteViews をネストするものがあり、そこからさらに RemoteViews に対するアクションが記録されている、というようなものもあります。

このあたりはRemoteViewsを眺めているとひと通り把握できます。

ここまでの情報で何を読み取るかは、したいこととアプリケーションの動きに依存します。ぜひ色々ログに吐き出したり、デバッガをアタッチして中を覗いてみたりすると良いでしょう。

余談:PendingIntent も活用してしまう

PendingIntent もリフレクションを使うことでより多くの情報を得ることが出来ます。@hideな API で、PendingIntent から発行される実際の Intent を取り出すメソッドが定義されているので、リフレクションでそのメソッドを呼び出し Intent が得て、いろいろ読み取ることができますね。

他のアプリの情報を読み取る、という点では、AccessibilityService が良く用いられますが、AppWidget や Notification に関して言えば、RemoteViews から読み取るというのも一つの手段です。

という訳で、こういう闇のコードを書く人も居るので、PendingIntent だからといって Intent 情報が読み取れないとたかをくくるのは危険です。気を付けましょう。

さいごに

情報を読み出すコードが、リフレクションや Parcel から read するのばかりで、可読性とメンテナンス性が第三象限の方まで振り切っているので、まあなんかそのあたりを手伝ってくれる良い子のライブラリを書きました。

28
29
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
28
29