Android IntentFilter匹配规则

显式调用

Intent intent = new Intent();
intent.setClassName(“lbb.demo.anotest”, “lbb.demo.anotest.TwoActivity”);
startActivity(intent);
打开包名为”lbb.demo.anotest”的 “lbb.demo.anotest.TwoActivity”方法。。。可能启动另外一个app

new Intent(this,AnoActivity.class); 打开当前应用的AnoActivity

隐式调用

Action,Catogory匹配

//此时action为”lbb.demo.anotest.TwoActivity”,同时默认添加DEFAULT的category
Intent intent = new Intent(“lbb.demo.anotest.TwoActivity”);
//intent.addCategory(“android.intent.category.DEFAULT”);
startActivity(intent);
//此时根据AMS规则,是全局查找的。。。并不是只针对于当前应用。。可能启动另外一个app

        <activity
            android:name=".TwoActivity"
            android:label="@string/title_activity_two"
            android:theme="@style/AppTheme.NoActionBar">
            <intent-filter>
                <action android:name="lbb.demo.anotest.TwoActivity"/>
                <category android:name="android.intent.category.DEFAULT"/>
            </intent-filter>
        </activity>

category android:name=”android.intent.category.DEFAULT”这样是必不可少的。否则隐式匹配不到该activity,同时注意大小写匹配

Data匹配

Each element can specify a URI and a data type (MIME media type). There are separate attributes —scheme, host, port, and path — for each part of the URI:
scheme://host:port/path or pathPrefix or pathPattern
For example, in the following URI,
content://com.example.project:200/folder/subfolder/etc
the scheme is “content”, the host is “com.example.project”, the port is “200”, and the path is “folder/subfolder/etc”.

path 用来匹配完整的路径,如:http://example.com/blog/abc.html,这里将 path 设置为 /blog/abc.html 才能够进行匹配;
pathPrefix 用来匹配路径的开头部分,拿上来的 Uri 来说,这里将 pathPrefix 设置为 /blog 就能进行匹配了;
pathPattern 用表达式来匹配整个路径,这里需要说下匹配符号与转义。

匹配符号:
” 用来匹配0次或更多,如:“a” 可以匹配“a”、“aa”、“aaa”…
“.” 用来匹配任意字符,如:“.” 可以匹配“a”、“b”,“c”…
因此 “.*” 就是用来匹配任意字符0次或更多,如:“.*html” 可以匹配 “abchtml”、“chtml”,“html”,“sdf.html”…

转义:因为当读取 Xml 的时候,“/” 是被当作转义字符的(当它被用作 pathPattern 转义之前),因此这里需要两次转义,读取 Xml 是一次,在 pathPattern 中使用又是一次。如:“” 这个字符就应该写成 “//”,“/” 这个字符就应该写成 “”。

setType 调用后设置 mimeType,然后将 data 置为 null;
setData 调用后设置 data,然后将 mimeType 置为 null;
setDataAndType 调用后才会同时设置 data 与 mimeType。
setDataAndType不等同于先调用setData后调用setType,尤其注意

URI的schema是有默认值的,默认值是”content”/”file”

<intent-filter>
    <data android:mimeType="video/mpeg"/>
</intent-filter>

//正确方式
intent.setDataAndType(Uri.parse("file://abc"), "video/mpeg");
intent.setDataAndType(Uri.parse("content://abc"), "video/mpeg");
intent.setType("video/mpeg");

intent.setDataAndType(Uri.parse(“http://abc“), “video/mpeg”);
这样是匹配不到的,因为schema部分不匹配默认值是”content”/”file”

PackageManager相关方法

如果有多个action匹配就会出现选择框。。如果没有任何一个,就会Force Close,所以可以通过方法检查是否有符合条件的activity,避免FC
PackageManager方法

    /**
     * Determine the best action to perform for a given Intent.  This is how
     * {@link Intent#resolveActivity} finds an activity if a class has not
     * been explicitly specified.
     *
     * <p><em>Note:</em> if using an implicit Intent (without an explicit ComponentName
     * specified), be sure to consider whether to set the {@link #MATCH_DEFAULT_ONLY}
     * only flag.  You need to do so to resolve the activity in the same way
     * that {@link android.content.Context#startActivity(Intent)} and
     * {@link android.content.Intent#resolveActivity(PackageManager)
     * Intent.resolveActivity(PackageManager)} do.</p>
     *
     * @param intent An intent containing all of the desired specification
     *               (action, data, type, category, and/or component).
     * @param flags Additional option flags.  The most important is
     * {@link #MATCH_DEFAULT_ONLY}, to limit the resolution to only
     * those activities that support the {@link android.content.Intent#CATEGORY_DEFAULT}.
     *
     * @return Returns a ResolveInfo containing the final activity intent that
     *         was determined to be the best action.  Returns null if no
     *         matching activity was found. If multiple matching activities are
     *         found and there is no default set, returns a ResolveInfo
     *         containing something else, such as the activity resolver.
     *
     * @see #MATCH_DEFAULT_ONLY
     * @see #GET_INTENT_FILTERS
     * @see #GET_RESOLVED_FILTER
     */
    public abstract ResolveInfo resolveActivity(Intent intent, int flags);

    /**
     * Retrieve all activities that can be performed for the given intent.
     *
     * @param intent The desired intent as per resolveActivity().
     * @param flags Additional option flags.  The most important is
     * {@link #MATCH_DEFAULT_ONLY}, to limit the resolution to only
     * those activities that support the {@link android.content.Intent#CATEGORY_DEFAULT}.
     *
     * @return A List&lt;ResolveInfo&gt; containing one entry for each matching
     *         Activity. These are ordered from best to worst match -- that
     *         is, the first item in the list is what is returned by
     *         {@link #resolveActivity}.  If there are no matching activities, an empty
     *         list is returned.
     *
     * @see #MATCH_DEFAULT_ONLY
     * @see #GET_INTENT_FILTERS
     * @see #GET_RESOLVED_FILTER
     */
    public abstract List<ResolveInfo> queryIntentActivities(Intent intent,
            int flags);

看两个方法的注释

resolveActivity返回最佳匹配,找不到匹配的返回null
queryIntentActivities 返回所有的,找不到匹配的返回null
flags必须是CATEGORY_DEFAULT,增加catogory匹配规则,否则会忽略category匹配,那么可能会导致startactivity/startservice失败

最后实现肯定是通过PMS(PackageManagerService)执行对应方法,IBinder通信

综合前面,AMS,WMS,PMS都介绍过了。

例子

       <activity
            android:name=".TestActivity"
            android:label="@string/title_activity_test"
            android:theme="@style/AppTheme.NoActionBar">
            <intent-filter>
                <action android:name="android.intent.action.TestActivity"/>
                <category android:name="android.intent.category.DEFAULT"/>
                <data
                    android:host="baidu"
                    android:mimeType="image/png"
                    android:scheme="http"/>
            </intent-filter>
        </activity>
    @OnClick(R.id.but)
    void OnClick() {
        Intent intent = new Intent();
        intent.setAction("android.intent.action.TestActivity");
        intent.setDataAndType(Uri.parse("http://baidu:8888/abc/..."), "image/png");
        PackageManager pm = getPackageManager();
        if (pm.resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY) != null) {
            startActivity(intent);
        }else{
            Log.d("LiaBin","no match intent");
        }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值