参考文献:https://developer.android.com/reference/android/content/Intent#developer-guides
https://developer.android.com/guide/components/intents-filters.html#Receiving
目录
1. Intent是什么
Intent字面意思翻译过来就是‘意图’, 它是Android要执行的操作的抽象描述,可以用它来启动Activity,发送广播组件,与后台Service联系。
1.1 Intent结构组成
Intent的主要组成信息分为:
- action: 要执行的一般操作,比如:ACTION_VIEW, ACTION_EDIT, ACTION_MAIN….
- data: 要操作的数据,比如:数据库里的数据,表示成Uri数据。
比如:
ACTION_VIEW content://contacts/people/1 -- 显示ID为1的人的信息。
ACTION_EDIT content://contacts/people/1 -- 编辑ID为1的人的信息。
除了主要信息,Intent还有额外的附属信息:
- category: 提供相关action要执行的额外信息,例如,CATEGORY_LAUNCHER意味着它应该作为顶级应用程序出现在启动程序中,而CATEGORY_ALTERNATIVE意味着它应该包含在用户可以对数据执行的可选操作列表中。
- type: 指定意图数据为显式类型。通常,类型是从数据本身推断出来的。通过设置此属性,可以禁用该计算并强制使用显式类型。
- component: 指定要用于该意图的组件类的显式名称。通常,这是通过查看意图中的其他信息(操作、数据/类型和类别)并将其与能够处理它的组件匹配来确定的。如果设置了此属性,则不执行任何计算,并且按原样使用此组件。通过指定此属性,所有其他Intent属性都是可选的。
- extras: 这是一组Bundle附加信息。这可以用来向组件提供扩展信息。例如,如果我们有一个发送电子邮件的操作,我们还可以在这里包含额外的数据片段来提供主题、发送人,接受人,信息内容,及附件等额外的信息。
1.2 Intent类型
我们主要会使用两种类型的Intent,显式Intent和隐式Intent。
- 显式Intent: 指定了一个组件(通过setComponent(ComponentName)或setClass(Context, Class))来提供要运行的确切类。这些通常不包括任何其他信息,只是作为应用程序在用户与应用程序交互时启动各种内部活动的一种方式。
- 隐式Intent:没有指定组件,相反,它们必须包含足够的信息,以便系统确定哪个可用组件最适合运行该目的。
1.2.1 显式Intent与隐式Intent的区别
区别总结:显式Intent会指定特定组件,而隐式Intent不会指定特定的组件,详细请看下方案例。
隐式Intent不会直接指定app要调用的组件,而是指定要执行的操作,并且提供执行该操作需要的数据。也就是说我们只管去注册这些隐式Intent,当我们的app要执行这些操作时,系统会去搜索所有注册了特定操作和数据类型的组件,找出所有可以使用的组件来供用户去选择使用。
比如:我们要实现一个功能为:点击按钮,然后打开浏览器并打开百度页面。
Button btn = findViewById(R.id.btn);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
/*对应的Intent基本组成信息分别是:
action: ACTION_VIEW
data: Uri.parse("https://www.baidu.com")
*/
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://www.baidu.com"));
startActivity(intent);
}
});
效果为:
显式Intent会直接指定需调用的组件,所以当你知道要执行的操作需要调用哪个组件来实现,并且不想让用户自由控制要使用哪个组件时,就需要用到显式Intent。比如,你有一个具有两个活动的应用程序。活动A和活动B。您希望从活动A启动活动B。在这种情况下,你定义了一个明确的目标活动B的意图,使用它时就将直接调用它,系统也就不会再多余的去搜索其他能实现该操作的组件。
在一个activity上跳转到另一个activity的实现方法为:
Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
startActivity(intent);
查看我们使用的Intent()方法, 其说明就为:创建指定特定组件的意图,所有其他字段(action、data、type, class)为空,不过稍后可以显式修改它们。
/**
* Create an intent for a specific component. All other fields (action, data,
* type, class) are null, though they can be modified later with explicit
* calls. This provides a convenient way to create an intent that is
* intended to execute a hard-coded class name, rather than relying on the
* system to find an appropriate class for you; see {@link #setComponent}
* for more information on the repercussions of this.
*
* @param packageContext A Context of the application package implementing
* this class.
* @param cls The component class that is to be used for the intent.
*
* @see #setClass
* @see #setComponent
* @see #Intent(String, android.net.Uri , Context, Class)
*/
public Intent(Context packageContext, Class<?> cls) {
mComponent = new ComponentName(packageContext, cls);
}
Activity间的跳转流程图见下: (活动A)创建一个带有操作描述的意图,并将其传递给startActivity()。Android系统会搜索所有应用程序,寻找与意图匹配的意图过滤器(Intent filter)。当找到匹配时,系统通过调用它的onCreate()方法并传递意图来启动匹配的活动(活动B)。
2. Intent的应用
Intent有多种方式来促进组件之间的通信,主要三个基本用例:
1. 启动Activity
Activity之间的跳转加传递一些数据,都需要用到Intent,具体实践见上方?。
额外:如果你想在某个Activity结束时从该Activity接收结果,比如,你有两个Activity(Activity A 和 Activity B),你从Activity A跳转到Activity B,你想在Activity B结束然后返回Activity A时,携带一些数据给Activity A。这时候你就需要用到startActivityForResult()方法,具体实现方式及案例请看另一篇博客:startActivityForResult()方法实践及Demo
2. 开启Service
服务(Service)是在没有用户界面的情况下在后台执行操作的组件,利用Intent来描述要启动并携带任何必要数据的服务。
//todo: need write another blog to explain startService() function and android Service.
3. 发送广播
广播是任何应用程序都可以接收到的消息。系统为系统事件提供各种广播,例如当系统启动或设备开始充电时。通过将Intent传递给sendBroadcast()或sendOrderedBroadcast(),可以将广播传递给其他应用程序。
//todo: need write another blog to explain sendBroadcast() function and android Broadcast
3. Intent filter
3.1 Intent filter是什么,有什么作用
意图过滤器(Intent filter)是应用程序清单文件(AndroidManifest.xml)中的表达式,用来指定活动、服务或广播接收器可以响应的Intent类型。intent filter声明其父组件的功能——活动或服务可以做什么,接收者可以处理什么类型的广播。它打开组件以接收广告类型的Intent,同时过滤掉对组件没有意义的Intent。
过滤器的大部分内容由它的<action>、<category>和<data>子元素描述。
- <action> : 在name属性中声明接受的intent操作。该值必须是操作的文字字符串值,而不是类常量。
- <category> : 在name属性中声明接受的intent类别。该值必须是操作的文字字符串值,而不是类常量。
- <data> : 使用指定数据URI(协议(scheme),主机(host),端口(port),路径(path))和MIME类型的各个方面的一个或多
个属性声明接受的数据类型。
备注:MIME (Multipurpose Internet Mail Extensions) 是描述消息内容类型的因特网标准。MIME 消息能包含文本、图像、音频、视频以及其他应用程序专用的数据。
3.2 Intent filter例子解析说明
<activity android:name="MainActivity">
<!-- 该活动是app主入口, 是app启动后显示出来的第一个活动 -->
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- 此活动有两个intent-filter -->
<activity android:name="ShareActivity">
<!-- 此filter处理带有文本数据的“发送”操作 -->
<intent-filter>
<action android:name="android.intent.action.SEND"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="text/plain"/>
</intent-filter>
<!-- 此filter还处理媒体数据的“SEND”和“SEND_MULTIPLE”操作 -->
<intent-filter>
<action android:name="android.intent.action.SEND"/>
<action android:name="android.intent.action.SEND_MULTIPLE"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="application/vnd.google.panorama360+jpg"/>
<data android:mimeType="image/*"/>
<data android:mimeType="video/*"/>
</intent-filter>
</activity>
如上图所示,第二个活动ShareActivity是在促进共享文本和媒体内容。虽然用户可以通过从MainActivity导航到此活动,但他们也可以直接从另一个应用程序通过发送与之匹配的隐式Intent进入到ShareActivity。
END~~