Intent 和 Intentfilter

来自:https://developer.android.com/guide/components/intents-filters.html

Intent是一个消息传递对象,您可以使用它从其他应用组件请求操作。尽管
Intent 可以通过多种方式促进组件之间的通信,但其基本用例主要包括以下三个:

  • 启动 Activity

    Activity表示应用中的一个屏幕。通过将Intent传递给startActivity(),您可以启动新的Activity实例。Intent描述了要启动的Activity,并携带了任何必要的数据。

    如果您希望在 Activity 完成后收到结果,请调用startActivityForResult()。在
    Activity的onActivityResult()回调中,您的
    Activity 将结果作为单独的Intent对象接收。如需了解详细信息,请参阅Activity指南。

  • 启动服务

    Service是一个不使用用户界面而在后台执行操作的组件。通过将Intent传递给startService(),您可以启动服务执行一次性操作(例如,下载文件)。Intent描述了要启动的服务,并携带了任何必要的数据。

    如果服务旨在使用客户端-服务器接口,则通过将Intent传递给bindService(),您可以从其他组件绑定到此服务。如需了解详细信息,请参阅服务南。

  • 传递广播

    广播是任何应用均可接收的消息。系统将针对系统事件(例如:系统启动或设备开始充电时)传递各种广播。通过将Intent传递给sendBroadcast()sendOrderedBroadcast()sendStickyBroadcast(),您可以将广播传递给其他应用。

Intent 类型

Intent 分为两种类型:

  • 显式Intent:按名称(完全限定类名)指定要启动的组件。通常,您会在自己的应用中使用显式Intent来启动组件,这是因为您知道要启动的 Activity 或服务的类名。例如,启动新Activity以响应用户操作,或者启动服务以在后台下载文件。
  • 隐式Intent:不会指定特定的组件,而是声明要执行的常规操作,从而允许其他应用中的组件来处理它。例如,如需在地图上向用户显示位置,则可以使用隐式 Intent,请求另一具有此功能的应用在地图上显示指定的位置。

创建显式 Intent 启动 Activity 或服务时,系统将立即启动Intent对象中指定的应用组件。

图 1. 隐式 Intent 如何通过系统传递以启动其他 Activity 的图解:[1] Activity A 创建包含操作描述的 Intent,并将其传递给 startActivity()[2] Android
系统搜索所有应用中与 Intent 匹配的 Intent 过滤器。找到匹配项之后,[3] 该系统通过调用匹配 Activity(Activity B)的 onCreate() 方法并将其传递给Intent,以此启动匹配
Activity。

创建隐式 Intent 时,Android 系统通过将Intent的内容与在设备上其他应用的清单文件中声明的Intent过滤器进行比较,从而找到要启动的相应组件。Intent如果
Intent 与 Intent 过滤器匹配,则系统将启动该组件,并将其传递给对象。如果多个 Intent 过滤器兼容,则系统会显示一个对话框,支持用户选取要使用的应用。

Intent 过滤器是应用清单文件中的一个表达式,它指定该组件要接收的 Intent 类型。例如,通过为 Activity 声明 Intent 过滤器,您可以使其他应用能够直接使用某一特定类型的 Intent 启动 Activity。同样,如果您没有为 Activity 声明任何 Intent 过滤器,则 Activity 只能通过显式 Intent 启动。

警告:为了确保应用的安全性,启动Service时,请始终使用显式
Intent,且不要为服务声明 Intent 过滤器。使用隐式 Intent 启动服务存在安全隐患,因为您无法确定哪些服务将响应Intent,且用户无法看到哪些服务已启动。从Android 5.0(API 级别 21)开始,如果使用隐式Intent调用bindService(),系统会抛出异常。

构建Intent

Intent对象携带了Android系统用来确定要启动哪个组件的信息(例如,准确的组件名称或应当接收该 Intent 的组件类别),以及收件人组件为了正确执行操作而使用的信息(例如,要采取的操作以及要处理的数据)。

Intent中包含的主要信息如下:

组件名称
要启动的组件名称。

这是可选项,但也是构建显式Intent 的一项重要信息,这意味着 Intent 应当仅传递给由组件名称定义的应用组件。如果没有组件名称,则 Intent 是隐式的,且系统将根据其他Intent信息(例如,以下所述的操作、数据和类别)决定哪个组件应当接收Intent。因此,如需在应用中启动特定的组件,则应指定该组件的名称。

注意:启动Service时,您应始终指定组件名称。否则,您无法确定哪项服务会响应Intent,且用户无法看到哪项服务已启动。

