在android中,Intent的使用可算是无处不在,它起到了媒介的作用,可以当做一条指令,或者一种协议。它的作用是告诉android系统要做什么和怎么做
该Intent对象组要由六部分,分别是Component name,Action,Data,Category,Extras以及Flags。那么这些部分分别起到什么作用,以及在何时应该如何使用呢,下面做一下简单的讲解。
1,Component name
顾名思义,这指的是组件的名称。即要把该Intent对象传递给它的那个组件。组件名称对象由ComponentName类来描述,包含包名称和类名称,并且该组件肯定会被声明在AndroidManifest.xml中。
组件名称通过 setComponent(),setClass(),setClassName()设置,通过getComponent()获取。
需要注意的是Component name是一个可选项,如果被设置,那么Intent对象就显式指定了要转向的组件,如果没有被设置,则Intent对象需要根据其他信息进行筛选查找。
例如:当前有LocalService1和LocalService2两个Service,并在AndroidManifest.xml文件中的配置如下:
<service android:name=".services.LocalService1"> <service android:name=".services.LocalService2"> |
String packageName = getPackageName() ; Intent intent = new Intent() ; intent.setComponent(component) ; |
intent.setClassName(packageName,className) ; |
这我们指定了Intent会被发送到的对象为LocalService2
2,Action
这个指定的是一个动作,它是一个字符串类型。在Intent类里面定义了很多有关Action的常量,这些常量对应的都是Android系统提供的一些供用户使用的功能。当然我们是可以自定义Action的,只需要定义一个字符串即可,但是需要注意的是,该字符串应该使用你的应用的包名作为前缀!
Action这部分的内容十分的关键,应该它会决定其它部分的内容如何构造,例如这个动作是“发邮件”,那么其它部分的内容就需要安装“邮件”的协议来构造数据。 Action的不同,主要会影响Data和
Extras的不同。
Action的设置方式如下:
Intent intent = new Intent() ; intent.setAction("com.example.test.LocalService2") ; |
请思考,如果使用以下的方式来设置Intent,会启动哪个Service
String packageName = getPackageName() ; intent.setAction("com.example.test.LocalService2") ; |
答案是启动LocalService1,只有没有设置Component name才会按照Action去查找。
3,Data
在讲Data之前,先说说URI(统一资源标识符)。
互联网上(包括本地)有许多的资源,包括图片,视频,程序等等,然而我们需要一种统一的标准来定位各样的资源,这就是URI,它其实就是一个字符串而已。我们可以通过URI使用特定的协议和资源进行交互。
URI文法结构: URI协议名:协议对应的内容
URI协议名有很多,例如:http, ftp,mailto,file等等,每一种协议都决定了协议内容的语法和语义,例如,如果是http协议,那么协议内容就要指定主机名,端口号,资源路径等;如果是mailto协议,那么协议内容就需要指定邮箱地址等。
在android中,动作和数据是匹配的,Data描述的是相应动作要处理的数据资源信息。Data所包含的内容如下:
<data android:scheme=""/> <data android:pathPattern=""/> |
那么在使用的时候哪些需要设置,哪些不需要设置呢? 这其实和使用Intent的那个组件有关,如果那个组件是浏览器,那么我们可能就需要可以主机,端口号,路径等信息。
如果AndroidManifest.xml文件中的配置为:
<service android:name=".services.LocalService2"> <data android:scheme="file"/> <data android:mimeType="text/html" /> </service> |
在intent-filter中指定data属性的实际目的是:要求接收的Intent中的data必须符合intent-filter中指定的data属性,这样达到反向限定Intent的作用。
那么在启动这个Service的时候,Intent的写法如下:
Intent intent = new Intent() ; intent.setAction("com.example.test.LocalService2") ; Uri uri = Uri.parse("file://com.android.test:500/mnt/sdcard"); intent.setDataAndType(uri, "text/html") ; |
data属性解析:android:scheme、android:host、android:port、android:path、android:mimeType
data的前四个属性构成了URI的组成部分,mimeType设置了数据的类型
data元素组成的URI模型如下:
scheme://host:port/path |
举例说明(URI ):
file://com.android.test:500/mnt/sdcard |
scheme-->file:
host-->com.android.test
port-->500
path-->mnt/sdcard
其中host和port为URI的authority,如果没有指定host,port将被忽略。
data的各属性并不是独立的,data的各属性构成了URI的整个组成部分。要使authority(host和port)有意义,必须指定scheme;要使path有意义,必须使scheme和authority(host和port)有意义。
URI和intent-filter匹配:
Intent中URI和intent-filter进行比较的时候只会进行部分的比较:
(1)当intent-filter中只设置了scheme,只会比较URI的scheme部分;
(2)当intent-filter中只设置了scheme和authority,那么只会匹配URI中的scheme和authority;
(3)当intent-filter中设置了scheme、authority和path,那么只会匹配URI中的scheme、authority、path;(path可以使用通配符进行匹配)
(4)当intent-filter中设置了mimeType,还会进行数据类型的匹配。
常用的Data的URI格式如下:
tel://:号码数据格式,后跟电话号码。
mailto://:邮件数据格式,后跟邮件收件人地址。
smsto://:短息数据格式,后跟短信接收号码。
content://:内容数据格式,后跟需要读取的内容。
file://:文件数据格式,后跟文件路径。
market://search?q=pname:pkgname:市场数据格式,在Google Market里
搜索包名为pkgname的应用。
geo://latitude,longitude:经纬数据格式,在地图上显示经纬度指定的位置。
4,Category
Intent中的类别是一种被执行动作的额外信息。Category是一个字符串,在Intent中提供了一些默认的Category字符串常量。例如 LAUNCHER_CATEGORY 表示Intent 的接受者应该在Launcher中作为顶级应用出现;而ALTERNATIVE_CATEGORY表示当前的Intent是一系列的可选动作中的一个,这些动作可以在同一块数据上执行。
常用的CATEGORY常量及说明:
CATEGORY_DEFAULT:Android系统中默认的执行方式,按照普通Activity的执行方式执行。
CATEGORY_HOME:设置该组件为Home Activity。
CATEGORY_PREFERENCE:设置该组件为Preference。
CATEGORY_LAUNCHER:设置该组件为在当前应用程序启动器中优先级最高的Activity,
通常为入口ACTION_MAIN配合使用。
CATEGORY_BROWSABLE:设置该组件可以使用浏览器启动。
CATEGORY_GADGET:设置该组件可以内嵌到另外的Activity中。
5,Extras
附加信息,是其它所有附加信息的集合。使用extras可以为组件提供扩展信息,比如,如果要执行“发送电子邮件”这个动作,可以将电子邮件的标题、正文等保存在extras里,传给电子邮件发送组件。
6,Flags
预定义一系列用来控制Intent行为的属性值。
intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT); 如果activity在task存在,拿到最顶端,不会启动新的Activity |
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 如果activity在task存在,将Activity之上的所有Activity结束掉 |
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 默认的跳转类型,将Activity放到一个新的Task中 |
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); 如果Activity已经运行到了Task,再次跳转不会在运行这个Activity |