本篇主要介绍内容;
Intent详解;
Intent filter匹配规则;
一、Intent详解
Intent:在Android中是一个非常重要的类,连接四大组件,主要用来启动Activity、Service和发送广播;
Intent类别:
1、显式Intent
2、隐式Intent
Intent的组成:
1、component(组件):目的组件
2、action(动作):用来表现意图的行动
3、category(类别):用来表现动作的类别
4、data(数据):表示与动作要操纵的数据
5、type(数据类型):对于data范例的描写
6、extras(扩展信息):扩展信息
7、Flags(标志位):期望这个意图的运行模式
1、ComponentName
要启动的组件名称;如果你想使用显式的Intent,那么你就必须指定该参数,一旦设置了component name,Android会直接将Intent传递给组件名所指定的组件去启动它。如果没有设置component name,那么该Intent就是隐式的,Android系统会根据其他的Intent的信息(例如下面要介绍到的action、data、category等)做一些比较判断决定最终要启动哪个组件。
注意:当启动Service的时候,你应该总是指定Component Name。否则,你不确定最终哪个App的哪个组件被启动了,并且用户也看不到哪个Service启动了。
示例:
Intent intent = new Intent();
//参数1:包名 参数2:完整的类名
ComponentName componentName =
new ComponentName("test.jiao.com","test.jiao.com.activity_test.SecondActivity");
intent.setComponent(componentName);
startActivity(intent);
这种方式亦可启动不同应用的Activity;
2、Action
Action 是一个用户定义的字符串,用于描述一个 Android 应用程序组件;
可以在Activity的<intent-filter>中定一个或多个action来描述Activity要响应的动作;
其对应着Intent Filter中的action标签<action />。
<intent-filter>
<action android:name="test.jiao.com.action1" />
<action android:name="test.jiao.com.action2" />
</intent-filter>
我们亦可在启动Activity的时候设定自己想要的动作;
intent.setAction("test.jiao.com.action1");
3、category
category和action有点类似,也是用户定义的字符串;同时系统有很多预定义的category;
常见的有:
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.LAUNCHER" />
category并不是很常用,但是如果一个Activity在定义的时候想要被隐式启动就一定要添加
<category android:name="android.intent.category.DEFAULT" />
因为系统在startActivity的时候默认为Intent添加了
<category android:name="android.intent.category.DEFAULT" />;
4、data
在启动Activity的时候通过Intent携带的数据,其对应着Intent Filter中的data标签<data />。
data有两部分组成:mimeType和URI
mimeType是指媒体类型比如:image/jpeg、video/等,可以表示文本、图片等不同的媒体格式;
URI:<scheme>://<host>:<port>/<path>
Scheme:URI的模式比如http、file等;
Host:URI的主机名,比如www.baidu.com
Port:URI的端口号,比如80
Path:路径信息,可以包含通配符
接下来我们举个例子在Activity中定义:
<intent-filter>
<data
android:mimeType="video/mpeg"
android:scheme="http" />
</intent-filter>
如果我們想要匹配该Activity需要
intent.setDataAndType(Uri.parse("http://abc"),"video/mpeg");
5、Type
Type属性用于明确指定Data属性的数据类型;
如上面例子中提到的: android:mimeType="video/mpeg" ,
android:mimeType="image/*" 等
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
Uri data = Uri.parse("file:///storage/sdcard0/平凡之路.mp3");
intent.setDataAndType(data, "audio/mp3");
startActivity(intent);
6、extras
扩展信息、附加信息,是其它所有附加信息的集合。
使用extras可以为组件提供扩展信息,比如,如果要执行“发送电子邮件”这个动作,可以将电子邮件的标题、
正文等保存在extras里,传给电子邮件发送组件。如下:
String[] tos = { "jiao9030@gmail.com" }; //所有收件人
String[] ccs = { "jiao9030@163.com" }; //所有抄送
intent.putExtra(Intent.EXTRA_EMAIL, tos);
intent.putExtra(Intent.EXTRA_CC, ccs);
intent.putExtra(Intent.EXTRA_TEXT, "the email text"); //设置附加信息 邮件正文
intent.putExtra(Intent.EXTRA_SUBJECT, "subject"); //设置附加信息 邮件标题
intent.setType("text/plain");
Intent.createChooser(intent, "Choose Email Client");
7、Flags
标志位,期望这个Intent的运行模式,这个在上篇中有详细的解释;
二、Intent filter匹配规则
上面讲到的Intent的可以携带的参数,根据这些参数我们就可以启动我们想要启动的页面;
然而系统是如何根据Intent的参数来匹配要启动的Activity呢?
1、action匹配规则
①如果Intent中的action(仅一个)和Intent filter中的任何一个action匹配成功
(这里的匹配成功是指值完全一样)就算通过验证;
<intent-filter>
<action android:name="test.jiao.com.action1" />
<action android:name="test.jiao.com.action2" />
</intent-filter>
intent.setAction("test.jiao.com.action1");
验证通过
②如果Intent未指定action 而Intent filter中有action过滤,那么该Intent将不能通过验证;
<intent-filter>
<action android:name="test.jiao.com.action1" />
<action android:name="test.jiao.com.action2" />
</intent-filter>
而intent未指定action 将不能与上面的Intent filter匹配成功;
③如果Intent中携带多个action,那么Intent filter中必须包含该Intent中的所有action才能通过验证;
<intent-filter>
<action android:name="test.jiao.com.action1" />
<action android:name="test.jiao.com.action2" />
</intent-filter>
intent.setAction("test.jiao.com.action1");
intent.setAction("test.jiao.com.action2");
intent.setAction("test.jiao.com.action3");
验证不通过;
2、category匹配规则
category的匹配规则和action的规则①③完全一致
唯一不同的是:
如果intent未指定category 而intent filter指定了多个category 该intent将能通过验证,
原因是在startActivity的时候系统默认为intent添加了一个
<category android:name="android.intent.category.DEFAULT"/>;
这里要说明一点:如果Activity要想被隐式启动就必须在Intent filter中添加
<category android:name="android.intent.category.DEFAULT"/>
为什么上面已经讲过了;
3、data匹配规则
data的匹配规则与action完全一致,它也要求intent中必须含有data数据,并且data数据能够完全匹配过滤规则中
的某一个就算通过验证;举例说明
<intent-filter>
<data android:mimeType="image/*"/>
</intent-filter>
这种规则制定媒体类型为所有类型的图片,那么intent中的mimeType属性必须为"image/*"才能匹配;
注意:以上过滤规则中虽然并没有指定URI但是却有默认值URI默认值为content和file;
也就是说虽然没有指定URI但是intent中的URI部分必须为content或file才能通过验证;
intent.setDataAndType(Uri.parse("file://abc"),"image/png");
该intent既能通过验证;
如果intent filter中有两组data规则,我们只需匹配一组即可通过验证;
最后:如果我们在启动一个Activity的时候,系统没有找到该Activity会报异常android.content.ActivityNotFoundException,因此如果我们隐式启动一个Activity的时候,我们并不能确定一定有Activity能匹配我们的规则启动成功,可以用PackageManager的resolveActivity或者Intent的resolveActivity方法来判断一下,如果他们找不到相应的Activity就会返回null,从而避免以上错误的出现;
另外:PackageManager的queryIntentActivitys方法可以返回所有可以成功匹配的Activity信息;