Intent的这一字段是ComponentName对象,您可以使用目标组件的完全限定类名指定此对象,其中包括应用的软件包名称。例如,com.example.ExampleActivity。您可以使用setComponent()setClass()setClassName()Intent构造函数设置组件名称。

操作

指定要执行的通用操作(例如,“查看”或“选取”)的字符串。

对于广播 Intent,这是指已发生且正在报告的操作。操作在很大程度上决定了其余 Intent 的构成,特别是数据和extra中包含的内容。

您可以指定自己的操作,供Intent在您的应用内使用(或者供其他应用在您的应用中调用组件)。但是,您通常应该使用由Intent类或其他框架类定义的操作常量。以下是一些用于启动
Activity 的常见操作:

ACTION_VIEW
如果您拥有一些某项 Activity 可向用户显示的信息(例如,要使用图库应用查看的照片;或者要使用地图应用查找的地址),请使用 Intent 将此操作与startActivity()结合使用。
ACTION_SEND
这也称为“共享”Intent。如果您拥有一些用户可通过其他应用(例如,电子邮件应用或社交共享应用)共享的数据,则应使用 Intent 中将此操作与startActivity()结合使用。

有关更多定义通用操作的常量,请参阅Intent类引用。
其他操作在Android框架中的其他位置定义。例如,对于在系统的设置应用中打开特定屏幕的操作,将在Settings中定义。

您可以使用setAction()Intent构造函数为Intent指定操作。

如果定义自己的操作,请确保将应用的软件包名称作为前缀。 例如:

static final String ACTION_TIMETRAVEL = "com.example.action.TIMETRAVEL";
数据
引用待操作数据和/或该数据MIME类型的URI(Uri对象)。提供的数据类型通常由Intent的操作决定。例如,如果操作是ACTION_EDIT,则数据应包含待编辑文档的URI。

创建 Intent 时,除了指定URI 以外,指定数据类型(其 MIME 类型)往往也很重要。例如,能够显示图像的Activity可能无法播放音频文件,即便 URI 格式十分类似时也是如此。因此,指定数据的 MIME 类型有助于 Android 系统找到接收 Intent 的最佳组件。但有时,MIME 类型可以从URI 中推断得出,特别当数据是content:URI 时尤其如此。这表明数据位于设备中,且由ContentProvider控制,这使得数据
MIME 类型对系统可见。

要仅设置数据 URI,请调用setData()。要仅设置
MIME 类型,请调用setType()。如有必要,您可以使用setDataAndType() 同时显式设置二者。

警告:若要同时设置 URI 和 MIME 类型,请勿调用setData()setType(),因为它们会互相抵消彼此的值。请始终使用setDataAndType()同时设置
URI 和 MIME 类型。

类别
一个包含应处理 Intent 组件类型的附加信息的字符串。您可以将任意数量的类别描述放入一个Intent中,但大多数Intent均不需要类别。以下是一些常见类别:

CATEGORY_BROWSABLE
目标 Activity 允许本身通过 Web 浏览器启动,以显示链接引用的数据,如图像或电子邮件。
CATEGORY_LAUNCHER
该 Activity 是任务的初始 Activity,在系统的应用启动器中列出。

有关类别的完整列表,请参阅 Intent 类描述。

您可以使用addCategory()指定类别。

以上列出的这些属性(组件名称、操作、数据和类别)表示 Intent 的既定特征。通过读取这些属性,Android 系统能够解析应当启动哪个应用组件。

但是,Intent 也有可能会一些携带不影响其如何解析为应用组件的信息。Intent 还可以提供:

Extra
携带完成请求操作所需的附加信息的键值对。正如某些操作使用特定类型的数据 URI 一样,有些操作也使用特定的附加数据。

您可以使用各种putExtra()方法添加附加数据,每种方法均接受两个参数:键名和值。您还可以创建一个包含所有附加数据的Bundle对象,然后使用putExtras()Bundle插入Intent中。

例如,使用ACTION_SEND创建用于发送电子邮件的
Intent 时,可以使用EXTRA_EMAIL键指定“目标”收件人,并使用EXTRA_SUBJECT键指定“主题”。

Intent类将为标准化的数据类型指定多个 EXTRA_* 常量。如需声明自己的附加数据
键(对于应用接收的 Intent ),请确保将应用的软件包名称作为前缀。例如:

static final String EXTRA_GIGAWATTS = "com.example.EXTRA_GIGAWATTS";
标志
Intent类中定义的、充当Intent元数据的标志。标志可以指
Android系统如何启动Activity(例如,Activity应属于哪个任务),以及启动之后如何处理(例如,它是否属于最近的Activity列表)。

