我们都知道Android 应用框架中的4大基本组件分别是:
活动----绘制一个屏幕的用户界面,响应用户交互
服务----在后台运行,执行耗时操作或远程过程调用
广播接收器----响应系统级(或自定义)的广播通知
数据源----管理数据访问接口(应用内或系统级)
Android 应用框架让你使用一组可重用的基本组件即可创建出丰富而有创意的应用程序。
虽然每个组件是一个独立的存在,扮演特定的角色,但是部分组件之间存在依赖关系,应用框架使用意图(Intent)将组件连接起来,共同构成一个程序的整体行为。
意图是组件间传递消息的一种对象,主要由动作(action)和数据(data)两部分组成。Intent负责对应用中一次操作的动作、动作涉及数据、附加数据进行描述,Android则根据此Intent的描述,负责找到对应的组件,将 Intent传递给调用的组件,并完成组件的调用。因此,Intent在这里起着一个媒体中介的作用,专门提供组件互相调用的相关信息,实现调用者与被调用者之间的解耦。
Intent意图是要执行的操作的抽象描述。用于请求其他组件(活动、服务、广播接收器)中的操作,完成组件之间的交互。
由Intent来协助完成android各个组件之间的通讯。比如调用Activity实例化对象的startActivity()来启动一个activity,或者由broadcaseIntent()来传递给所有感兴趣的BroadcaseReceiver, 或者由startService()/bindservice()来启动一个后台的service。可见,intent主要用来启动activity或者service(并携带需要传递的参数信息)。
总之,Intent具有激活组件和携带数据的功能!
场景 |
方法 |
启动活动 |
startActivity startActivityForResult |
启动服务 |
startService bindService |
发送广播 |
sendBroadcast sendOrderedBroadcast sendStickyBroadcast |
类型 |
描述 |
显式意图 |
通过类名指定要启动的组件(在应用内部);如启动一个活动查看信息详细内容或启动一个服务在后台下载文件。 提示:处于安全考虑,使用显式意图启动程序中的服务。 |
隐式意图 |
不指定组件的名称,而是声明要执行的动作,这样就允许其他应用中的组件处理这个动作;如点击一个超链接,启动了浏览器开始加载这个页面。 |
明确指定组件名的意图Intent为显式意图,指定了Intent应该传递给哪个组件,并且可以设定需要传递的参数信息。由于显示意图指定了具体的组件对象,不需要设置intent的其它意图过滤对象。
没有明确指定组件名的Intent为隐式意图,系统会根据隐式意图中设置的动作(action)、类别(category)、数据URI等来匹配最合适的组件。
显式意图一般在应用的内部使用,因为在应用内部已经知道了组件的名称,比如从主活动MainActivity跳转到下一个活动NextActivity,直接调用就可以了。当一个应用要激活另一个应用中的Activity时,比如点击一个网址链接,要另起浏览器,只能使用隐式意图,根据Activity配置的意图过滤器建一个意图,让意图中的各项参数的值都跟过滤器匹配,这样就可以激活其他应用中的Activity。所以,隐式意图是在应用与应用之间使用的。
显式意图:必须指定要激活的组件的类名和完整包名,一般激活自己应用的组件的时候采用显示意图。
隐式意图:只需要指定要执行的动作和要携带的数据就可以,激活别人应用的时候使用,不需要关心对方的包名和类名。
(1)Activity A 创建一个有动作描述的Intent 并传递给 startActivity 方法。
(2)Android 系统搜索所有应用中的Intent Filter 来匹配该 Intent,若找到。
(3)Android 系统通过调用onCreate 创建匹配 Intent 的 Activity B,并把Intent 传递给 Activity B。
意图Intent作为联系各组件之间的纽带,其作用并不仅仅只限于简单的数据传递。通过其自带的属性,可以方便的完成很多较为复杂的操作。例如直接调用拨号功能、直接自动调用合适的程序打开不同类型的文件等等。诸如此类,都可以通过设置Intent属性来完成。Intent类的属性如下:
字段 |
描述 |
action |
要执行的动作(字符串常量 ) |
data |
要操作的数据(Uri 类型) |
category |
组件的类别信息 |
type |
明确指定要操作的数据类型(MIME)(默认根据数据判定) |
component |
目标组件的类名(若指定该属性,其他属性皆为可选) |
extras |
传递的附加信息,如邮件的标题、内容(键值对形式) |
flag |
标记系统如何启动活动 |
action属性是Intent意图类最重要的属性。Action是指Intent要完成的动作,是一个字符串常量。使用 setAction() 和 getAction()来设置和读取Action属性。
注意:一个Intent只能指定一个action,但是一个Activity(或广播等组件)可以设置(监听、匹配)多个action(即intent-filter中可以设置多个action属性)。
动作 |
描述 |
ACTION_MAIN |
应用的入口(启动的第一个活动),不接收数据 |
ACTION_EDIT |
提供对指定数据(Uri)的编辑 |
ACTION_VIEW |
显示数据 |
ACTION_PICK |
选择并获得选中的一项数据(如选择照片) |
ACTION_DIAL |
预备拨打指定的号码 |
ACTION_CALL |
直接拨打指定的号码 |
data属性在Intent意图类种也非常重要。Data属性是执行动作的URI和MIME类型,不同的动作有不同的数据规格。Data通常是Uri格式定义的操作数据.
当匹配intent和能够处理intent所带的数据的组件时,知道数据类型(MIME类型)是很重要的。比如,一个展示图像的组件不应该被叫去播放一个音频。
很多情况下,从URI可以看出数据类型,比如content:URIs,表示数据是在设备上,但是是由content provider控制。
数据类型也可以显式指定,比如setData(Uri)方法指定数据为Uri,setType(String type) 指定为MIME type,setDataAndType()指定它既为URI又为MIME type。读取的时候URI用getData(),MIME type用getType()。
动作与数据 |
描述 |
ACTION_VIEW content://contacts/people/1 |
查看联系人中编号为1的信息 |
ACTION_EDIT content://contacts/people/1 |
编辑联系人中编号为1的信息 |
ACTION_SENDTO mailto:[email protected] |
向指定的邮箱发送邮件 |
ACTION_DIAL tel:10086 |
预备拨打指定的号码 |
ACTION_CALL tel:10086 |
直接拨打指定的号码 |
Category是一个字符串,提供了额外的信息,有关于能够处理这个Intent对象的组件种类,一般在隐式地启动activity时需要用到。
与category相应的方法有添加addCategory()、移除removeCategory() 和获取所有category getCategories()。默认为CATEGORY_DEFAULT。常用类别如下:
类别 |
描述 |
CATEGORY_LAUNCHER |
常和 ACTION_MAIN 配合使用,标明活动会出现在应用列表中 |
CATEGORY_DEFAULT |
活动的默认类别(接收隐式意图启动的活动,至少要设置为这个类别) |
CATEGORY_APP_MUSIC |
声明该程序是一个音乐播放程序 |
CATEGORY_APP_MARKET |
声明该程序是一个应用市场 |
CATEGORY_ALTERNATIVE |
声明该活动是执行某个操作的备选 |
component name即组件名称,是要【处理】这个Intent对象的组件名称。组件名称对象由ComponentName类来封装,组件名称包含包名称和类名称,被声明在AndroidManifest.xml文件中。组件名称通过 setComponent(),setClass(),setClassName()设置,通过getComponent()获取。需要注意的是Componentname是一个可选项,如果被设置,那么Intent对象就显式指定了要转向的组件;如果没有被设置,则Intent对象需要根据其他信息进行筛选查找。
extras:传递给Intent的额外数据,以Bundle的形式定义,就是一些键值对。数据可以被作为一个Bundle对象被使用,利用 putExtras() 和 getExtras()方法。
flags:各种类型的Flag。很多是用来指定Android系统如何启动activity,还有启动了activity后如何对待它。所有这些都定义在Intent类中。
IntentFilter就是“意图过滤器”,主要用来过滤隐式意图。当用户进行一项操作的时候,Android系统会根据配置的 “意图过滤器” 来寻找可以响应该操作的组件,服务。
例如:当用户点击PDF文件的时候,Android系统就会通过设定好的意图过滤器,进行匹配测试。找到能够打开PDF文件的APP程序;此时就可能使用隐式意图打开了手机WPS,这是生活中常见到的。
Android 系统通过搜索所有程序的意图过滤器来匹配执行哪一个隐式意图;意图过滤器是对组件功能、特性的声明,一个组件(不论活动、服务还是广播接收器)都可以声明一个或多个过滤器来接收隐式意图。
在清单配置文件(manifest.xml)中为组件声明意图过滤器包含以下三个元素:
动作的名称,一个字符串常量
接收的数据类型,Uri 格式
接收的意图类型,必须包含CATEGORY_DEFAULT
在清单文件manifest.xml中为组件声明意图过滤器包含三个元素,
字段名 |
描述 |
schema |
模式:如 http、tel、content、mailto 等(全部小写字母) 若该属性未指定,除 mimeType 外的其他属性都会被忽略 |
host |
主机名,若该属性未指定,端口及所有路径属性都会被忽略 |
port |
端口号,依赖前面属性 |
path |
路径,依赖前面属性 |
pathPattern |
路径模式,依赖前面属性 |
pathPrefix |
路径前缀,依赖前面属性 |
mimeType |
Multi-Purpose Internet Mail Extensions,如 image/* |
可以给一个组件注册多个意图过滤器
实例效果如下图:
(1)创建一个新的工程,自定义命名。在主活动MainActivity对应的布局文件activity_main.xml中摆出3个Button,如上图所示。
(2)在布局文件activity_main.xml中给3个Button都添加属性
android:onClick="方法名","方法名"指定的方法需要我们自己在主活动MainActivity类中定义;当点击Button时,就会执行"方法名"指定的方法。
(3) "方法名"指定方法的实现
准备拨号
发送电子邮件
去相册选取照片
显示选取的照片
android:onClick="方法名"中,"方法名"分别替换上图所示的3个方法名doDail()、doSendMail()、doPick()即可。当点击Button时,就会执行"方法名"指定的方法。而这些方法都在方法体里创建隐式意图,系统会根据隐式意图中设置的动作(action)、类别(category)、数据URI等来匹配最合适的组件。比如点击第一个Button执行doDail()方法,就会打开拨号器;第二个会去找手机系统默认指定的“电子邮件程序”。
实例效果如下图:
(1)和上一个实例一样,创建一个新的工程,自定义命名。在主活动MainActivity对应的布局文件activity_main.xml中摆出1个EditText和2个Button,如上图所示。
(2)在布局文件activity_main.xml中给3个Button都添加属性
android:onClick="方法名"
需要自定义一个活动NextActivity,用2中方式实现从主活动MainActivity到NextActivity的跳转并携带数据。NextActivity对应的布局文件上只有一个TextView用于显示接收到的数据。
(3) "方法名"指定方法的实现
显式启动活动
隐式启动活动
工程清单文件:
xml version="1.0"encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.ljheee.intent.startactivitybyintent">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
intent-filter>
activity>
<activity android:name=".NextActivity"
android:label="NextActivity">
<intent-filter>
<action android:name="com.ljheee.intent.DATA_CONVERT"/>
<category android:name="android.intent.category.DEFAULT"/>
intent-filter>
activity>
application>
manifest>
接收传递的数据
完整工程:https://github.com/ljheee/StartActivityByIntent