Android里Activity的IntentFilter匹配规则

Activity的启动方式

显式启动

显示方式就是在通过intent启动Activity时指定了Activity的包名和类名,而且不管启动本应用的Activity还是启动其他应用的Actitity

例如:要启动的Activity是同一个项目之中:

Intent intent = new Intent(context, MyActitity.class);
startService(intent);

如果因为也是在同一个项目之中,但特殊原因不能直接引用XXXActivity,也可以通过loadClass,传入完整的包名来启动Activity:

try {
    Class c = context.getClassLoader().loadClass("com.xxx.MyActivity");
    Intent intent = new Intent(context, c);
    startActivity(context, intent);
} catch(ClassNotFoundException ex) {
    ex.printStackTrace();
}

又例如:要启动的Activity不在同一个项目之中:

ComponentName cn = new ComponentName("packageName",com.xxx.MyActivity");
Intent intent = new Intent();
intent.setComponent(cn);
startActivity(intent);

或者:

Intent intent = new Intent("android.intent.action.MAIN");
intent.setClassName("packageName","com.xxx.MyActivity");
startActivity(intent);

隐式启动

隐式启动Activity需要同时匹配过滤列表中的action、cetegor、data信息。action、cetegor和data可以有多个,同一类别的信息共同约束当前类别的匹配过程。一个Activity中可以有多个intent-filter,一个Intent只要能匹配任何一组intent-filter即可成功启动对应用Activity。

下面是一个过滤规则的示例:


    
        
        
        
        
        
        
    

匹配实例代码:

Intent intent = new Intent("com.xxx.a");
intent.addCategory("com.xxx.c");
intent.setDataAndType(Uri.parse("file://abc"), "text/plain");
startActivity(intent);

action的匹配规则

action是一个字符串,系统预定义了一些action,同时我们也可以在应用中定义自己的action,action区分大小写。action的匹配规则是Intent中的action必须能够和过滤规则中的action字符串完全一样。一个过滤中可以有多个action,Intent中的action能够和过滤规则中的任何一个action相同即可匹配成功。

category的匹配规则

category是一个字符串,系统预定义了一些category,同时我们也可以在应用中定义自己的category。category要求Intent中如果含有category,不管有多少个,都必须和过滤规则中的其中有定义的category相同。当然,Intent中可以没有category,如果没有category的话,按照上面的描述,这个Intent仍然可以匹配成功。原因是系统在调用startActivity或者startActivityForResult的时候会默认为Intent加上”android.intent.category.DEFAULT”这个category,所以这个category就可以匹配前面的过滤规则中的第三个category。同时,为了我们的activity能够接收隐式调用,就必须在intent-filter中指定”android.intent.category.DEFAULT”这个category。即是说,在Intent中可以没有category,但有的情况下,哪怕是其中一个都不能无中生有。

data的匹配规则

 data的匹配规则和action类似,如果过滤规则中定义了data,那么Intent中必须也要定义可匹配的data。data的语法如下所示:

data由两部分组成,mimeType和URI。mimeType指媒体类型,比如image/jpeg、audio/mpeg4-generic和video/*等,可以表示图片、文本、视频等不同的媒体格式,而URI中包含的数据就比较多了,下面是URI的结构:

://:/[||]

scheme:                       URI的模式,比如http、file、content等。如果URI中没有指定scheme,那么整个URI的其它参数无效,这也意味着URI是无效的。    

host:                              URI的主机名,比如www.baidu.com,如果host未指定,那么整个URI中的其他参数无效,这也意味着URI是无效的。    

port:                              URI中的端口号,比如80,仅当URI中指定了scheme和host参数的时候port参数才是有意义的。    

path、pathPattern和pathPrefix: 这三个参数表述路径信息,其中path表示完整的路径信息;pathPattern也表示完整的路径信息,但是它里面可以包含通配符“*”,“*”表示0个或多个任意字符,需要注意的是,由于正则表达式的规范,如果想表示真实的字符串,那么“*”要写成“\\*”,”\”要写成”\\\\”;pathPrefix表示路径的前缀信息。

分情况说明data的匹配规则

1、 如下过滤规则:

 
   

匹配实例:

intent.setDataAndType(Uri.parse("file://abc"),"image/png")

说明:

这种规则mimeType属性必须为“image/*”才能匹配,虽然过滤规则没有指定URI,但是却有默认值,URI的默认值为content和file。

2、 如下过滤规则:


    
    
 

匹配实列:

intent.setDataAndType(Uri.parse("http://abc"),"video/mpeg")

或者

intent.setDataAndType(Uri.parse("http://abc"),"audio/mpeg")

特殊写法

如下两种特殊写法,它们的作作是一样的:    


   

 和


   
   

错误规避

当我们通过隐式方式启动一个Activity时,如果没有匹配Activity则会出现错误,所以我们在匹配前可以使用PackageManager的resolveActivity方法或者Intent的resolveActivity方法。如果它们找不到匹配的Activity则返回null。PackageManager还提供了queryIntentActivities方法,这个方法不是返回最佳匹配的Activity信息,而是返回所有成功匹配的Activity信息。

有时,可以在startActivity前,先判断Intent是否有效,可以这样:

private static boolean isIntentAvailable(Context context, Intent intent) {
    if (intent == null) {
        return false;
    }
    boolean isAvailable = context.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY).size() > 0;
    return isAvailable;
}

入口Activity


以上代码,二者共同作用是用来标明这是一个入口Activity并且会出现在系统的应用列表中,少了任何一个都没有实际意义。

 

 


——本博文部分内容参考自《Android开发艺术探索》

你可能感兴趣的:(Android入门与基础)