【Android】IntentとIntent Filterの使い方

AndroidManifest.xmlIntent Filterを設定しておくと、暗黙的Intentを受信することが出来ます。

IntentはAndroidアプリの根幹に関わる仕組みなので、ちょっと検索すればすぐに豊富な資料を見つけることが出来るんですが、「実際にどうやって書くのか?」となると結構色んな資料を見なくてはいけないので、一つにまとめたいと思います。

暗黙的IntentとIntent Filterの仕組み

Intentには遷移するクラスを指定した明示的Intentと、「こう言う処理がしたいんだけど、誰かできる?」と問い合わせてみる暗黙的Intentがあります。

暗黙的Intentを発行するにはString actionを受け取るコンストラクタを使うか、Intent#setAction(String action)を使用する必要があります。

また、その暗黙的Intentで処理してもらいたいデータはUriとして渡すことが出来ます。

// 電話をかけられるアプリに電話番号を渡す
Intent i = new Intent(Intent.ACTION_DIAL, Uri.parse("tel:08099999999"));

//Intent i = new Intent();
//i.setAction(Intent.ACTION_CALL);
//i.setData(Uri.parse("tel:08099999999"));

startActivity(i);

上記のコードが実行されると、AndroidManifest.xmlに以下の記述があるアプリを探してきます。

<intent-filter>
  <action android:name="android.intent.action.DIAL" />
  <category android:name="android.intent.category.DEFAULT" />
</intent-filter>

必ずしも上記の通り、と言うわけではありません。<category>の値が違ったり、<data>が設定されているかもしれません。が、IntentにはACTION_DIALしか指定されていないので、とりあえずそれがあるものを探してきます。

該当するアプリが複数あればユーザにどれを使うか訊いてきます。選択されたアプリ(受信側)はActivity#getIntent()で送られてきたIntentを取得し、Intent#getData()Uriを取得し、Uriメソッド(電話番号だとUri#getSchemeSpecificPart()あたりかな?)でデータを抽出するわけです。

この仕組みを使うことで、処理を丸ごと別アプリに委譲したり、逆に別アプリからのデータを受け取って処理することが出来ます。また、独自のactionやcategoryを規定することでアプリのプラグインなどを容易に作成することも出来ます。

<intent-filter>に設定できる属性

ドキュメントを読む限り、AndroidManifestの<intent-filter>に設定できるAttributeは以下の三つみたいです。

何らかのアプリで暗黙的Intentが送信されると、「それ、ウチで処理できますよ」と手を挙げるアプリが一覧として表示されるわけですが、その時にどう表示するかを設定できるっぽいですね。

直接数値を設定するpriority以外はきちんとリソースを用意しておく必要があります。設定しないとapplicationの値を自動で継承してくれます。

ちなみにandroid:priorityですが、Activityに設定しても意味がないとのことです。なんてこったい。

<action>の設定

<intent-filter>に必須の子要素として、<action>があります。これはactionの名称(name)を指定してあげればOKです。

じゃあ指定できるactionってなに?となるんですが、結論から言えば、なんでもいいです。暗黙的Intentの送信側とIntent Filterが設定されている受信側で値が一致していれば、自動で受け取ってくれます。

とは言え、流石にそれだと使いにくすぎるので、Intentクラス内に定数としてよく使われるactionが定義されています。

Intentのドキュメント内で「Standard Activity Actions」と検索すればその一覧が出てくるので、それっぽいものを選びましょう。

また、設定する文字列はConstant Valueと言う形で書いてあります。例えばIntent#ACTION_CALLならandroid.intent.action.CALLです。

<category>の設定

actionとは別にcategoryを設定することが出来ます。actionよりもうちょっと具体性のある、「こう言う機能を持ったアプリにIntentを渡したい」と言う指示を出すことができます。

一覧を見たい場合はIntentのドキュメント内で「Standard Categories」と検索しましょう。Intent#CATEGORY_BROWSABLEあたりを見ておけば何となくイメージもつかみやすいんじゃないでしょうか。

送信側はIntent#addCategory(String category)メソッドで設定することが出来ます。

受信側は指定したいcategoryがなくてもDEFAULT_CATEGORYを指定しておかないと暗黙的Intentを受け取れないらしいです。

また、categoryもactionと同様に自分で定義したものを使用することが出来ます。

<data>の設定

dataを指定すると、Intentと一緒に渡されるUriレベルでフィルタリングすることが出来ます。

指定できる属性は以下の通りです。

scheme、host、portに関しては特に説明しなくてもいいでしょう。ただ、schemeが指定されていないのにhostを指定しても効果がないとか、そう言うのがあるとのことなのでドキュメントはちゃんと読んでおきましょうね。

mimeTypeもそのままの意味です。送られてくるデータの型でフィルタリングすることが出来ます。

pathはちょっと複雑ですが、pathを指定したときは完全一致、pathPrefixを指定したときは前方一致、pathPatternではワイルドカードを指定できます。

これらの値は基本的にUriクラスから取得することになるんですが、MIME-TypeだけはIntentクラスから設定/取得することになります。UriとMIME-Typeを同時に設定するメソッドも用意されているので、上手く活用しましょう。

まとめ

恐ろしくざっくりとした記事ですが、Intent Filterで厄介なのは「どのActionやCategoryをセットすればいいのか」と「どう言うUriを作成すればいいのか」と「Uriからどうやって値を取得したらいいのか」の三つで、その辺を全部すっ飛ばしてるからです。

とは言えこの辺すらわかってないと設計すら出来ないので、とりあえず一旦まとめておきました。

[2014/06/09追記]

[Android]Intentで渡すためのUriを作成すると言う続きのようなものを書きました。

[2014/06/09追記ここまで]

参考