如需了解详细信息,请参阅setFlags()方法。

显式Intent示例

显式Intent是指用于启动某个特定应用组件(例如,应用中的某个特定 Activity 或服务)的 Intent。要创建显式 Intent,请为Intent对象定义组件名称。Intent
的所有其他属性均为可选属性。

例如,如果在应用中构建了一个名为DownloadService、旨在从 Web 中下载文件的服务,则可使用以下代码启动该服务:

// 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(Context, Class)构造函数分别为应用和组件提供ContextClass对象。因此,此Intent将显式启动该应用中的DownloadService类。

如需了解有关构建和启动服务的详细信息,请参阅服务指南。

隐式Intent示例

隐式Intent指定能够在可以执行相应操作的设备上调用任何应用的操作。如果您的应用无法执行该操作而其他应用可以,且您希望用户选取要使用的应用,则使用隐式Intent非常有用。

例如,如果您希望用户与他人共享您的内容,请使用ACTION_SEND操作创建 Intent,并添加指定共享内容的Extra。使用该Intent
调用startActivity()时,用户可以选取共享内容所使用的应用。

警告:用户可能没有任何应用处理您发送到startActivity()的隐式
Intent。如果出现这种情况,则调用将会失败,且应用会崩溃。要验证 Activity是否会接收 Intent,请对Intent对象调用resolveActivity()。如果结果为非空,则至少有一个应用能够处理该
Intent,且可以安全调用startActivity()。如果结果为空,则不应使用该Intent。如有可能,您应禁用发出该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("text/plain");

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

注意:在这种情况下,系统并没有使用 URI,但已声明Intent的数据类型,用于指定Extra携带的内容。

调用startActivity()时,系统将检查已安装的所有应用,确定哪些应用能够处理这种
Intent(即:含ACTION_SEND操作并携带“文本/纯”数据的 Intent )。如果只有一个应用能够处理,则该应用将立即打开并提供给
Intent。如果多个 Activity 接受 Intent,则系统将显示一个对话框,使用户能够选取要使用的应用。

强制使用应用选择器

如果有多个应用响应隐式Intent,则用户可以选择要使用的应用,并将其设置为该操作的默认选项。如果用户可能希望今后一直使用相同的应用执行某项操作(例如,打开网页时,用户往往倾向于仅使用一种 Web 浏览器),则这一点十分有用。

但是,如果多个应用可以响应Intent,且用户可能希望每次使用不同的应用,则应采用显式方式显示选择器对话框。选择器对话框要求用户选择每次操作要使用的应用(用户无法为该操作选择默认应用)。 例如,当应用使用ACTION_SEND操作执行“共享”时,用户根据目前的状况可能需要使用另一不同的应用,因此应当始终使用选择器对话框,如图
2 中所示。

图 2. 选择器对话框。

要显示选择器,请使用createChooser()创建Intent,并将其传递给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的应用列表,并使用提供的文本作为对话框标题。

接收隐式 Intent



要公布应用可以接收哪些隐式 Intent,请在清单文件中使用 <intent-filter>; 元素为每个应用组件声明一个或多个Intent
过滤器。每个 Intent 过滤器均根据 Intent 的操作、数据和类别指定自身接受的 Intent 类型。仅当隐式 Intent 可以通过 Intent 过滤器之一传递时,系统才会将该 Intent 传递给应用组件。

注意:显式 Intent始终会传递给其目标,无论组件声明的 Intent 过滤器如何均是如此。

应用组件应当为自身可执行的每个独特作业声明单独的过滤器。例如,图像库应用中的一个 Activity 可能会有两个过滤器,分别用于查看图像和编辑图像。 当 Activity 启动时,它将检查Intent并根据Intent中的信息决定具体的行为(例如,是否显示编辑器控件)。

每个 Intent 过滤器均由应用清单文件中的<intent-filter>元素定义,并嵌套在相应的应用组件(例如,<activity>元素)中。在<intent-filter>内部,您可以使用以下三个元素中的一个或多个指定要接受的
Intent 类型:

<action>
name属性中,声明接受的 Intent 操作。该值必须是操作的文本字符串值,而不是类常量。
<data>
使用一个或多个指定数据 URI(schemehostportpath 等)各个方面和 MIME 类型的属性,声明接受的数据类型。
<category>
name属性中,声明接受的 Intent 类别。该值必须是操作的文本字符串值,而不是类常量。

