回头看Android之Intent

什么是Intent
intent实际上就是Android的一种消息传递机制。通过这种消息传递机制,同一应用中的不同组件可以进行交互与通讯,不同应用中的不同组件也可以进行交互和通讯。

什么是Intent-filter
Intent-filter通常被译为“意图过滤器“,实际上我认为把它理解为一种“匹配器“可能会更好。顾名思义,Android系统中,存在很多的不同应用。当一个应用发出请求时,那么这个请求到底是发送给哪个的呢?比如,老师在讲台上说:”你去扫地“,”你去擦窗户“。这里的”你“肯定是指的某一位同学,而不是指的全班同学。因此,Intent-filter实际上做的就是一种”意图的匹配“。当发送出来的Intent被其他组件接受并匹配到了之后才去执行操作,而不匹配的就用不着去执行操作了。

Intent概述
Intent可以用来启动activity,service,broadcast。
Intent可以传递数据。
Intent有6种属性(Component、Action、Data、Category、Extra、Flag)。通过这6种属性的设置可以对发送的Intent进行细致的描述,同时Android也会根据这些属性来解析Intent,并找到匹配的组件并启动它。
Intent有2种用法,一种是显示的Intent,一种是隐式的Intent。
实际上,这两种用法的本质区别就是看是否指定了Intent的component属性。

/显示Intent/

//创建一个ComponentName对象
ComponentName componentName = new ComponentName(
IntentDemoActivity.this, SecondActivity.class);
Intent intent = new Intent();
//设置Intent的Component属性
intent.setComponent(componentName);
//启动SecondActivity
startActivity(intent);

这种写法还比较少见,通常我们常见的是这样的写法

Intent intent = new Intent(IntentDemoActivity.this, SecondActivity.class);
//启动SecondActivity
startActivity(intent);

可以看到,显示的Intent需要指定具体的,明确的component属性。具体来说就是要给出目标组件的名称,即需要指定完整的包名和类名。因为对于本程序以外的其他应用程序,你很难知道它的组件名字。所以,这种显示Intent通常是用于应用程序的内部通信和交互,更确切的说,显示Intent是用于应用程序内部启动组件,通常又是Activity或Service,还没有见用显式Intent来给BroadcastReceiver发送广播的。

而对于隐式的Intent来说,由于没有指定component属性,因此需要指定其他属性来寻找目标组件。
/隐式Intent/

Intent it = new Intent();
it.setAction("com.google.test");
startActivity(it);

6种属性解释
1、component
组件名称实际上就是一个ComponentName对象,用于标识唯一的应用程序组件,即指明了期望的Intent组件,这种对象的名称是由目标组件的类名与目标组件的包名组合而成的。

2、action
Action实际上就是一个描述了Intent希望或者说将要触发的动作的名称(用字符串表示)。在Intent类中,Android已经定义了一些系统常量来表示不同的Action。当然,开发人员也可以自定义Action,其定义规则同样非常简单,但必须保证这个动作的名称是一个独一无二的字符串,所以通常使用基于Java包的命名方式来命名这个字符串。

系统定义的Action常量有很多,下面只列出其中一些较常见的。

ACTION_CALL,拨出Data里封装的电话号码。
ACTION_EDIT,打开Data里指定数据所对应的编码程序。
ACTION_VIEW,打开能够显示Data中封装的数据的应用程序。
ACTION_MAIN,声明程序的入口,该Action并不会接收任何数据,同时结束后也不会返回任何数据。
ACTION_BOOT_COMPLETED,BroadcastReceiver Action的常量,表明系统启动完毕。
ACTION_TIME_CHANGED,BroadcastReceiver Action的常量,表示系统时间通过设置而改变。

//声明一个Intent对象
Intent intent = new Intent();
/**
* 设置Action属性,这里是跳到拨号界面
* ACTION_DIAL = "android.intent.action.DIAL";
*/
intent.setAction(Intent.ACTION_DIAL);
startActivity(intent);

Action很大程度上决定了Intent的另外部分的结构, 就像一个方法名决定了它接受的参数和返回值一样. 因此, 最好给Action一个最能反映其作用的名字.也就是说我们取得名字,最好是让人一眼就能看出来,这个action所代表的动作。一个Intent对象中的Action是使用getAction()和setAction()来读写的.

3、data
Data主要是对Intent消息中数据的封装,主要描述Intent的动作所操作到的数据的URI及类型。不同类型的Action会有不同的Data封装,例如打电话的Intent会封装tel://格式的电话URI,而ACTION_VIEW的Intent中Data则会封装http:格式的URI。正确的Data封装对Intent匹配请求同样非常重要。

 //声明一个Intent对象
Intent intent = new Intent();
/**
* 设置Action属性,这里是跳到拨号界面
* ACTION_DIAL = "android.intent.action.DIAL";
*/
intent.setAction(Intent.ACTION_DIAL);
Uri uri = Uri.parse("tel:0-123-456-789");
intent.setData(uri);
startActivity(intent);

