一个意图是一个消息对象,你可以用它来请求从其他应用程序组件的操作。虽然意图促进在几个方面组件之间的通信中,有三个基本的用例:
要启动一个活动:
活动表示一个应用程序的单一屏幕。你可以通过传递一个Intent给startActivity开始活动的新实例()。的意图描述了启动活动并进行任何必要的数据。
如果你想从当它完成活动收到结果,调用startActivityForResult()。您的活动获得的结果在您的活动的的onActivityResult()回调一个单独的Intent对象。欲了解更多信息,请参见活动指南。
要启动服务:
服务是没有用户界面在后台执行操作的组件。您可以启动一个服务传递的意图,startService执行一次性操作(如下载文件),()。这样做的目的描述了启动该服务,并进行任何必要的数据。
如果该服务被设计在客户端 - 服务器接口,你可以通过一个意图bindService绑定到另一个组件的服务()。欲了解更多信息,请参阅服务指南。
为了提供广播:
广播是,任何应用程序可以接收消息。该系统提供了系统事件的各种节目,比如当系统启动或设备开始充电的。你可以通过传递一个Intent到sendBroadcast(),sendOrderedBroadcast()提供给其他应用程序广播,或sendStickyBroadcast()。
意图类型
有两种类型的意图的:
显式意图通过指定名称来启动(完全合格的类名)的组件。您通常会使用一个明确的意图在自己的应用程序来启动一个组成部分,因为你知道你想要启动的活动或服务的类名。例如,响应于用户动作开始一个新的活动或启动服务下载文件中的背景。
隐式意图不命名一个特定的组件,而是宣布执行一般的动作,这使得从其他应用程序的组件来处理它。例如,如果你想显示用户在地图上的位置,你可以用一个隐含的意图来请求另一个应用程序能够显示在地图上的指定位置。
当你创建一个明确的意图开始一项活动或服务时,系统立即开始在Intent对象中指定的应用程序组件。
图1.一个隐含的意图是如何通过系统交付给启动另一个活动说明:[1]活动A创建了一个动作描述一个Intent并把它传递给startActivity()。 [2] Android系统的搜索意图过滤器意图匹配所有的应用程序。当找到一个匹配,[3]系统通过调用其onCreate()方法,并传递给它的意图开始配对活动(活动B)。
当你创建一个隐含的意图,Android系统找到合适的组件通过意图的内容进行比较,以在设备上的其他应用程序的清单文件中声明的意图过滤器来启动。如果意图相匹配的意图过滤器,系统将启动该组件,并提供其意图对象。如果有多个意图过滤器是兼容的,系统会显示一个对话框,以便用户可以选择要使用的应用程序。
一个意图过滤器是在应用的清单文件,指定该组件希望收到意图的类型的表达式。例如,通过声明为活动的意图过滤器,你有可能使其他应用程序直接与某种意图开始您的活动。同样的,如果你不为活动声明任何的意图过滤器,那么就只能用明确意图开始。
注意:为了确保您的应用程序是安全的,启动服务时,一定要使用一个明确的意图,并没有为你的服务声明意图过滤器。使用一个隐含的意图是启动一个服务是一个安全隐患,因为你不能确定什么样的服务将向意图做出回应,并且用户无法看到哪些服务启动。采用Android 5.0(API级别21)开始,系统投如果你调用bindService()和一个隐含的意图异常。
建立一个Intent
一个Intent对象携带了Android系统用于确定要启动的组件(如确切的组件名称或应接收的意图组件类别),以及信息接收者组件,以便正确执行操作使用信息(如要采取的行动和数据要遵循)。
包含在意向书的主要信息如下:
组件名称
启动组件的名称。
这是可选的,但它的信息的关键部分,使得一个意图明确,这意味着意图应仅递送到由组件名称中定义的应用程序组件。没有一个组件名称,目的是隐式,系统决定哪个组件应接收基于其它意图信息的意图(如动作,数据和下面类别描述的)。所以,如果你需要在你的应用程序来启动某个特定组件,您应该指定组件名称。
注意:当启动一个服务,你应该总是指定组件名称。否则,你无法确定什么样的服务将向意图做出回应,并且用户无法看到哪些服务启动。
本意向书这个字段是一个组件名对象,您可以指定使用目标组件的完全限定类名,其中包括应用程序的包名。例如,com.example.ExampleActivity。您可以设置setComponent(),setClass(),setClassName(组件名称),或意图构造函数。
Action
指定通用操作的字符串来执行(如查看或选择)。
在广播意图的情况下,这是发生的,并且所报告的动作。操作在很大程度上决定了意图的其余部分所采用的结构,尤其中包含的内容数据,并附加功能。
您可以通过意图您的应用程序(或其他应用使用来调用你的应用程序组件)中指定使用自己的行为,但你通常应该使用Intent类或其他框架中的类定义的动作常量。下面是启动活动的一些常规操作:
ACTION_VIEW
当你有一些信息,一个活动可以显示给用户,如要查看的照片在画廊的应用程序,或查看在地图应用程序的地址使用这个动作与startActivity()的意图。
ACTION_SEND
也被称为“共享”的意图,你应该与startActivity()的意图,当你有一些数据,利用这一点,用户可以通过其他应用程序,共享,如电子邮件应用或社交共享应用程序。
参见定义通用的行为更多的常量Intent类参考。其他的动作在Android框架其他地方定义,比如在打开系统的设置应用特定画面的操作设置。
您可以指定使用的setAction意向()的动作或与意向构造。
如果您定义自己的操作,一定要包括你的应用程序的包名作为前缀。例如:
static final String ACTION_TIMETRAVEL = "com.example.action.TIMETRAVEL";
Data
引用的数据的URI(一个Uri对象)也可以作用于和/或MIME类型的数据。类型提供的数据通常由意图的动作决定的。例如,如果动作是ACTION_EDIT,数据应包含编辑文档的URI。
当创建一个意图,它指定数据的除了它的URI的类型(它的MIME类型)往往重要。例如,这能够大概显示图像的活动将不能够播放音频文件,即使该URI格式可能是相似的。因此指定MIME类型的数据有助于Android系统发现收到你的意图的最佳组件。然而,MIME类型,有时可以从推断的URI的,特别是当数据是一个内容:URI,表示该数据位于设备上,并通过一个ContentProvider的,这使得该数据的MIME类型的系统可见控制。
要设置只有数据的URI,调用使用setData()。要设置只MIME类型,调用的setType()。如果有必要,你可以用setDataAndType同时设置明确的()。
注意:如果你要同时设置URI和MIME类型,不要调用使用setData()和的setType(),因为它们都废了对方的价值。始终使用setDataAndType()同时设置URI和MIME类型。
Category
包含的那种分量应该处理这个意图附加信息串。任何数量的类别描述可以放置在一个意图,但大多数意图不要求一个类别。下面是一些常见的类别:
CATEGORY_BROWSABLE
目标活动允许自身通过web浏览器来显示由链路诸如图像或电子邮件消息中引用的数据来启动。
CATEGORY_LAUNCHER
该活动是一个任务的初始活性和在该系统的应用程序启动被列出。
见类别的完整列表Intent类的描述。
您可以指定addCategory类别()。
上述(组件名称,动作,数据,和类别)中列出这些性质表示意图的限定特征。通过阅读这些特性,Android系统能解决哪些应用组件它应该开始。
然而,意图可以携带不影响它是如何解析为应用程序组件的其他信息。一个意图还可以提供:
Extras
携带完成所请求的操作所需的附加信息键 - 值对。正如一些行动使用特定类型的数据的URI,一些动作也用特别的演员。
可以使用各种putExtra()方法添加额外的数据,每一个接受两个参数:键名和值。您还可以创建与所有额外的数据一个Bundle对象,然后用putExtras插入捆绑在Intent()。
例如,在创建意图时,与ACTION_SEND发送电子邮件,您可以指定与EXTRA_EMAIL键“到”收件人,并指定“主体”与EXTRA_SUBJECT键。
意图类指定许多EXTRA_ *常量标准化的数据类型。如果您需要声明自己的附加键(对于您的应用程序接收意图),一定要包括你的应用程序的包名作为前缀。例如:
static final String EXTRA_GIGAWATTS = "com.example.EXTRA_GIGAWATTS";
Flags
在Intent类中定义的标志为目的的元数据该功能。这些标志可指示Android系统如何启动一个活动(例如,它的任务活动应该属于)和它的发射后如何对待它(例如,它是否属于在最近的活动的列表)。
欲了解更多信息,请参见setFlags()方法。
例如明确意图
一个明确的意图是让你用来启动特定的应用程序组件,比如在你的应用程序特定的活动或服务之一。要创建一个明确的意图,在意向对象的所有其他意图属性定义的组件名称是可选的。
例如,如果你建你的应用程序服务,命名为下载服务,旨在从网络上下载一个文件,可以用下面的代码开始吧:
/
// 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);
这样做的目的(背景下,A类)构造函数提供应用程序上下文和组件的Class对象。因此,这种意图明确开始在应用程序的下载服务类。
有关构建和启动服务的详细信息,请参阅服务指南。
例如隐含意图
隐式意图指定可以调用该设备能够执行行动的任何应用程序的操作。使用一个隐含的意图时,你的应用程序无法执行的操作,但其他应用程序也许可以和你想的用户选择使用哪个应用是非常有用的。
例如,如果你有内容,您希望用户与其他人共享,创建具有ACTION_SEND行动意图,并添加指定内容共享临时演员。当你与意图调用startActivity(),用户可以选择通过共享的内容的应用程序。
注意:这是可能的,用户不会有处理您发送给startActivity()的隐含意图任何应用。如果发生这种情况,调用将失败,您的应用程序会崩溃。要验证活动将收到的意图,你的意图对象调用resolveActivity()。如果结果不为null,则至少有一个应用程序能够处理的意图和它的安全调用startActivity()。如果结果为空,你不应该使用的意图,可能的话,你应该禁用发出意图的功能。
// 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);
}
注意:在这种情况下,一个URI是不使用,但意图的数据类型声明来指定由额外携带的内容。
当startActivity()被调用时,系统会检查所有已安装的应用程序,以确定哪些可以处理这种意图(与ACTION_SEND采取行动的意图,并携带“text / plain的”数据)。如果只有一个应用程序可以处理它,该应用程序会立即打开,并给出意图。如果有多个活动接受的意图时,系统会显示一个对话框,以便用户可以选择要使用的应用程序..
图2.选择对话框。
强制应用程序选择器
当有多个应用程序,响应你的意图隐含的,用户可以选择哪些应用程序来使用,让该应用程序的操作的默认选择。为执行该用户可能希望使用相同的应用程序从现在起,一个动作时,这是很好的,例如打开一个网页时,如(用户往往更喜欢只是一个网络浏览器)。
但是,如果多个应用程序可以向意向作出回应,用户可能希望每次都使用不同的应用程序,你应该明确地显示一个选择对话框。在选择对话框要求用户选择哪些应用每次使用的操作(用户不能选择为操作的默认应用)。例如,当您的应用程序进行“共享”与ACTION_SEND动作,用户可能想利用这取决于他们目前的状况不同的应用分享,所以你应该始终使用选择对话框,如图2。
要显示选择器,创建一个使用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()方法的意图做出回应,并使用所提供的文本作为对话框的标题应用程序列表的对话框。
接收隐式意图
为了宣传其隐含的意图您的应用程序可以接收,在您的清单文件中的<意向filter>元素声明为每个应用程序组件的一个或多个意图过滤器。每一个意图过滤指定它接受基于意图的动作,数据和类别意图的类型。该系统将提供一个隐含的意图,你的应用程序组件只有意图可以通过你的意图过滤器之一。
注:明确意图一直传递到其目标,无论任何意图过滤组件声明。
一个应用程序组件应为每一个独特的工作可以做单独声明过滤器。例如,在一个图片库应用一个活动可能有两个过滤器:一个过滤器来查看图像,另一个过滤器来编辑图像。当活动启动时,它检查该意图,并决定基于意图的信息(诸如,显示在编辑器控制或不)如何表现。
每一个意图过滤器通过在应用程序的清单文件中的<意向filter>元素,嵌套在相应的应用程序组件(如<活动>元素)定义。在<意图过滤器>,您可以指定意图的方式,通过这三个要素中的一个或多个接受:
<action>
接受声明的意图行动,name属性。该值必须是一个行动的文本字符串值,而不是类常量。
<data>
声明数据的接受,使用该指定数据的URI(方案,主机,端口,路径等),MIME类型的各个方面的一个或多个属性的类型。
<category>
声明接受意向类别中的name属性。该值必须是一个行动的文本字符串值,而不是类常量。
注意:为了获得隐含的意图,你必须包括意图过滤器的CATEGORY_DEFAULT类别。方法startActivity()和startActivityForResult()把所有的意图,如果他们宣布CATEGORY_DEFAULT类别。如果没有这一类的意图过滤器声明,没有隐含意图将解析为您的活动。
例如,这里是与意图过滤器来接收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>
没关系创建一个过滤器,包括<行动>多个实例,<数据>或<category>中。如果你这样做,你只是需要确定该组件可以处理任何与这些过滤元件的所有组合。
当你要处理多个种类的意图,但只有在行动中,数据和类别类型的特定组合,那么你需要创建多个意图过滤器。
限制访问组件
使用意图过滤器是不是为了防止你开始组件的其他应用程序的安全方式。虽然意图过滤器来限制只有某些类型的隐含意图的响应一个组成部分,其他应用程序可以通过如果开发商决定了你的组件名称使用一个明确的意图可能会启动您的应用程序组件。如果是很重要的,只有你自己的应用程序能够启动您的组件之一,设置导出属性为“false”该组件。
隐式意图由意图比较每三要素的对一个过滤器进行测试。被传递到该组件,意图必须通过所有三个测试。如果失败,甚至其中的一个匹配,Android系统将无法实现意图的组件。但是,由于组件可以具有多个意图过滤器,即不通过的部件的过滤器之一的意图可能使其通过另一个过滤器。在低于约意图解决部分提供了有关该系统如何解决意图的更多信息。
注意:为避免无意中运行不同的应用程序的服务,始终使用明确意图开始自己的服务,并没有为您服务声明意图过滤器。
注意:对于所有的活动,您必须在清单文件中声明你的意图过滤器。然而,对于广播接收机滤波器可以动态地由调用registerReceiver注册()。然后,您可以取消注册unregisterReceiver接收器()。这样做使您的应用程序到你的应用程序正在运行,而只在指定的时间段监听特定广播。
例如过滤器
为了更好地理解一些意图过滤器的行为,看看从共享的社会应用程序的清单文件中的片断。
<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>
第一项活动,MainActivity,是应用程序的主入口点活动,当用户最初启动的启动器图标应用程序打开:
该ACTION_MAIN行动表明这是主要的入口点,并且不期待任何意图的数据。
该CATEGORY_LAUNCHER类别表示,本次活动的图标应放置在系统的应用启动。如果<活动>元素不指定与图标的图标,则系统使用从<application>元素的图标。
这两个必须一起才能配对的活动出现在应用程序启动器。
第二活动,ShareActivity,是为了便于共用的文本和媒体内容。虽然用户可以通过导航MainActivity它进入这个活动,他们也可以直接从其他应用程序,发出一个隐含的意图匹配两个意图过滤器中的一个输入ShareActivity。
注:MIME类型,应用/ vnd.google.panorama360 + JPG格式,是指定的全景照片,您可以使用谷歌API的全景处理特殊的数据类型。
使用意向之前
一个的PendingIntent对象围绕一个Intent对象的包装。一的PendingIntent的主要目的是将权限授予外国申请使用包含的意图,就好像它是从你的应用程序自身的进程中执行。
主要用例挂起的意图包括:
声明的意图,当用户执行与您的通知的动作(Android系统的NotificationManager执行意向)执行。
声明的意图,当用户执行与你的App小工具(在主页屏幕上的应用程序执行意向)的动作将被执行。
声明的意图在未来(Android系统的AlarmManager执行意向)在规定的时间执行。
因为每个意图对象被设计为通过特定类型的应用程序组件(无论是一个活动,服务,或一个BroadcastReceiver)的处理,所以也必须一的PendingIntent用相同的考虑创建。当使用挂起的意图,你的应用程序将不会执行与如startActivity()的调用的意图。当你通过调用相应的创建者方法创建的PendingIntent您必须声明,而不是预期的组件类型:
PendingIntent.getActivity()来启动一个活动的意图。
PendingIntent.getService()来启动服务的意图。
PendingIntent.getBroadcast()来启动一个广播接收器一个意图。
除非你的应用程序从其他应用程序接收未决的意图,上面的方法来创建的PendingIntent是你可能永远需要的唯一的PendingIntent方法。
每个方法对当前应用背景信息,要包指定如何意图应使用的意图,以及一个或多个标记(例如是否意图可以使用一次以上)。
关于使用未决意图详细信息设有用于每个各自的使用情况下,例如在声明和应用的窗口小部件的API导的文档。
分辨率意向
当系统收到一个隐含的意图开始活动,它将搜索通过比较意图基于以下三个方面的意图过滤器意图的最佳活动:
这样做的目的行动
这样做的目的数据(URI和数据类型)
这样做的目的类别
以下各节描述的意图是如何的意图过滤器是如何在一个应用程序的清单文件中声明的条款匹配到合适的组件(S)。
操作测试
要指定接受的意图行动,意图过滤器可以声明零个或更多的<action>元素。例如:
<intent-filter>
<action android:name="android.intent.action.EDIT" />
<action android:name="android.intent.action.VIEW" />
...
</intent-filter>
打通这个过滤器,在Intent指定的动作必须匹配过滤器中列出的操作之一。
如果过滤器没有列出任何动作,没有任何一个意图匹配,所以所有的意图失败的考验。但是,如果意图不指定一个动作,它将通过测试(只要该过滤器包含至少一个动作)。
分类测试
要指定接受意向类别,一个意图过滤器可以声明零个或更多的<category>元素。例如:
<intent-filter>
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
...
</intent-filter>
对于一个意图通过分类测试,在意图每个类别必须在过滤器的类别相匹配。相反的是没有必要的,意图过滤器可以宣告多个大类的意图指定和意图仍然会通过。因此,没有类别的意图应该总是通过这个测试,无论在过滤器中声明哪些类别。
注:Android的自动的CATEGORY_DEFAULT类适用于传递给startActivity()和startActivityForResult()所有隐含意图。所以如果你想你的活动接受隐含意图,它必须包括在它的意图过滤器“android.intent.category.DEFAULT”类别(如在以前<意图过滤器>的例子。
数据测试
要指定接受意图数据,一个意图过滤器可以声明零个或多个<数据>元素。例如:
<intent-filter>
<data android:mimeType="video/mpeg" android:scheme="http" ... />
<data android:mimeType="audio/mpeg" android:scheme="http" ... />
...
</intent-filter>
每个<data>元素可以指定一个URI结构和数据类型(MIME媒体类型)。有单独的属性 - 模式,主机,端口和路径 - 为URI的各个部分:
<scheme>://<host>:<port>/<path>
例如:
content://com.example.project:200/folder/subfolder/etc
在此URI,该方案的内容,主机是com.example.project,端口是200,和路径是文件夹/子/等。
每个属性是在<data>元素可选的,但也有线性的依赖关系:
如果没有指定一个方案,主机将被忽略。
如果没有指定主机,端口会被忽略。
如果未指定两个方案和主机,路径被忽略。
当在意图的URI被相比,在过滤器中的URI规范,它相比仅包括在过滤器URI的部分。例如:
如果过滤器仅指定一个方案,与该计划所有URI匹配滤波器。
如果过滤器指定了一个方案,一个权威,但没有路径,用同样的方案和权威的URI通过过滤器,不管他们的路径。
如果过滤器指定了一个方案,一个权威,和路径,只能用相同方案,授权和路径的URI通过过滤器。
注:路径规范可以包含通配符星号(*),以只需要路径名的一个部分匹配。
数据测试比较两者的URI和在意图在滤波器中指定的URI和MIME类型的MIME类型。的规则如下:
既不包含URI也不是MIME类型的意图传递仅当过滤器不指定任何的URI或MIME类型的测试。
包含URI的意图,但没有MIME类型(既不明确也不能推理从URI)通过测试仅当它的URI相匹配的滤波器的URI格式和过滤器同样未指定MIME类型。
包含MIME类型,但不是一个URI通过了测试仅在过滤器中列出了相同的MIME类型,不指定一个URI格式的意图。
同时包含URI和MIME类型(无论是明确的还是能推理从URI)意图通过测试的MIME类型部分仅当该类型的过滤器中列出的类型相匹配。它通过测试的URI的一部分或者如果它的URI的过滤器匹配的URI,或者如果它有一个内容:或file:URI和过滤器没有指定一个URI。换句话说,组件被假定为支持内容:和文件:数据如果滤波器仅列出一个MIME类型。
这最后一条规则,规则(四),反映了期望组件能够从文件或内容提供商获取本地数据。因此,他们的过滤器可以列出只是一个数据类型,并不需要明确地命名内容:和文件:方案。这是一个典型的案例。像下图的<data>元素,例如,告诉Android组件可以从内容提供商获取图像数据并显示它:
<intent-filter>
<data android:mimeType="image/*" />
...
</intent-filter>
由于大多数可用的数据是由内容提供者,过滤器,用于指定一个数据类型而不是一个URI也许是最常用的分配。
另一种常见的配置是一个方案和一个数据类型的过滤器。例如,<数据>像下面的元素告诉Android组件可以从网络检索视频数据以执行的操作:
<intent-filter>
<data android:scheme="http" android:type="video/*" />
...
</intent-filter>
意向匹配
意图是针对意图过滤器匹配,不仅发现一个目标组件激活,同时也发现一些关于设备上的组件集合。例如,家庭应用填充通过查找所有与指定ACTION_MAIN行动,并CATEGORY_LAUNCHER类别的意图过滤器活动的应用程序启动器。
应用程序可以以类似的方式使用意图匹配。该软件包管理系统有一套查询...()返回,可以接受特定意图的所有组件的方法,以及类似的一系列决心...()确定对意图做出反应的最佳组件的方法。例如,queryIntentActivities()返回一个可以执行作为参数传递的意图所有活动的列表,以及queryIntentServices()返回一个类似的服务列表。无论方法激活的组件;他们只是列出了可以响应的人。有一个类似的方法,queryBroadcastReceivers(),对于广播接收机。