注意:为了接收隐式Intent,必须CATEGORY_DEFAULT类别包括在
Intent 过滤器中。方法startActivity()startActivityForResult()将按照已申明CATEGORY_DEFAULT类别的方式处理所有
Intent。 如果未在 Intent 过滤器中声明此类别,则隐式Intent不会解析为您的 Activity。

例如,以下是一个使用Intent过滤器进行的Activity声明,当数据类型为文本时,系统将接收ACTION_SENDIntent :

<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>

您可以创建一个包括多个<action>、<data>或 <category>实例的过滤器。创建时,仅需确定组件能够处理这些过滤器元素的任何及所有组合即可。

如需仅以操作、数据和类别类型的特定组合来处理多种 Intent,则需创建多个 Intent 过滤器。

限制对组件的访问

使用 Intent 过滤器时,无法安全地防止其他应用启动组件。尽管 Intent 过滤器将组件限制为仅响应特定类型的隐式 Intent,但如果开发者确定您的组件名称,则其他应用有可能通过使用显式 Intent 启动您的应用组件。如果必须确保只有您自己的应用才能启动您的某一组件,请针对该组件将exported属性设置为"false"

系统通过将 Intent 与所有这三个元素进行比较,根据过滤器测试隐式 Intent。隐式 Intent 若要传递给组件,必须通过所有这三项测试。如果 Intent 甚至无法匹配其中任何一项测试,则 Android 系统不会将其传递给组件。但是,由于一个组件可能有多个 Intent 过滤器,因此未能通过某一组件过滤器的 Intent 可能会通过另一过滤器。如需了解有关系统如何解析 Intent 的详细信息,请参阅下文的 Intent
解析
部分。

警告:为了避免无意中运行不同应用的 Service,请始终使用显式 Intent 启动您自己的服务,且不必为该服务声明 Intent 过滤器。

注意:对于所有 Activity,您必须在清单文件中声明 Intent 过滤器。但是,广播接收器的过滤器可以通过调用registerReceiver()动态注册。稍后,您可以使用unregisterReceiver()注销该接收器。这样一来,应用便可仅在应用运行时的某一指定时间段内侦听特定的广播。

过滤器示例

为了更好地了解一些 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操作指示这是主要入口点,且不要求输入任何 Intent 数据。
  • CATEGORY_LAUNCHER类别指示此 Activity 的图标应放入系统的应用启动器。如果<activity>元素未使用icon指定图标,则系统将使用<application>元素中的图标。

这两个元素必须配对使用,Activity 才会显示在应用启动器中。

第二个 Activity ShareActivity 旨在便于共享文本和媒体内容。尽管用户可以通过从MainActivity导航进入此 Activity,但也可以从发出隐式 Intent(与两个 Intent 过滤器之一匹配)的另一应用中直接进入ShareActivity

注意:MIME 类型application/vnd.google.panorama360+jpg 是一个指定全景照片的特殊 数据类型,您可以使用Google
全景
API 对其进行处理。

使用待定 Intent



PendingIntent对象是Intent对象的包装器。PendingIntent的主要目的是授权外部应用使用包含的Intent,就像是它从您应用本身的进程中执行的一样。

待定 Intent 的主要用例包括:

由于每个Intent对象均设计为由特定类型的应用组件进行处理(ActivityService 或 BroadcastReceiver),因此还必须基于相同的考虑因素创建PendingIntent。使用待定
Intent 时,应用不会使用调用(如startActivity())执行该 Intent。相反,通过调用相应的创建器方法创建 PendingIntent时,您必须声明所需的组件类型:

除非您的应用正在从其他应用中接收待定Intent,否则上述用于创建PendingIntent的方法可能是您所需的唯一PendingIntent方法。

每种方法均会提取当前的应用Context、您要包装的Intent以及一个或多个指定应如何使用该Intent的标志(例如,是否可以多次使用该
Intent)。

如需了解有关使用待定Intent的详细信息,请参阅通知应用小工具API
指南等手册中每个相应用例的相关文档。

时间: 2024-11-23 20:57:13

Intent 和 Intentfilter的相关文章

android笔记--Intent和IntentFilter详解

Intent用于启动Activity, Service, 以及BroadcastReceiver三种组件, 同时还是组件之间通信的重要媒介. 使用Intent启动组件的优势1, Intent为组件的启动提供了一致的编程模型. 无论想要启动的组件是Activity, Service, 还是BroadcastReceiver, 都可以使用Intent封装启动的意图.2, 在某些时候, 应用程序只是想启动具有某种特征的组件, 并不想和某个特定的组件耦合. 使用Intent可以方便的达到这种高层次解耦的

