【Android】暗黙的Intent と Intent Filter の使い方
2018/11/28 追記
- リンクが切れている箇所を修正しました。
- シンタックスハイライトを適用しました。
前書き
AndroidManifest.xml
にIntent Filterを設定しておくと、暗黙的 Intent を受信することが出来ます。
Intent は Android アプリの根幹に関わる仕組みなので、ちょっと検索すればすぐに豊富な資料を見つけることが出来るんですが、「実際にどうやって書くのか?」となると結構色んな資料を見なくてはいけないので、一つにまとめたいと思います。
暗黙的 Intent と Intent Filter の仕組み
Intent には遷移するクラスを指定した明示的 Intent と、「こう言う処理がしたいんだけど、誰かできる?」と問い合わせてみる暗黙的 Intent があります。
暗黙的 Intent を発行するにはString action
を受け取るコンストラクタを使うか、Intent#setAction(String action)
を使用する必要があります。
また、その暗黙的 Intent で処理してもらいたいデータはUri
として渡すことが出来ます。
Intent 送信側の動き
// 電話をかけられるアプリに電話番号を渡す 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>
の値が違ったり、<intent-filter>
内に更に<data>
が設定されているかもしれません。
が、今回のIntent
には ACTION_DIAL
しか指定されていないので、とりあえず<intent-filter>
にそれが指定されているものを探してきます。
ちなみに、該当するアプリが複数あればユーザにどのアプリを使うか訊いてきます。
Intent 受信側の動き
選択されたアプリ(受信側)はActivity#getIntent()
で送られてきた Intent
を取得し、Intent#getData()
で Uri
を取得し、Uri
のメソッド*1でデータを抽出するわけです。
この仕組みを使うことで、処理を丸ごと別アプリに委譲したり、逆に別アプリからのデータを受け取って処理することが出来ます。また、独自の <action>
や <category>
を規定することでアプリのプラグインなどを容易に作成することも出来ます。
<intent-filter>
に設定できる属性
ドキュメントを読む限り、AndroidManifest の<intent-filter>
に設定できる属性は以下の三つみたいです。
android:icon
android:label
android:priority
何らかのアプリで暗黙的 Intent が送信されると、「それ、ウチで処理できますよ」と手を挙げるアプリが一覧として表示されるわけですが、その時にどう表示するかを設定できるっぽいですね。
直接数値を設定する android:priority
以外はきちんとリソースを用意しておく必要があります。設定しないと<application>
の値を自動で継承してくれます。
ちなみに android:priority
ですが、Activity に設定しても意味がないとのことです。なんてこったい。
<action>
の設定
<intent-filter>
に必須の子要素として、<action>
があります。これは action
の名称を示す属性(name
)を指定してあげれば OK です。
じゃあ指定できる <action>
の値ってなに?となるんですが、結論から言えば、なんでもいいです。暗黙的 Intent の送信側と Intent Filter が設定されている受信側で値が一致していれば、自動で受け取ってくれます。
action name
の定数
とは言え、流石にそれだと使いにくすぎるので、Intent
クラス内に定数としてよく使われる action
が定義されています。
Intent
のドキュメント内で「Standard Activity Actions」と検索すればその一覧が出てくるので、それっぽいものを選びましょう。
また、設定する文字列は Constant Value と言う形で書いてあります。例えばIntent#ACTION_CALL
なら android.intent.action.CALL
です。
<category>
の設定
<action>
とは別に<category>
を設定することが出来ます。<action>
よりもうちょっと具体性のある、「こう言う機能を持ったアプリに Intent を渡したい」と言う指示を出すことができます。
こちらもname
属性に指定してあげれば OK です。
category name
の定数
定数の一覧を見たい場合は Intent のドキュメント内で「Standard Categories」と検索しましょう。Intent#CATEGORY_BROWSABLE
あたりを見ておけば何となくイメージもつかみやすいんじゃないでしょうか。
送信側はIntent#addCategory(String category)
メソッドで設定することが出来ます。
受信側は指定したい <category>
がなくてもDEFAULT_CATEGORY
を指定しておかないと暗黙的 Intent を受け取れないので注意しましょう。
また、<category>
も <action>
と同様に自分で定義したものを使用することが出来ます。
<data>
の設定
<data>
を指定すると、Intent と一緒に渡される Uri の値をもとにフィルタリングすることが出来ます。
指定できる属性は以下の通りです。
android:scheme
android:host
android:port
android:mimeType
android:path
android:pathPrefix
android:pathPattern
scheme
、host
、port
に関しては特に説明しなくてもいいでしょう。ただ、scheme
が指定されていないのに host
を指定しても効果がないとか、そう言うのがあるとのことなのでドキュメントはちゃんと読んでおきましょうね。
mimeType
もそのままの意味です。送られてくるデータの型でフィルタリングすることが出来ます。
path
はちょっと複雑ですが、path
を指定したときは完全一致、pathPrefix
を指定したときは前方一致、pathPattern
ではワイルドカードを指定できます。
これらの値は基本的にUri
クラスから設定 / 取得することになるんですが、MIME-Type だけはIntent
クラスから設定 / 取得することになります。*2
Uri
と MIME-Type を同時に設定するメソッドも用意されているので、上手く活用しましょう。
まとめ
恐ろしくざっくりとした記事ですが、Intent Filter で厄介なのは「どの Action や Category をセットすればいいのか」と「どう言う Uri を作成すればいいのか」と「Uri からどうやって値を取得したらいいのか」の三つで、その辺を全部すっ飛ばしてるからです。
とは言えこの辺すらわかってないと設計すら出来ないので、とりあえず一旦まとめておきました。
2014/06/09 追記
続きのような記事を書きました。
参考
- Android Intent で画面遷移する(暗黙的 Intent) | Tech Booster
- RFC 2396
- Yuki の枝折: Android:Uri と Uri.Builder の API
- Java URI メモ(Hishidama’s Java URI Memo)
- Yuki の枝折: Android:Intent に格納する URI 指定時の注意
- traceback.: <intent-filter> に設定する android:priority 属性の意味について
- Yuki の枝折: Android:IntentFilter に DEFAULT_CATEGORY が必要な理由
*1:電話番号だとUri#getSchemeSpecificPart()あたりかな?