您的位置:首页 > 移动开发 > Android开发

Intent的匹配规则

2016-07-09 15:34 495 查看


intent是android中作为启动四大组件的粘合剂,中文意思是意图。intent是某种将要执行的操作的抽象描述,它可以通过startActivity(Intent) 启动activity,sendBroadcast(Intent)匹配BroadcastReceiver,startService(Intent)或者bindService(Intent)调动后台service。当然在我们android开发中最主要的是用来在activity之间进行交互,因为intent的可以携带基于将要执行的操作的信息,所以Intent
Resolution(android中专门用于匹配和过滤intent filter的进程)能够匹配出最合适的处理容器。

在intent中最主要的数据资料是:

(1)action:即将要执行的活动,通常是用字符串表示,比如:“android.intent,action.VIEW“,但其实android已经定义好了大量常量,我们直接使用即可,比如Intent.ACTION_VIEW就是“android.intent,action.VIEW“的常量。

(2)data:将被所执行的活动所处理的数据,通常用Uri的形式表示,在后面会有更详细的解析,这里先大概了解一下。

一对action/data集合,就能翻译成我们能理解的类似人类语言的句子,但前提是我们必须知道action的意思是什么(Intent中为action定义的常量实在太多,读者在需要的时候需自行查阅相关资料),比如我们看下面的一对action/data集合,
Intent  intent=new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.setData(Uri.parse("content://contacts/people/1"));
翻译中中文意思是查找通讯录中identifier是1 的人的通讯信息。为什么是这么理解呢。我们查看Intent.ACTION_VIEW的源码,可以知道这个action是用来给用户展示数据的意思。所要处理的数据是,通讯录数据库中identifier是1的people的数据,总的意思就是我前面说的意思。

intent中还有一些可有可没有的附加数据资料,因为在隐式意图(android启动一个容器可通过显示意图和隐式意图两种方式)中经常需要使用到,所以必须要了解和掌握各数据属性的意思。

(1)category:用于给将要执行的action附加说明,这么说很晦涩难懂。看下面的图片:



上面的话就是给action添加了category信息,其中category的意思是当前的容器将作为应用的启动器运行。也就是说当前的容器的启动方式是作为当前应用的启动器来运行。

(2)type:用于指定data的MIME类型(比如image/jpeg),通常情况下系统会根据data来推断所请求的数据的mime类型,但如果明确指出了type属性值,那么系统就会使用当前的type值而不会再对data进行mime类型的推断。

(3)component:用于显式的指定所要启动的容器是什么,一旦指定了这个值,那么其它所有的数据资料(data、action......)都变的是可有可无的。

(4)extras:额外的数据,通常是通过bundle捆绑一些参数,在两个容器之间进行数据的传递。

Intent可分为两种意图,分别为显示意图和隐式意图,后者的匹配规则相对复杂,需要细心了解,接下来会带来详细的规则匹配解析。
(1)显示意图:通常来说如果我们很明确的知道我们需要启动的容器是什么,那么我们就可以使用显示意图。使用方法看下图:



(2)隐式意图:隐式意图的匹配规则比较复杂,Intent Resolution进程通过过滤intent 的action,data,category......数值来匹配哪个是最合适的能够处理此意图的容器。各字段的匹配规则如下:
①:action:上面已经说过action其实是一个String的值,除了系统定义好的action常量之外,我们也可以自定义常量,要注意的是action是区分大小写的。在Intent中我们指定的action只要和intent-filter中任意一条action一样,就可以匹配成功。如果使用隐式意图,action字段是不能缺少的。

②:category:category同样是一个String的值,除了系统定义好的category常量之外,我们也可以自定义常量,同时,category也是区分大小写的。不同于action,在intent中,我们是可以通过Intent.addCategroy(String )来添加多个category,intent中所有的category必须在过滤规则中有定义,否则将匹配失败。需要注意的是,如果给某个容器指定了category规则,那么我们必须加上"android.intent.categroy.DEFAULT”这个值,因为在startActivityhe
startActivityForResult中,系统会默认为我们的intent加上此字段值,如果我们的过滤规则没有写这个值,会匹配失败。