Intent和IntentFilter详解

Intent用于启动Activity, Service, 以及BroadcastReceiver三种组件, 同时还是组件之间通信的重要媒介. 使用Intent启动组件的优势1, Intent为组件的启动提供了一致的编程模型. 无论想要启动的组件是Activity, Service, 还是BroadcastReceiver, 都可以使用Intent封装启动的意图.2, 在某些时候, 应用程序只是想启动具有某种特征的组件, 并不想和某个特定的组件耦合. 使用Intent可以方便的达到这种高层次解耦的

Android的Intent和IntentFilter应用说明一例

转自:http://www.blogjava.net/TiGERTiAN/archive/2010/02/03/311827.html 很多人对文档中的Intent和IntentFilter不理解是什么意思,我这里举例解释下.Intent字面意思就是目标,目的.通俗一点,需要达成某些目标,则需要提供一些动作,这些目标的分类,以及达成这些目标所需要的一些数据等等.Android中的Intent通过Action,Category和data等属性进行了相应的描述,我们想做某些事情(达成某些目标),就需

Android应用程序组件之间的通信Intent和IntentFilter

Android应用程序的基本组件,这些基本组建除了Content Provider之外,几乎全部都是依靠Intent对象来激活和通信的. 下面介绍Intent类,并通过例子来说明Intent一般用法 1.1 Intent类简介 Intent类的对象是组件间通信的载体,组件之间进行通信就是一个个Intent对象在不断地传递.Intent对象主要作用于运行在相同或不同应用程序的Activity,Service和Broadcast Receiver组件之间,对于这3种组件,其作用机制也不相同 一,对于

安卓 Intent 与/intent-filter的关系详解。

Intent可以分为两种:显式Intent和隐式Intent;显式Intent:通过组件名字字段指定目标组件;因为开发者通常不知道其它应用程序的组件名字,所以,显式Intent通常用于应用程序内部消息传递;例如:一个Activity启动从属的服务或启动一个同级别的Activity;隐式Intent:不指定目标组件的名字(组件名字字段是空);隐式Intent经常用于激活其它应用程序中的组件;Android系统传递一个显式Intent消息对象到一个指定目标组件名字的实例,Intent消息对象中只用组

Intent及IntentFilter详解

Intent用于启动Activity, Service, 以及BroadcastReceiver三种组件, 同时还是组件之间通信的重要媒介. 使用Intent启动组件的优势 1, Intent为组件的启动提供了一致的编程模型. 无论想要启动的组件是Activity, Service, 还是BroadcastReceiver, 都可以使用Intent封装启动的意图. 2, 在某些时候, 应用程序只是想启动具有某种特征的组件, 并不想和某个特定的组件耦合. 使用Intent可以方便的达到这种高层次解

Intent以及IntentFilter详解

1. 前言 在Android中有四大组件,这些组件中有三个组件与Intent相关,可见Intent在Android整个生态中的地位高度.Intent是信息的载体,用它可以去请求组件做相应的操作,但是相对于这个功能,Intent本身的结构更值得我们去研究. 2. Intent与组件 Intent促进了组件之间的交互,这对于开发者非常重要,而且它还能做为消息的载体,去指导组件做出相应的行为,也就是说Intent可以携带数据,传递给Activity/Service/BroadcastReceiver.

Intent和IntentFilter的理解

<activity android:name=".SecondActivity"> <intent-filter> <action android:name="hello1" /> <action android:name="hello2" /> <category android:name="android.intent.category.DEFAULT" /> &

[转]Intent和IntentFilter详解

Intent   Android中提供了Intent机制来协助应用间的交互与通讯,Intent负责对应用中一次操作的动作.动作涉及数据.附加数据进行描述,Android则根据此Intent的描述,负责找到对应的组件,将 Intent传递给调用的组件,并完成组件的调用.Intent不仅可用于应用程序之间,也可用于应用程序内部的Activity/Service之间的交互.因此,Intent在这里起着一个媒体中介的作用,专门提供组件互相调用的相关信息,实现调用者与被调用者之间的解耦.在SDK中给出了I

android:android Intent and IntentFilter

文章来自:http://blog.csdn.net/intbird 如果说是将一个activity有其他应用打开,或者是在webView中调用我们自己的activity,那么最好就是使用intentfilter来过滤我们需要的activity; 说明什么是uri参数 Java Code: final Uri uri = Uri.parse("intbird://com.intbird.soft/testing/tested?name='Test'"); TextView textVie