Intent和IntentFilter

Posted devbird

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Intent和IntentFilter相关的知识,希望对你有一定的参考价值。

作为四大组件的枢纽,Intent和IntentFilter起着功不可没的作用,所以有必要好好做个总结。

一、Intent

Intent分为两种类型:显式Intent、隐式Intent

  • 显示Intent:指定要启动组件的名称(类的全路径名)
// Executed in an Activity, so 'this' is the Context
// The fileUrl is a string URL, such as "http://www.example.com/image.png"
Intent downloadIntent = new Intent(this, DownloadService.class);
downloadIntent.setData(Uri.parse(fileUrl));
startService(downloadIntent);
  • 隐式Intent:不指定特定的组件,而是通过设置常规操作,如:ActionDataCategory
// Create the text message with a string
Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, textMessage);
sendIntent.setType("text/plain");

// Verify that the intent will resolve to an activity
if (sendIntent.resolveActivity(getPackageManager()) != null) 
    startActivity(sendIntent);

在构造Intent的时候可以给这个Intent指定这些信息:
Component nameActionDataCategoryExtrasFlags

Component name:主要是用来指定组件名称,可以通过setComponent()setClass()setClassName() 或者直接通过Intent的构造函数来指定组件名称。
示例:

 Intent intent = new Intent();
 //Intent intent = new Intent(this, BJActivity.class);//通过构造函数指定组件名
 ComponentName component = new ComponentName(this, BJActivity.class);
 intent.setComponent(component);//通过setComponent()方法指定组件名
 //intent.setClass(this, BJActivity.class);//通过setClass()指定组件名
 //intent.setClassName(this, "com.tiandawu.nougat.BJActivity");//通过setClassName()指定组件名
 startActivity(intent);

Action:主要用来指定Intent的动作,可以通过setAction() 来指定Intent的动作。
示例:

Intent intent = new Intent();
intent.setAction(Intent.ACTION_CALL);//拨打电话的动作
intent.setData(Uri.parse("tel:10086"));//携带的数据
this.startActivity(intent);

Action的种类很多,具体种类可以去官网的Intent类中查看。

Data:主要用来指定Intent携带的数据,可以通过setData() 来指定Intent携带的数据。例如上面的例子中就就通过setData 来指定携带了电话号码。

setData()和setType()的注意事项:
当要指定data和type的时候请使setDataAndType(),因为用setData和setType()来分别制定data和type时,setData()和setType()都会清除对方的值。

Category:主要用于隐式Intent,用来指定类别,通过addCategory() 来指定类别。主要用途是用来匹配Intent-Filter中的<category> 标签中的元素。后面会在IntentFilter中作详细讲解。

Extras: 主要用于携带完成请求操作所需的附加信息的键值对,通过putExtra() 方法来存入键值对。
示例:

intent.putExtra("strKey", "strValue");//存入一个字符串键值对
intent.putExtra("intKey", 20);//存入一个int型的键值对

putExtra() 能存入很多基本数据类型,还可以put对象,通过这个方法就可以完成Activity之间的数据交互。

Flags 见名思意,可以用来携带标志,通过setFlags() 就可以指定所需要的标志。
示例:

Intent intent = new Intent();
intent.setClass(this, MyActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);//新开一个任务栈,来启动Activity
startActivity(intent);

能指定的Flags有很多,具体的Flags有哪些可以去官网的Intent类中查看。


二、IntentFilter

IntentFilter是用来过滤Intent的,当用隐式Intent来启动一个Activity的时候,就会匹配Intent携带的信息和intent-filter 中的过滤信息,当这些信息匹配成功则启动Activity。intent-filter 的过滤信息分为三类,分别是:action类category类data类
一个<Activity> 节下面可以包含多个<intent-filter> 节,当一个Intent能匹配任何一个<intent-filter> 中的action类category类data类 时则匹配成功,此时才能启动目标Activity。

下面是一个Activity中的过滤规则示例:

<activity android:name=".TestActivity" >
    <!--第一组intent-filter-->
    <intent-filter>
        <action android:name="com.tdw.action_1" />
        <action android:name="com.tdw.action_2" />
        <category android:name="com.tdw.category_1" />
        <category android:name="com.tdw.category_2" />
        <category android:name="android.intent.category.DEFAULT" />
        <data android:mimeType="image/*" />
        <data android:mimeType="video/*" />
    </intent-filter>
    <!--第二组intent-filter-->
    <intent-filter>
        <action android:name="com.tdw.action_group_2" />
        <category android:name="android.intent.category.DEFAULT" />
        <data android:mimeType="image/*" />
    </intent-filter>
</activity>

在这个<Activity>中有两组<intent-filter>,只要一个Intent能匹配其中任意一组<intent-filter>即可。这里的匹配是指需要同时匹配一组中的action类别、categroy类别和data类别。
下面分别详细介绍这三个类别的匹配规则。