③:data:data是Uri形式的值,data的匹配规则和action一样,一旦intent中设置了data,那么只要和过滤规则中的任意一条一样,就可以匹配成功。在过滤规则中,data主要有两部分组成,uri和mimetype。看图:



其中除了mimeType字段外,其它所有的字段都是Uri的组成部分。scheme表示模式,如果这个值没有指定,那么整个uri是没有意义的,host表示主机,这个值没有写,uri也是没有意义的。port表示端口,必须结合host使用,否则也没有意义。path表示路径,pathPattern表示路径的完整匹配模式,pathPrefix表示路径的前缀。为了匹配图片的过滤规则,需要调用intent.setDataAndType()方法,在这里是intent,setDataAndType(Uri,parse("file://hy:88/image/imagePath/jpg","image/jpeg"),前面的参数是uri,后面的是对应的mimeType类型。

上面讲了这么多规则,下面我们通过一个例子来讲解,希望通过例子可以引导大家理解。看下面的AndroidManifest,xml代码:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.hy.androidart">

<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"
android:configChanges="orientation">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".TestActivity">
<!--intent-filter可以有多组,只要匹配其中的一组就可以成功启动当前的容器-->
<span style="color:#ff6666;"><!--①--></span>
<intent-filter>
<action android:name="android.intent.action.a" />

<category android:name="android.intent.category.b" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<span style="color:#ff6666;"><!--②--></span>
<intent-filter>
<action android:name="android.intent.action.c" />
<action android:name="android.intent.action.d" />

<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.e" />
<category android:name="android.intent.category.f" />
<category android:name="android.intent.category.g" />
</intent-filter>
<!-- 这一组没有category android:name="android.intent.category.DEFAULT" -->
<span style="color:#ff6666;"><!--③--></span>
<intent-filter>
<action android:name="android.intent.action.h" />
<category android:name="android.intent.category.i" />
</intent-filter>
<span style="color:#ff6666;"><!--④--></span>
<intent-filter>
<action android:name="android.intent.action.j" />
<category android:name="android.intent.category.k" />
<data
android:host="hy"
android:mimeType="image/jpeg"
android:path="/path"
android:pathPattern="/pattern"
android:pathPrefix="/prefix"
android:port="88"
android:scheme="content" />
</intent-filter>
</activity>
</application>

</manifest>


接下来我们主要通过隐式意图来启动TestActivity的例子来讲解各种匹配规则的使用(后面都省略了startactivity(intentn)语句)。
(1)
Intent intent=new Intent();
intent.setAction("android.intent.action.a");
会匹配第一组,所以会成功启动。你也许会疑惑为什么只匹配了action不用匹配category也能成功启动。还记得前面说的startactivity会自动给当前的intent添加"android.intent.categroy.DEFAULT”吗?因为有了这个category,所以和第一组的匹配成功。
(2)
Intent intent=new Intent();
intent.setAction("android.intent.action.d");
intent.addCategory("android.intent.categroy.e");
intent.addCategory("android.intent.category.f");
会匹配第二组,所以会成功启动,注意这里添加了两个category,这两个category必须全部在过滤规则中声明才能正确启动。
(3)
Intent intent=new Intent();
intent.setAction("android.intent.action.h");
不能匹配第三组,所以启动失败,因为startactivity会默认给当前intent添加“android.intent.category.DEFALT”,而第三组的过滤规则却没有写所以启动不起来。以后当我们声明了category,就必须加上“android.intent.category.DEFALT”这个值,以满足系统的匹配规则。

(4)
Intent intent=new Intent();
intent.setAction("android.intent.action.j");
intent.addCategory("android.intent.category.k");
intent.setDataAndType(Uri.parse("content://hy:88/path/pattern/prefix"),"image/jpeg");


会匹配第四组,所以成功启动,在这里主要目的是要明白怎么拼写data的Uri值,data的拼写规则是:scheme://host:post/path/pattern/pathPrefix
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息