赞
踩
Intent
是一个消息对象,你可以用来请求一个来自其他应用组件的操作。在几种方式中,Intent有利于组件之间的通信,有三个基本的用例:
一个Activity
代表了应用程序中的一个界面。通过传递一个Intent给startActivity(),你可以启动Activity的一个新的实例。这个Intent描述了Activity的启动,并携带任何必要的数据。
当Activity结束以后,如果你想从它那里获得一个结果,请调用startActivityForResult()。在你的Activity的 onActivityResult()
回调函数中,你的Activity接收的接过是作为独立的Intent对象的。欲了解更多信息,请参见Activities指南。
一个Service是在后台执行操作并且没有用户界面的组件。通过传递一个Intent给StartService();你可以启动一个服务去执行一个一次性的操作(例如下载的文件)。该这个Intent描述了Service的启动,并携带任何必要的数据。
如果Service被设计为具有客户端-服务器接口,那么通过传递一个Intent给bindService(),你可以从其他组件绑定到此Service上。欲了解更多信息,请参阅Service指南。
广播是任何应用程序都能够接收的消息。系统为系统事件发送各种广播,比如当系统启动或设备开始充电时,你可以通过传递一个Intent给 sendBroadcast()
,sendOrderedBroadcast()
, or sendStickyBroadcast()
来发送
一个广播给其它应用程序。
有两种类型的意图:
当您创建一个显示意图启动一个activity或者service时,系统会立即启动应用程序的组件,这个组件在Intent对象中被指定。
图1。系统如何传递一个显示意图来启动另一个activity:[1] Activity A 创建一个有动作的描述的Intent,并把它传递给startActivity()
。[2] Android系统搜索的所有应用程序Intent过滤器,与之相匹配。当找到相匹配的Intent,[3]系统启动配对的activity(activityB),通过调用此activity的onCreate()并把这个Intent传递给它。
当你创建一个隐式意图,通过比较设备上的其他应用声明在mainfest文件中的意图的意图过滤器的内容,Android系统找到匹配组件并启动。如果Intent匹配一个Intent过滤器,系统启动那个组件,并将这个Intent对象传递给它。如果有多个Intent过滤器是兼容的,系统会显示一个对话框,让用户可以选择要使用的应用程序。
一个Intent过滤器存在于应用程序的mainfest文件中用来指定该组件希望接收的Intent类型的表达式。例如,通过为一个activity声明Intent过滤器,你可以让其他应用程序直接用特定的Intent启动你的activity成为可能。同样的,如果你不为一个activity声明任何Intent过滤器,那么就只能用显示意图来启动它。
注意:为了确保您的应用程序是安全的,当你要启动一个Service并没有为你的Service声明一个Intent过滤器,你可以用显示意图来启动它。使用一个隐含的意图启动一个服务是一个安全隐患,因为你不能确定什么样的Service会响应你的Intent,用户无法看到哪些服务被启动了。从Android 5.0(API等级21)开始,如果你用一个隐式Intent来调用bindService(),系统会抛出异常。
一个Intent对象携带了Android系统决定启动那个组件的信息(如具体部件名称或接收的意图组件类别),以及为了让接收信息的组件更好的执行动作的信息(如将要采取的行动,和要用到的数据)。
Intent包含的主要信息如下:
这是可选的,但也是构建一个显示Intent的关键所在,这意味着Intent应仅传递给由组件名称定义的应用程序的组件。没有组件名称,Intent也是隐式是,系统根据其他信息决定那个组件将会接收到该Intent(如动作,数据和下面类别描述的类别)。所以,如果你需要在你的应用程序启动特定的组件,你应该指定组件名称。
注:当启动一个Service,你应该始终指定组件名称。否则,你无法确定什么样的Service将会响应你的Intent,并且用户不能看到哪个服务被启动。
在Intent是一个 ComponentName
(组件名称)对象方面,你可以指定目标组件的完整类名,其中包括应用程序的包名。例如, com.example.ExampleActivity
。您可以用setComponent()
,setClass()
,setClassName()设置的组件名称
,或使用Intent构造。
在广播意图的情况下,动作会发生并被广播。动作很大程度上决定了Intent其余部分的结构--尤其中包含的内容数据和附加功能。
你可以通过意图在你的应用程序(或使用其他应用程序来调用你的应用程序组件)内指定自己的动作,但你通常应该使用由Intent类定义的或者其他框架类定义动作常量。以下是开始活动的一些常规操作:
ACTION_VIEW
ACTION_SEND
更多定义常用actions的常量请参考Intent 类。其他actions定义在Android核心框架里,如在设置中为打开系统中的设置应用程序特定屏幕的action。
您可以用setAction()或者Intent的结构来为Intent指定action。
如果你定义自己的action,务必要包括你的应用程序的包名作为前缀。例如:
static final String ACTION_TIMETRAVEL = "com.example.action.TIMETRAVEL";
ACTION_EDIT
,数据应包含编辑文档的URI。
当创建一个Intent时,重要的是除了它的URI外还要指定数据的类型(它的MIME类型)。例如,一个activity是能够显示图像,多半不能够播放音频文件。因此指定数据的MIME类型有助于Android系统找到接收你的意图的最佳组件。然而,MIME类型,有时可以从URI中推断--特别是当数据是一个内容:
URI,表明该数据位于设备上,并通过ContentProvider控制
,这使得数据的MIME类型对于系统来说是可见的。
要设置唯一的URI数据,调用setData()
。要设置唯一的MIME类型,调用setType()
。如果有必要,你可以用setDataAndType()同时明确设置它们。
注意:如果你想同时设置URI和MIME类型, 不调用setData()
和 setType()
,因为它们互相抵消了彼此的作用。始终使用setDataAndType()
同时设置URI和MIME类型。
CATEGORY_BROWSABLE
CATEGORY_LAUNCHER
关于全部category请参阅Intent类。
你可以用addCategory()指定一个category。
上述列出的这些属性(组件名称,动作,数据和类别)表示了Intent的限定特征。通过阅读这些特性,Android系统能够解决应该启动哪些应用组件。
然而,意图可以携带那并不影响它是如何被解析给应用组件的其他信息。意图还可以提供:
可以使用各种putExtra()方法添加额外的数据,每种方法都接受两个参数:键名和值。您还可以创建一个拥有所有额外数据的Bundle对象,然后用putExtra()将Bundle对象插入到Intent中。
例如,当用ACTION_SEND创建一个Intent发送电子邮件时 ,你可以用 EXTRA_EMAIL
键指定“到”收件人,并用 EXTRA_SUBJECT
键指定“主题”。
Intent类指定le 不少EXTRA_ *
常数,用来标准化数据类型。如果你需要声明自己的附加 键(你的应用程序要接收的Intent),务必要包含你的应用程序的包名作为前缀。例如:
static final String EXTRA_GIGAWATTS = "com.example.EXTRA_GIGAWATTS";
欲了解更多信息,请参见setFlags()
方法。
一个显示Intent是用来启动特定的应用程序组件,如你的应用程序特定的activity或服务之一。要创建一个显示意图,就要为Intent对象定义组件名称--所有其他Intent属性都是可选的。
例如,如果你在你的应用程序中构建了一个service,名叫DownloadService
,目的是从网上下载文件,你可以用下面的代码来启动它:
//执行的一个活动,所以'这个'是 Context(上下文)
//fileUrl是一个URL字符串,如"http://www.example.com/image.png"
Intent downloadIntent = new Intent ( this , DownloadService . class );
downloadIntent . setData ( Uri . parse
( fileUrl ));
startService ( downloadIntent );
构造函数需求应用程序Intent(Context, Class
和组件class对象。因此,这个Intent再应用程序中显示的启动了DownloadService类。Contex
有关构建和启动服务的详细信息,请参阅 Services 指南。
一个隐式意图指定可以调用设备上能够执行操作的任何应用程序的操作。当你的应用程序无法执行action,而其他应用可以并且你希望用户能选择使用哪个应用时,使用隐式意图是非常有用的。
例如,如果你希望用户与其他人共享你的内容,那么创建一个Intent,使Intent有ACTION_SEND动作,并添加指定共享内容的附件数据。当你用此Intent调用 startActivity()时
,用户可以选择用来分享内容的应用程序。
注意:用户没有任何 能处理你发送给startActivity()的隐式意图的应用程序是可能的
。如果出现这种情况,则调用将失败,你的应用程序会崩溃。要验证activity将收到的Intent,用你的Intent对象调用resolveActivity()
。如果结果不为null,则至少有一个应用程序能够处理这个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);
}
注意:在这种情况下,URI没有使用,但Intent的数据类型被声明,用以指定由额外附件的内容。
当startActivity()
被调用时,系统会检查所有已安装的应用程序,以确定哪些可以处理这种Intent(Intent有ACTION_SEND
行动,并携带“text / plain”数据)。如果只有一个应用程序可以处理它,该应用程序将立即启动,并被给予这个Intent。如果有多个activity接受这个Intent,系统会显示一个对话框,让用户可以选择要使用的应用程序...
图2。一个选择器对话框。
当有一个以上的应用程序,响应你的隐式意图时,用户可以选择要使用的应用程序,并且使该应用程序成为默认选择。执行用户可能从今以后要一直使用相同的应用程序的action,是很好的,比如打开一个网页的时候(用户常常喜欢只是一个网络浏览器)。
但是,如果多个应用程序可以响应此Intent,用户可能希望每次都使用不同的应用程序,那么你应该显示一个选择对话框。在选择对话框要求用户每次都去选择要使用的应用程序(用户不能为这个action选择默认的应用程序)。例如,当你的应用程序用ACTION_SEND action
进行“分享”,为了分享用户可能要使用不同的应用程序,这依赖于他们目前的状况,所以你应该始终使用选择对话框,如图2。
要显示选择器,创建一个Intent,使用createChooser()
,并把它传递给startActivity()
。例如:
Intent sendIntent = new Intent(Intent.ACTION_SEND);
...
// Always use string resources for UI text.
// This says something like "Share this photo with"
String title = getResources().getString(R.string.chooser_title);
// Create intent to show the chooser dialog
Intent chooser = Intent.createChooser(sendIntent, title);
// Verify the original intent will resolve to at least one activity
if (sendIntent.resolveActivity(getPackageManager()) != null) {
startActivity(chooser);
}
通过createChooser()
方法来显示一个有应用程序列表的对话框,并使用所提供的文本作为对话框标题。
为了标榜你的应用程序可以接收隐式意图,应该声明一个或多个Intent过滤器为每个应用程序组件,这些组件在你的mainfest文件中有 <intent-filter>元素
。每个Intent过滤器指定Intent本身能接受的Intent类型,这些Intent的类型基于Intent的action,data和category。系统将一个隐式意图传递给你的应用程序组件,如果此Intent能匹配你的Intent 过滤器中的任何一个。
注:一个显示意图总是被传递给它的目标,不用考虑任何组件的Intent过滤器的声明。
一个应用程序组件应该为自己能做的每一个独特的工作单独声明过滤器。例如,相册应用程序的一个activity可以有两个过滤器:一个过滤器为了查看图像,而另一个过滤器用来编辑图像。当activity启动时,它检查该Intent,并决定如何根据Intent所述的信息来表现(例如,显示编辑控件与否)。
每一个Intent过滤器是通过应用程序mainfest清单文件中的一个<intent-filter>
元素来定义的,嵌套在相应的应用程序组件(如
<activity>
元素)。里面的<
,你可以指定意图的类型,用来接受使用这个三个元素中的一种或者多种。intent-filter>
<action>
name
属性中,声明已接受的Intent action。该值必须是一个action的文本字符串值,而不是类常量。
<data>
scheme
,
host
,
port
,
path
等)和MIME类型。
<category>
name
属性中,
声明已接受的Intent Category。该值必须是一个
action
的文本字符串值,而不是类常量。
注:为了接收隐式Intent,你 必须在Intent过滤器中包括 CATEGORY_DEFAULT
的Category。方法 startActivity()
和 startActivityForResult()
把所有的Intent都当作它们已声明了CATEGORY_DEFAULT
类别。如果你在你的Intent过滤器中不声明此类别,将没有隐式Intent解析你的activity。
例如,这里有一个activity的声明,其中有一个Intent过滤器接收 ACTION_SEND
意图,当数据类型为文本时:
<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>
创建一个filter包含多于一个的<action>, <data>, 或 <category>的实例是可以的。如果你这么做,你只需要简单地让某些组件可以处理任意组合的这些filter元素
当你想要去处理多种类型的intent的时候,但是仅有action、data和category类型的指定组合,你需要创建多个intent filter。
一个隐式意图通过比较intent的三个元素来进行filter的针对性测试。为了被发送给应用程序组件,intent必须通过全部的三个测试。如果他们中的任何一个匹配失败,Android系统不会发送这个intent到应用程序组件。但是,因为一个组件可能有多个intent filter,一个intent不能通过组件的一个filter,但是可能通过另一个filter。有关系统如何解析Intent的更多信息,将在下面有关部分提供 Intent Resolution。
警告:为了避免在不经意间运行不同的应用程序的 Service,应该总是使用一个明确的意图启动自己的服务并且不给您的服务定义Intent filter。
使用Intent filter不是一个让其他的应用启动你的组件的安全的方法。通过Intent filter限制一个组件响应只有某些类型的隐式Intent,其他的应用可能能通过一个显式Intent启动你的应用程序组件,如果开发者知道你的组件名称的话。如果仅有你自己的应用程序启动你的应用程序组件之一是重要的,给该组件设置exported属性值为"false"。
为了更好地理解一些Intent过滤器的行为,看看从一种社会共享应用程序的清单文件的片断。
<activity android:name="MainActivity">
<!-- This activity is the main entry, should appear in app launcher -->
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="ShareActivity">
<!-- This activity handles "SEND" actions with text data -->
<intent-filter>
<action android:name="android.intent.action.SEND"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="text/plain"/>
</intent-filter>
<!-- This activity also handles "SEND" and "SEND_MULTIPLE" with media data -->
<intent-filter>
<action android:name="android.intent.action.SEND"/>
<action android:name="android.intent.action.SEND_MULTIPLE"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="application/vnd.google.panorama360+jpg"/>
<data android:mimeType="image/*"/>
<data android:mimeType="video/*"/>
</intent-filter>
</activity>
第一个activity,MainActivity
,是应用程序的主入口点,当用户通过桌面上的应用程序的图标初始化启动应用程序时,这个activity会显示出来。
ACTION_MAIN action
表明这是主要的入口点,并且不期望任何Intent数据。CATEGORY_LAUNCHER category表明
这个Activity的图标将要显示在系统的Launcher应用上。如果 <activity>元素没有通过icon指定一个图标,那么系统将使用<application>元素的icon图标。这两个必须配对在一起,以便Activity显示在应用程序的启动器(Launcher)上。
第二个activity,ShareActivity
,是为了便于分享文本和媒体内容。虽然用户可能会从MainActivity导航到这个Activity,它们也可以直接从其他应用程序通过发出匹配这两个intent filter中的一个的隐式Intent来进入ShareActivity。
注: MIME类型,application/vnd.google.panorama360+jpg
,是指全景照片的数据类型,你能够通过Google panorama APIS来处理这种特殊的格式。
一个PendingIntent
对象是是Intent
对象的一个包装器。PendingIntent的一个最主要的目是将权限授予给一个外部应用程序去使用已包含的Intent
,就像是它从你的应用程序本身的进程中执行。
NotificationManager
执行这个Intent)。
AlarmManager
执行这个Intent)。因为每一个Intent对象被设计用于操作指定类型的应用程序组件(Activity,Service或者BroadcastReceiver),因此PendingIntent也必须基于相同的考虑被创建。当使用pending Intent 的时候,你的应用不能通过 startActivity()调用执行Intent。当你通过相应的构造方法创建PendingIntent的时候,您必须声明预期的组件类型:
PendingIntent.getActivity()
启动一个Activity的Intent
。PendingIntent.getService()
启动一个Service的Intent
。PendingIntent.getBroadcast()
启动一个BroadcastReceiver的Intent
。 除非你的应用程序是接收其他应用程序的pending intent,上面的这些创建 PendingIntent
的方法可能是你需要的创建 PendingIntent
的唯一的方法。
每个方法都需要当前的应用程序 Context
(上下文)、你想要包装的Intent
,以及指定一或多个Intent如何使用的Flag(如意图是否可以使用一次以上)。
有关使用待定意图的更多信息,在每个相应用例中将提供,比如:在 Notifications 和App Widgets API 官方指南中。
当系统收到一个隐式Intent启动一个activity时,它会基于以下的三个层面比较Intent的Intent filter来搜索最佳的Activity 的Intent:
以下各节描述的是:一个Intent是如何跟适当的组件相匹配的,就Intent filter是怎样被声明在应用程序的mainfest清单文件中而言。
要指定已接受的Intent的action,Intent filter可以声明0个或者更多的<action>
元素。例如:
<intent-filter>
<action android:name = "android.intent.action.EDIT" />
<action android:name = "android.intent.action.VIEW" />
...
</intent-filter>
要通过这个过滤器,在 Intent
中被指定的action必须与fitler中列出的action中的一个匹配。
要指定已接受Intent 的category,一个Intent过滤器可以声明零个或多个 <category>
元素。例如:
<intent-filter>
<category android:name = "android.intent.category.DEFAULT" />
<category android:name = "android.intent.category.BROWSABLE" />
...
</intent-filter>
对于一个Intent要通过category测试,每一个Intent中的category必须匹配过滤器中的一个category。相反是没有必要的—— intent filter 可能定义比指定的Intent 更多的category,并且这个Intentt能够通过测试。因此,一个没有category的Intent总是能够通过这个测试,无论在Manifest的filter中定了什么样的category。
注: Android会自动提供CATEGORY_DEFAULT category
给所有被传递给startActivity()
和startActivityForResult()的
隐含意图。所以,如果你想你的activity接收隐式Intent,它必须在其意图过滤器中包含一个category :“android.intent.category.DEFAULT”。
(如之前的<intent-filter>
的例子。)
要指定已接受Intent数据,ntent filter可以声明0个或者更多的
元素。例如:<data>
<intent-filter>
<data android:mimeType = "video/mpeg" android:scheme = "http" ... />
<data android:mimeType = "audio/mpeg" android:scheme = "http" ... />
...
</intent-filter>
每个
元素可指定一个URI结构和数据类型(MIME媒体类型)。有单独的属性-<data>
scheme
, host
, port
, 和 path
-URI的各个部分:
<scheme>://<host>:<port>/<path>
例如:
content://com.example.project:200/folder/subfolder/etc
在这个URI中,scheme 是content,主机(host)是com.example.project,端口(port)是200,和路径(path)是folder/subfolder/
等。
这些属性中的每一个在<data>元素中
都是可选的,但也有线性的依赖关系:
当一个Intent中的URI和在filter中指定的URI比较的时候,它只比较包含在这个filter中的URI的一部分。比如:
注:一个path的指定能够包含一个通配字符型号(*)来要求仅匹配path的名称部分。
Data测试通过对比Intent中的URI以及MIMI类型和filter中指定的URI和MIMI类型。它们的规则如下:
这是最后的规则,规则反应组件能够从一个文件或者content Provider中得到本地数据的期望。因此,它们的filter能够列出仅有一个数据类型而且不需要显示命名的content: 和file: 的schema。这是一个典型的案例。一个<data>元素像下面这样,比如,告诉Android这个组件能够从content provider得到图片数据并显示它:
<intent-filter>
<data android:mimeType="image/*" />
...
</intent-filter>
因为大部分可用的数据通过content provider、filter指定数据类型,并不需要一个URI可能是常见的。
另一种常见的配置是filter的schema和数据类型.比如说,一个像下面这样的<data>元素告诉Android这个组件能够执行从网络上得到video数据的操作。
<intent-filter>
<data android:scheme="http" android:type="video/*" />
...
</intent-filter>
Intent匹配Intent filter不仅能发现一个可被激活的目标组件,也有可能发现多个这个设备上的组件。例如,Home 应用能够找到所有指定 ACTION_MAIN
action和CATEGORY_LAUNCHER
category的intent filter相匹配的Activity,并放置于Launcher中。
你的应用程序能够使用类似的Intent匹配。 PackageManager
有一系列的query...() 方法来返回所有的能够接收这个特殊的Intent的组件,还有类似的一系列的resolve...() 方法确定能够响应这个Intent的最佳的组件。例如,queryIntentActivities()返回一个能够执行一个作为参数的Intent的Activity列表。queryIntentServices()
返回相似的Service列表。它们都不能激活组件;它们仅仅列出那些可以响应的组件。有一个类似的方法, queryBroadcastReceivers()
,用于broadcast receiver。
原文:http://developer.android.com/guide/components/intents-filters.html
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。