intent-filterのdataをずっと勘違いしていた話


Androidは2系からずっと触ってきましたが、なぜか今まで勘違いしてました

かなり初歩的なことだし検索すると普通に記事があるので知っている人も多いと思いますが、忘れないように恥を忍んでメモ。

問題

AndroidManifestで以下のように宣言されている時、暗黙的Intentで立ち上がるURLはどれでしょうか?

AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest ...>
    <application ...>
        <activity android:name=".MainActivity">
            <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="bbb"
                    android:scheme="aaa" />
                <data
                    android:host="ddd"
                    android:scheme="ccc" />
            </intent-filter>
        </activity>
    </application>
</manifest>
  1. aaa://bbb
  2. aaa://ddd
  3. ccc://bbb
  4. ccc://ddd

答え

全部!

解説

上のように書いたとき、自分の中では以下のような感じで処理されると思っていました。

if ((scheme == aaa && host == bbb) || (scheme == ccc && host == ddd)) {
    // ...
}

でも実際はこうでした。

if ((scheme == aaa || scheme == ccc) && (host == bbb || host == ddd)) {
    // ...
}

前者のようにするには

以下のように2回intent-filterを書きます。ちょっと無駄感がありますね。

AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest ...>
    <application ...>
        <activity android:name=".MainActivity">
            <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="bbb"
                    android:scheme="aaa" />
            </intent-filter>
            <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="ddd"
                    android:scheme="ccc" />
            </intent-filter>
        </activity>
    </application>
</manifest>

勘違いしないために

こういう仕様であるって覚えておけばそれまでなんですが、書き方を変えるだけでも勘違いを減らせるかなと思いました。

dataに複数の要素を書かない

一番最初の問題みたいに、4つのURLで全て起動することを意図しているなら、以下のように分けて書いたほうが分かりやすいかなと思いました。

AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest ...>
    <application ...>
        <activity android:name=".MainActivity">
            <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:scheme="aaa" />
                <data android:scheme="ccc" />
                <data android:host="bbb" />
                <data android:host="ddd" />
            </intent-filter>
        </activity>
    </application>
</manifest>

こうしておけば新たに加えるときもやりやすいかなと思います。

以下のように書けないのもちょっとモヤッとします。

NG
<data
    android:host="bbb"
    android:host="ddd"
    android:scheme="aaa"
    android:scheme="ccc" />

まとめ

pathPrefixなども絡んでくると、結構複雑だなと思いました。

すでに知っている人には本当に申し訳ありませんでした