注意! この記事はQiitaにて公開されていた内容をimportしたものです。
これらの内容は場合によっては陳腐化していて役に立たなくなっていたり、有害であったり、現在の著者の主張と異なることがあります。
皆様の判断の上でご利用いただけますと幸いです(度を超してヤバいものは著者に連絡して頂ければ対応します m(_ _)m)


はじめに

Androidアプリ開発では暗黙的Intentを処理することは非常によく発生します。 ただ、記述する定義に対して、明示的・暗黙的なルールがあったりして非常に初見殺しであるとも言えます。

今回は、IntentFilterのdata要素でハマった点を解説します

公式ドキュメントの記載

まずはじめに簡単にdata要素について。

これを読む限り、以下のことが言えます。

  • data要素ではandroid:scheme属性が最低でもひとつは必要である
    • ただしandroid:mimeTypeが指定されていると暗黙的にfilecontentが指定されているものとされる
  • android:host属性はandroid:scheme属性が指定されていないと意味を成さない
  • android:pathandroid:pathPrefixandroid:pathPattern属性はandroid:schemeおよびandroid:host属性が指定されていないと意味を成さない

これらの情報から、以下の様なIntentFilterを定義し、adb shell am startコマンドでいくつか検証しました。

<activity android:name=".HogeActivity">
    <intent-filter>
        <action android:name="android.intent.action.VIEW"/>

        <category android:name="android.intent.category.DEFAULT"/>
        <category android:name="android.intent.category.BROWSABLE"/>

        <data
            android:host="example.com"
            android:scheme="http"/>

    </intent-filter>
</activity>
$ adb shell am start -a android.intent.action.VIEW -c android.intent.category.BROWSABLE -d http://example.com/test.mp4

これでHogeActivityが起動するはずです。

問題:Chromeでリンクをタップした時に割り込めない

上記指定で無事に起動しました。めでたし。 ただ、以下のようにdata要素の指定を増やすと(?)、Chromeでリンクをクリックしてもアプリの選択画面に現れなくなります。 (本当にdataが増えたことに因果関係があるかどうかは不明。再現しないケースもある。。)

<activity android:name=".HogeActivity">
    <intent-filter>
        <action android:name="android.intent.action.VIEW"/>

        <category android:name="android.intent.category.DEFAULT"/>
        <category android:name="android.intent.category.BROWSABLE"/>

        <data
            android:host="example.com"
            android:scheme="http"/>
        <data
            android:host="*.example.net"
            android:scheme="http"/>
    </intent-filter>
</activity>

解決策: android:pathPrefix もしくは android:pathPattern を設定する

おなじみのStackOverflowを参照すると、android:pathPrefixを付与している例が見られます。 また、android:pathPattern=".*"という一件無意味そうな定義があります。

ただ、これらの指定をすることで、Chromeで該当のリンクをクリックするとちゃんとアプリの選択ダイアログが表示されるようになります。

<activity android:name=".HogeActivity">

    <intent-filter>
        <action android:name="android.intent.action.VIEW"/>

        <category android:name="android.intent.category.DEFAULT"/>
        <category android:name="android.intent.category.BROWSABLE"/>

        <data
            android:host="example.com"
            android:scheme="http"
            android:pathPattern="/.*"/>

        <data
            android:host="*.example.net"
            android:scheme="http"
            android:pathPattern="/.*"/>
    </intent-filter>
</activity>

ちなみに

android:hostにはワイルドカード指定が使えます。