4、category
Category是对目标组件类别信息的描述。同样作为一个字符串对象,一个Intent中可以包含多个Category。Android系统同样定义了一组静态字符常量来表示Intent的不同类别,下面列出一些常见的Category常量。

CATEGORY_GADGET,表示目标Activity是可以嵌入到其他Activity中的。
CATEGORY_HOME,表明目标Activity为HOME Activity。
CATEGORY_TAB,表明目标Activity是TabActivity的一个标签下的Activity。
CATEGORY_LAUNCHER,表明目标Activity是应用程序中最先被执行的Activity。
CATEGORY_PREFERNCE,表明目标Activity是一个偏好设置的Activity。

一个Intent最多只能包含一个Action属性,但是一个Intent中可以包含多个Category属性

5、Extra

Extra中封装了一些额外的附加信息,这些信息是以键值对的形式存在的。Intent可以通过putExtras()与getExtras()方法来存储和获取Extra。在Android系统的Intent类中,同样对一些常用的Extra键值进行了定义,如下所示。

EXTRA_BCC,装有邮件密送地址的字符串数组。
EXTRA_EMAIL,装有邮件发送地址的字符串数组。
EXTRA_UID,使用ACTION_UID_REMOVED动作时,描述删除用户的id。
EXTRA_TEXT,当使用ACTION_SEND动作时,描述要发送文本的信息

Intent it = new Intent(Activity.Main.this, Activity2.class);
Bundle bundle=new Bundle();
bundle.putString("name", "This is from MainActivity!");
it.putExtras(bundle);       // it.putExtra(“test”, "shuju”);
startActivity(it); 

6、Flag
一些有关系统如何启动组件的标志位,Android同样对其进行了封装

Intent-filter
前面说了, 显示的Intent就根据指定的component,直接找到目标组件并启动它就OK了。而隐式的Intent的因为没有指定component属性,所以只好借助其他属性来描述目标组件的特征。同样的,Android收到了这些特征的描述就会进行”特征匹配“。而实现这个功能的,就是Intent-filter。
先来看个实例

    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:screenOrientation="landscape" android:name=".RadioActivity" 
                  android:theme="@android:style/Theme.NoTitleBar"
                  android:launchMode="singleTask">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
            <intent-filter>
                <action android:name="com.my.radio.RadioActivity" />
                <category android:name="android.intent.category.DEFAULT" />             
            </intent-filter>
        </activity>
    </application>

IntentFilter过滤Intent时,一般是通过Action、Data及Category三方面进行监测的。

(1)检查Action
一个Intent只能设置一种Action,但是一个IntentFilter却可以设置多个Action过滤。

当IntentFilter设置了多个Action时,只需一个满足即可完成Action验证。
当IntentFilter中没有说明任何一个Action时,那么任何的Action都不会与之匹配。
如果Intent中没有包含任何Action,那么只要IntentFilter中含有Action时,便会匹配成功。

(2)检查Data
数据的监测主要包含两部分,即数据的URI及数据类型,而数据URI又被分成三部分进行匹配(scheme、authority、path),只有这些全部匹配时,Data的验证才会成功。

(3)检查Category
IntentFilter同样可以设置多个Category,当Intent中的Category与IntentFilter中的一个Category完全匹配时,便会通过Category的检查,而其他的Category并不受影响。但是当IntentFilter没有设置Category时,只能与没有设置Category的Intent相匹配。

关于Intent-filter的几点注意事项
1、在manifest中,我们通常都会看到这两个Intent-filter成对出现

<intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
</intent-filter>

实际上这两个是系统默认添加的,其中android.intent.action.MAIN是决定一个app最先启动那个组件,而android.intent.category.LAUNCHER决定是否在桌面上显示该app的图片。

2、
前文提到,Intent-filter实际上是与隐式Intent关联在一起的。而在这里需要特别注意的是:每一个通过startActivity()方法发出的隐式Intent,系统都默认会为其添加一个category,即”android.intent.category.DEFAULT”。所以如果想让目标组件能够被成功启动,那么就要在其的manifest中Intent-filter添加这个属性,如下所示 。

<activity android:name="com.gesture.QGestureListActivity">
     <intent-filter>  
           <action android:name="com.google.test" />
           <category android:name="android.intent.category.DEFAULT" />
 </intent-filter> 
</activity>

3、关于intent-filter匹配优先级
首先查看Intent的过滤器(intent-filter),按照以下优先关系查找:action->data->category

其他的
个人认为,Google对于intent-filter的说明不太友好,其中有很多坑官方并没有做出说明。
关于其他的匹配规则等,请移步这里查看更多。
PS:本文参考了柳志超的这篇文章

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值