您的位置:首页 > 其它

隐式意图和intentFilter匹配

2015-12-24 09:37 507 查看

隐式意图

  隐式意图:在程序中没有为
Intent
对象的
mComponent
属性明确指出想要其启动组件。

  隐式意图仅仅是为
Intent
对象指出一些筛选条件,然后
Android
系统会取出
Intent
对象中的数据和所有已经注册到系统中的组件进行匹配。
-  若匹配成功,则系统将激活该组件。
-  若有多个组件匹配成功,则系统将弹出一个对话框,要求用户选择所要激活的组件。
-  若没有任何组件匹配成功则抛异常。

  应用程序中定义的
Android
组件都需要在
AndroidManifest.xml
文件中记录。当系统在进行意图匹配时,就会取出
Intent
对象中的筛选条件与所有已注册到系统中的各个组件的
<intent-filter>
标签下定义的数据进行匹配。
  上面所说的“筛选条件”指的就是
Intent
对象以下三个方面:
1、动作(mAction)
2、数据(mData和mType)
3、分类(mCategories)

  也就是说,我们通过为Intent的上面四个属性赋值,来执行“设置筛选条件”,然后操作系统也会读取这四个属性,并用它们进行匹配。

动作

  
mAction
:是
String
类型的,用来告诉系统本次请求要执行什么样的动作。如:张三看书、李四唱歌中的
“看”
“唱”
就是指动作。在Android中内置的动作有很多,常见的有:
-  Intent.ACTION_VIEW :“查看”动作。
-  Intent.ACTION_EDIT :“编辑”动作。
-  Intent.ACTION_DELETE :“删除”动作。
-  Intent.ACTION_CALL:“呼叫”动作,通常指打电话。
-  Intent.ACTION_MAIN :标记当前Activity是程序的入口。


数据

  数据:
“动作”
所要操作的数据,显然不同的动作要跟不同的数据规范类型配合使用,比如:
-  如果动作是ACTION_VIEW,那么数据就应该指向一个可被查看的东西,比如网页、图片、视频等。
-  如果动作字段是ACTION_EDIT,那么它的数据应该指向它所要编辑的数据。
-  如果动作是ACTION_CALL,那么数据就应该是一个呼叫号码。

  再具体点说,数据包括两部分:
mData
mType

-  数据的URI(mData):用来指出数据所在的位置。如file:///tmp/android.txt。
-  数据的类型(mType):用来指出数据的MIME类型。如:text/html 。


分类

  
mCategories
“动作”
的附加信息(可以有多个)。在Android中内置的类型有:
-  Intent.CATEGORY_LAUNCHER :目标Activity能够被列在应用程序启动器上。
-  Intent.CATEGORY_BROWSABLE :目标Activity能够安全的调用浏览器来显示链接所指向的数据(如图片或电子邮件)。
-  Intent.CATEGORY_HOME :目标Activity显示在主屏幕上。


IntentFilter类

  通过前面的介绍,我们已经知道这三点:
-  创建完Activity等组件后,还需要在清单文件中配置它们,以便让系统知道这些组件的存在。
-  在配置它们的时候,除了ContentProvider之外的另外三个组件都可以配置一个或多个<IntentFilter>,它表示过滤器。
-  当我们需要启动一个组件时,整个流程是这样的:
-  首先,我们创建一个Intent对象,然后将它传递给操作系统。
-  然后,系统会检测Intent,若它是显式意图的直接启动目标组件,否则会依据Intent内部的信息进行匹配。
-  接着,如果我们调用的startActivity来启动组件,那么系统会获取当前所有注册到系统中的Activity,并获取它们的<IntentFilter>。
-  最后,让Intent对象和这些Activity的<IntentFilter>进行匹配,匹配成功就会启动该Activity,若有多个Activity都匹配成功,则系统会让用户选择启动哪一个。
-  另外,组件可以有多个<IntentFilter>标签,只要该组件有一个匹配成功,则就能启动。

  
IntentFilter
类与
<IntentFilter>
标签对应,它有类似于Intent对象的动作、数据、和分类字段。

Action匹配

  在清单文件中的
<intent-filter>
元素内的
<action>
子元素对应咱们前面说的“动作”。如:
12345

