首页 > 技术文章 > Android四大组件之Intent

Spground 2015-06-26 17:16 原文


Android四大组件之Intent( Intent & Intent Filter)

1.概述

 

一个Intent是一个消息对象,你可以使用它来获得另一个app组件的操作。尽管有很多种方式来使用intent来进行组件之间的通信,但是主要是有三种基本的使用情景:

.开始一个Activity
 使用startActivity(),或者startActivityForResult();这时候Intent描述了要激活的是哪一个Activity以及携带一些其他的必要的信息
.开始一个Service
使用startService()开启一个Service,当然你也可以将你的Service设计成为C/S结构的,即使用bindService()方法将你的Service绑定到其他组件上面

.分发一个广播

广播是一个所有app都能够收到的消息,Android为了不同的系统事件分发不同的广播。你可以使用Intent来作为sendBroadcast(),sendOrderedBroadcast(), 或者 sendStickyBroadcast()来分发一个广播。

2.Intent的类型

 

有两种Intent
.显式Ittent:用完整的包名类名来开始一个指定的组件,典型的使用场景就是你使用一个显示的Intent来激活你自己app上面的一个组件。
.隐士Intent:不给出要激活的组件的名字,代替的是声明将要期望执行的操作。例如:当你想要在map上显示一个地理位置的时候,你可以使用一个隐士的Intent来请求那些具有显示地理位置功能的地图app或者其他app来处理你的请求。

说明:
当你创建一个显示的Intent来启动你的组件的时候,系统立刻就激活这个组件。而当你使用隐士的Intent的时候,系统将要去寻找合适的组件,通过比对在manifest文件中声明的intent-filter。如果你创建的intent匹配一个声明的intent-filter,系统将激活这个组件,并且将你的intent传递给它,如果同时有多个intent-filter匹配你的intent,那么系统将要显示一个对话框叫用户选择一个app来使用。

一个intent-filter是一个manifest文件中的表达式,这个表达式指定了这个组件可以处理或者愿意接受的intent的类型。例如:通过声明为一个activity一个intent-filter,其他app直接调用你的app的activity是可能的。如果你在activity中不声明任何的intent-filter,那么这个activity仅仅能够被一个显示的intent所激活启动。

下图是一个示意图说明隐士intent如何工作的:

 

注意:为了确保你的app是安全的,一直要记住使用显示的intent来开启一个服务,不要为了你的Service声明一个intent-filter。使用一个隐士的intent开启一个Service会带啦风险的,因为你不能确定是哪一种Service将要响应你的intent,同时用户不能看见是哪一个Serivice开启了。在Android5.0以后,如果传递一个隐士intent给一个bindService(),系统将抛出异常。

3.Intent的内容

 

intent里面主要的信息是如下:
.组件名字(Component Name)
这个是可选的,但是你要是用显示的intent的话,你就必须在你的intent包含这个信息。如果没有这个信息,那么意味着你是在使用一个隐式的的Intent来开启一个组件,系统决定哪一个组件收到这个intent。
.操作(Action):
一个字符串描述将要执行的操作
intent中的action很大部分上决定了intent其他部分的组成,例如intent的data,extras等等。
你可以指定自己的action在你的app中,但是你应该更常用的是Intent类里面自定义的常量。
例如:
ACTION_VIEW

ACTION_SEND等等
.数据(Data)
包含了intent里面制定的URI以及MIME 类型
.策略(Category)
一个字符串描述了能够处理这种intent的组件的额外的信息。
下面是一些常见的策略:
CATEGORY_BROWSABLE
被intent启动的目标组件
允许自己被一个浏览器来启动并显示一个链接指向的数据。
CATEGORY_LAUNCHER
运用这个策略的activity是一个初始化的activity,并被列在系统程序的启动栏中。
.额外的信息(Extras)
一些携带者额外的信息的键值对,可以通过putExtral()方法或者创建一个Bundle对象来填入你的Extral的所有的键值对,然后将Bundle对象作为参数传递给putExtrals();
.标签(Flags)
标签的功能就是作为一个Intent的元数据而存在。标签告诉系统怎么样去加载一个activity(例如,这个activity隶属于哪一个任务),当他被启动后如何去对待它,(例如它是否属于最近活动列表中)

4.显示、隐式Intent的例子

 

.对于显示Intent的例子此处省略。
.此处说明一下隐式Intent需要注意的地方:
由于你在Intent里面给出的action,系统并没有找到合适的组件来处理它,那么你的程序将会崩溃。因此在你的使用隐式Intent开始一个Activity的时候,记住使用resolveActivity()来测试你的Intent是否有合适的activity来处理它,如果这个方法的返回值是一个非空的值,那么说明有合适的ativity来处理你的intent,否则说明没有合适的activity来处理这个intent,那么你就不要调用startActivity()了。

下面是一个隐式Intent的简单的例子:
// Create the text message with a string
Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, textMessage);
sendIntent.setType(HTTP.PLAIN_TEXT_TYPE); // "text/plain" MIME type
// Verify that the intent will resolve to an activity
if (sendIntent.resolveActivity(getPackageManager()) != null) {    
startActivity(sendIntent);
}


5.Intent-Filter的定义

 

每一个被定义的intent-filter都可能包含下列三种元素中的一个或多个
<action>
声明接受的intent的操作,在name属性中声明,这个值是一个字符串。
<data>
声明被接受的数据类型,使用一个或多个属性来声明数据的URI和MIME类型

<category>

声明可以接受的intent的策略

注意:为了收到隐式的Intent,你必须包含CATEGORY_DEFAULT策略在你intent-filter,当你使用startActivity()和startActivityForResult()将所有的intent看作他们已经声明了CATEGORY_DEFAULT。如果你在你的intent-filter里面没有声明这个CATEGORY_DEFAULT策略,那么你的activity将不会解析任何intent
下面是一个简单的可以处理ACTION_SEND intent的intent-filter
<activity android:name="ShareActivity">    
<intent-filter>        
<action android:name="android.intent.action.SEND"/>        
<category android:name="android.intent.category.DEFAULT"/>        
<data android:mimeType="text/plain"/>    
</intent-filter></activity>




 

推荐阅读