1、action 的匹配规则
从上面的例子中可以看出,一个intent-filter中可以有多个action,如果Intent中的action和过滤规则中action的字符串相同(区分大小写),则匹配。如果intent-filter中有多个action,那么只要匹配上过滤规则中的一个action也算匹配成功。如果Intent中没有指定action或则与intent-filter中的action一个也没匹配上,则匹配失败。比如:Intent中action的值为com.tdw.action_1com.tdw.action_2就算匹配成功,如果一个都不相同则匹配失败。

2、category 的匹配规则
category 的匹配规则和action的匹配规则有所不同。如果Intent中携带了category,不管有几个category,对于携带的每个category 来说,它必须是过滤规则中已经定义好了的category。但是Intent中也可以没有携带category,如果没有的话也可以匹配成功,因为系统在调用startActivity 或者 startActivityForResult 的时候会默认为Intent加上“android.intent.category.DEFAULT”这个category。与action 不同的是,action 是要求Intent中必须有一个action 且必须能够和过滤规则中的某个action 相同。

3、data的匹配规则
要了解data 的匹配规则首先要了解data 的语法,所以还是先来学习data 的语法。

data 的语法示例:

<data
   android:scheme="string"
   android:host="string" 
   android:por="string"
   android:path="string"
   android:pathPattern="string"
   android:pathPrefix="string"
   android:mimeType="string"/>

data 由两部份组成,mimeType和URI。mimeType指媒体类型,比如:image/jpegvideo/* 可以分别表示图片和视频。mimeType的媒体类型有很多,具体需要用时可以去查看。而URI中包含的数据就比较多了,URI的结构如下:

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

具体示例:
content://com.example.project:200/folder/subfolder/et
http://www.google.com:80/search/info

通过两个具体示例和URI的结构示例对照看就很清楚URI的含义了。
scheme: URI的模式,比如http、file、content等,如果URI中没有指定scheme,那么整个URI的其他参数无效,这也意味着URI无效。
host: URI的主机名,比如:www.google.com,如果host为指定,那么整个URI的其他参数无效,这也意味着着URI无效。
port: URI的端口号,比如:80,仅当URI中指定了scheme和host参数的时候port参数才是有意义的。
path、pathPattern、和pathPrefix: 这三个参数表述路径信息,其中path表示完整的路径信息; pathPattern也表示完整的路径信息,大师它里面可以包含通配符(*), 通配符(*) 表示0个或多个任意字符,需要注意的是,由于正则表达式的规范,如果想表示真实的字符串,那么* 要写成\\\\* ,\\要写成\\\\\\;pathPrefix 表示路径的前缀信息。

data 的匹配规则和action 类似,它也要求Intent中必须含有data 数据,并且data 数据能够完全匹配过滤规则中的某一个data。这里的完全匹配是指过滤规则中出现的data 部分也出现在了Intent中的data 中。

  • 示例1:
<intent-filter>
    <data android:mimeType="image/*" />
    ...
</intent-filter>

这个示例当中,mimeType指定的媒体类型是图片,那么Intent中的mimeType属性也必须为”image/*“才能匹配,这种情况下虽然没有指定URI,但是确是有默认值,URI的默认值为contentfile。也就是说,虽然没有指定URI,但是Intent中的URI部分的scheme 必须为content或则file才能匹配。所以Intent中的scheme 可以这么写:

intent.setDataAndType(Uri.parse(“file://abc”),”image/*”)

注意的是:如果要为Intent指定完整的data ,必须用setDataAndType 方法,不能先调用setData 再调用setType ,因为这两个方法在调用时会彼此清除对方的值。

  • 示例2:
<intent-filter>
    <data android:mimeType="video/mpeg" android:schema="http" .../>
    <data android:mimeType="audio/mpeg" android:scheme="http" .../>
    ...
</intent-filter>

这种规则指定了两组data 规则,且每个data 都指定了完整的属性值,既有URI又有mimeType。为了匹配示例2中的规则,可以在写出如下示例:

intent.setDataAndType(Uri.parse(“http://abc“),”video/mpeg”)

或则是

intent.setDataAndType(Uri.parse(“http://abc“),”audio/mpeg”)

  • 示例3:
<!--第一种-->
<intent-filter>
    <data
        android:scheme="file"
        android:host="www.google.com" />
    ...
</intent-filter>
<!--第二种-->
<intent-filter>
    <data android:scheme="file" />
    <data android:host="www.google.com" />
    ...
</intent-filter>

这是 data 特殊情况,如上两种写法,作用是一样的。


参考书籍: Android开发艺术探索
参考网站: Android官方文档

以上是关于Intent和IntentFilter的主要内容,如果未能解决你的问题,请参考以下文章

Intent和IntentFilter

详解intent和intentfilter

IntentFilter

Intent和IntentFilter

Intent和IntentFilter

Intent和IntentFilter