<intent-filter>    <action android:name="com.example.project.SHOW_CURRENT" />    <action android:name="com.example.project.SHOW_RECENT" />    <action android:name="com.example.project.SHOW_PENDING" /></intent-filter>

语句解释:
-  像本例显示的这样,一个过滤器可以列出多个Action。但这个列表不能是空的,一个过滤器必须包含至少一个<action>元素,否则它不会匹配任何Intent对象。
-  要通过这个检测,在Intent对象中指定的Action必须跟这个过滤器的动作列表中的某个Action一致匹配。

  

  进行意图匹配时,只有在Intent的
mAction
属性与
<intent-filter>
下的某个
<action>
标签的值匹配成功后,才会去匹配
mCategories
属性。

Category检测

  
<intent-filter>
元素内的
<category>
子元素对应前面说的“分类”。例如:
1234

<intent-filter>    <category android:name="android.intent.category.DEFAULT" />    <category android:name="android.intent.category.BROWSABLE" /></intent-filter>

  对于一个要通过
Category
检测的
Intent
对象,在
Intent
对象中所包含的每个分类,过滤器中都必须得包含,过滤器能够列出Intent中不包含的分类,但是它不能忽略
Intent
对象中的任何分类。

  因此,原则上一个没有
category
Intent
对象应该始终通过这个检测,而不管过滤器中声明的分类。
  注意:
-  所有传递给startActivity()方法的隐式Intent对象,都会至少包含了一个android.intent.category.DEFAULT。
-  只有Intent对象的mCategorie里的所有类型都匹配成功后,才会去匹配<data>标签。


Data检测

  像
Action
Category
检测一样,针对
IntentFilter
的“数据”也要包含在一个子元素中,这个子元素能够出现
0~n
次。例如:
1234

<intent-filter>    <data android:mimeType="video/mpeg" android:scheme="http" />     <data android:mimeType="audio/mpeg" android:scheme="http" /></intent-filter>

  每个
<data>
元素能够指定
URI
和数据类型(
MIME
)对于每个
URI
部分都会有独立的属性:scheme、host、port、path。格式:
1

<scheme>://<host>:<port>/[<path>|<pathPrefix>|<pathPattern>]

  例如,以下URI:
1

content://com.example.project:200/folder/subfolder/etc

-  scheme是content
-  host  是com.example.project
-  port  是200
-  path  是folder/subfolder/etc。

  其中
host
port
一起构成了
authority
,如果没有指定
host
,那么
port
也会被忽略。

开始匹配

  范例1:新建Activity。
123456

<activity android:name="org.cxy.intent.SecondActivity">    <intent-filter>        <action android:name="act.second"/>        <category android:name="android.intent.category.DEFAULT"/>    </intent-filter></activity>

  在MainActivity中书写如下跳转语句:
123

Intent intent =  new Intent();intent.setAction("act.second"); this.startActivity(intent);

语句解释:
-  本范例并没有为Intent指定具体要跳转到哪个Activity,而是为Intent指定一个action。
-  在调用startActivity方法启动Activity时,该方法会自动为Intent对象设置一个category,即:“android.intent.category.DEFAULT”。


  范例2:data匹配。
1234567

<activity android:name="org.cxy.intent.SecondActivity">    <intent-filter>        <action android:name="org.cxy.action.Second"/>        <category android:name="android.intent.category.DEFAULT"/>        <data android:scheme="http" android:host="www.cxy.com" android:port="80" android:path="/hi.jsp"/>    </intent-filter></activity>

  在MainActivity中书写如下跳转语句:
1234

Intent intent = new Intent();intent.setAction("org.cxy.action.Second");intent.setData(Uri.parse("http://www.cxy.com:80/hi.jsp"));this.startActivity(intent);

语句解释:
-  使用scheme属性匹配代码中的协议名。
-  使用host属性匹配代码中的主机名,使用此属性之前,必须要先指定scheme属性,在代码中scheme和host之间要写上“://”作为间隔。
-  使用port属性匹配代码中的端口号,使用path属性匹配代码中的路径。


  范例3:数据类型匹配。
12345678

<activity android:name="org.cxy.intent.SecondActivity">    <intent-filter>        <action android:name="org.cxy.action.Second"/>        <category android:name="android.intent.category.DEFAULT"/>        <data android:scheme="http" android:host="www.cxy.com" android:port="80"                 android:path="/hi.jsp" android:mimeType="image/gif"/>    </intent-filter></activity>

  在MainActivity中书写如下跳转语句:
1234

Intent intent = new Intent();intent.setAction("org.cxy.action.Second");intent.setDataAndType(Uri.parse("http://www.cxy.com:80/hi.jsp"),"image/gif");this.startActivity(intent);

语句解释:
-  使用mimeType属性可以对数据的MIME类型进行限制。
-  使用setData方法设置Intent的Uri,使用setType方法设置Intent的MIME类型。
-  但是如果你想同时设置这两者,则只能使用setDataAndType方法,因为setData和setType方法中会彼此清除对方的值,具体请查看源码。


  在
<intent-filter>
中可以不列出
<data>
元素,但是只要列出了,那么
<data>
中所列出的所有属性都得匹配。

  范例4:假设我们有如下配置:
1234567

<activity android:name=".B">    <intent-filter>        <action android:name="aa.test.BBBBBB"/>        <category android:name="android.intent.category.DEFAULT"/>        <data android:mimeType="image/*"/>    </intent-filter></activity>

  那么我们可以用如下代码进行匹配:
1234

Intent intent = new Intent();intent.setAction("aa.test.BBBBBB");intent.setDataAndType(Uri.parse("content://abc"),"image/png");startActivity(intent);

语句解释:
-  也就是说,虽然我们没有为<data>元素设置scheme属性,但是它却存在默认值,会默认匹配“file”、“content”。
-  另外,在<data>元素的path和mimeType属性的值中,都可以包含通配符“*”,用来匹配0~n个任意字符。


  范例5:安装应用程序。
1234

Intent intent = new Intent(Intent.ACTION_VIEW);// Uri.fromFile()方法根据文件对象的路径来构造一个Uri。intent.setDataAndType(Uri.fromFile(file),"application/vnd.android.package-archive");startActivity(intent);

语句解释:
-  本范例使用系统内置的ACTION_VIEW动作安装APK文件。
-  ACTION_VIEW动作所要操作的数据的Uri是通过一个File对象的路径构造出来的。
-  ACTION_VIEW动作用于“查看”,该动作会根据其所要查看的数据的MIME类型的不同,来调用不同的应用程序来查看数据。
-  APK文件的MIME类型为application/vnd.android.package-archive ,而查看APK文件,其实就是安装APK文件。


  范例6:卸载应用程序。
1234

Intent intent = new Intent();intent.setAction(Intent.ACTION_DELETE);intent.setData(Uri.parse("package:"+ this.getPackageName()));startActivity(intent);

语句解释:
-  调用系统内置的ACTION_DELETE动作可以执行删除操作。
-  若删除的数据为:“package:应用程序包名”,则相当于卸载该应用程序。
-  调用Activity的getPackageName()方法可以获取当前应用程序的包名称。


  范例7:启动发送短信Acitivity。
12345678

Intent intent = new Intent();// 设置意图的动作为“发送”和“发送数据”的MIME类型。intent.setAction(Intent.ACTION_SEND);intent.setType("text/plain"); // 设置要发送的 正文数据。intent.putExtra(Intent.EXTRA_TEXT, "Hi 发送短信哦!");startActivity(intent);

语句解释:
-  程序运行时会打开系统发送短信界面。


扩展:
当我们使用隐式意图启动一个A时,可以做一下判断,看是否有A能够匹配我们的隐式意图,如果不判断就有可能因找不到而报错。
所以我们采用:

  
PackageManager
类中有一组
query…()
以及
resolve…()
方法。

  前者返回能够接受一个特殊
Intent
对象的所有组件,后者返回最佳匹配结果(即只返回1个结果),例如:
-  queryIntentActivities(Intent intent,int flags)方法返回能够执行这个Intent对象的所有Activity。

第二个参数我们使用:MATCH_DEFAULT_ONLY 这个表示仅仅匹配那些intent-filter中声明的

<category android:name="android.intent.category.DEFAULT"/>的Activity。因为不含有Default的那些Activity是无法接受隐式意图。
-  queryIntentServices()方法类似地返回Service列表。
-  queryBroadcastReceivers()方法类似地返回Broadcast Receiver列表。

  这些方法都不激活组件,它们只是列出能够响应这个
Intent
对象的所有组件。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: