Android学习之基于隐式的Intent的通讯

来源:互联网 发布:大学生网络赚钱 编辑:程序博客网 时间:2024/05/21 10:27

Intent隐式通讯

Intent对象可以向操作系统描述我们需要处理的任务。使用显式intent,我们需明确地告诉操作系统要启动的activity类名。

下面是之前创建过的显式intent:

Intent i = new intent(Context packageContext, Class<?> cls);
startActivity(i);

而使用隐式intent,只需向操作系统描述清楚我们的工作意图。操作系统会去启动那些对外宣称能够胜任工作任务的activity。如果操作系统找到多个符合的activity,用户将会看到一个可选应用列表,然后就看用户如何选择了。

隐式intents并不声明要启动组件的具体类名,而是声明一个需要执行的action。这个action指定了我们想做的事情,例如查看,编辑,发送或者是获取一些东西。

Intents通常会在发送action的同时附带一些数据,例如你想要查看的地址或者是你想要发送的邮件信息。
数据的具体类型取决于我们想要创建的Intent,比如Uri或其他规定的数据类型,或者甚至也可能根本不需要数据。

典型隐式intent的组成

下面是一个隐式intent的主要组成部分,可以用来定义我们的工作任务。

要执行的操作

通常以Intent类中的常量来表示。
例如,要访问查看某个URL,可以使用Intent.ACTION_VIEW
要发送邮件,可以使用Intent.ACTION_SEND

例如,查看网页:

Uri webpage = Uri.parse("http://www.android.com");Intent webIntent = new Intent(Intent.ACTION_VIEW, webpage);

要访问数据的位置

这可能是设备以外的资源,如某个网页的URL,也可能是指向某个文件的URI,或者是指向ContentProvider中某条记录的某个内容URI(content URI)。

如果数据是一个Uri,会有一个简单的Intent() 构造方法 用于定义action与data。

例如,下面是一个带有指定电话号码的intent:

Uri number = Uri.parse("tel:1234567");Intent callIntent = new Intent(Intent.ACTION_DIAL, number);

操作涉及的数据类型

这指的是MIME形式的数据类型,如text/html或audio/mpeg3。

如果一个intent包含某类数据的位置,那么通常可以从中推测出数据的mime类型。

可选类别Category

如果操作用于描述具体要做什么,那么类别通常用来描述我们是何时、何地或者说如何使用某个activity的。

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

Android的android.intent.category.LAUNCHER类别表明,activity应该显示在顶级应用启动器中。

android.intent.category.INFO类别表明,虽然activity向用户显示了包信息,但它不应该显示在启动器中。

基于以上信息,操作系统将启动适用应用的适用activity(如果有多个适用应用可选,用户可自行如何选择)。

举例intent过滤器

通过配置文件中的intent过滤器设置,activity会对外宣称自己是适合处理ACTION_VIEW的activity。

如果是开发一款浏览器应用,为响应ACTION_VIEW操作,需要在activity声明中包含以下intent过滤器:

<activity   android:name=".BrowserActivity"   android:label="@string/app_name">   <intent-filter>      <action android:name="android.intent.action.VIEW" />      <category android:name="android.intent.category.DEFAULT" />      <data android:scheme="http" android:host="www.csdn.net" />   </intent-filter> </activity>

intent过滤器中的action元素告诉操作系统,activity能够处理指定的任务;

DEFAULT类别告诉操作系统,activity愿意处理某项任务。DEFAULT类别必须明确地在intent过滤器中进行设置。

DEFAULT类别实际隐含添加到了几乎每一个隐式intent中。(唯一的例外是LAUNCHER类别)。

有时间再探索下这个Intent过滤器的使用^_^

隐式intent的附加数据

如同显式intent,隐式intent也可以包含extra信息。不过,操作系统在寻找适用的activity时,它不会使用任何附加在隐式intent上的extra。

一些需要extra数据的隐式intent,我们可以使用 putExtra() 方法来添加那些数据。

默认的,系统会根据Uri数据类型来决定需要哪些合适的MIME type。如果我们没有在intent中包含一个Uri, 则通常需要使用 setType() 方法来指定intent附带的数据类型。设置MIME type 是为了指定应该接受这个intent的activity

例如,发送一个带附件的email:

Intent emailIntent = new Intent(Intent.ACTION_SEND);// 这个 intent 没有一个URI, 因此需要声明"text/plain" MIME typeemailIntent.setType(HTTP.PLAIN_TEXT_TYPE);emailIntent.putExtra(Intent.EXTRA_EMAIL, new String[] {"dengfengdecao@example.com"}); // 收件人emailIntent.putExtra(Intent.EXTRA_SUBJECT, "Email 主题");emailIntent.putExtra(Intent.EXTRA_TEXT, "Email的文本信息");emailIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse("content://path/to/email/attachment"));// 你也可以附加多个项通过ArrayList<Uris>

注意:请尽可能的将隐式Intent定义的更加确切。例如,如果想要使用ACTION_VIEW 的intent来显示一张图片,则还应该指定 MIME type 为image/*.这样能够阻止其他能够 “查看” 其他数据类型的app(比如一个地图app) 被这个intent唤起。

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

例如:

static final String EXTRA_GIGAWATTS = "com.example.EXTRA_GIGAWATTS";

验证是否有App去接收这个Intent

尽管Android系统会确保每一个确定的intent会被系统内置的app(如the Phone, Email, or Calendar app)之一接收,但是我们还是应该在触发一个intent之前做验证是否有App接受这个intent的步骤。

Note:如果系统没有对应的activity被唤起,则应用会崩溃!

为了验证是否有合适的activity会响应这个intent,
需要执行queryIntentActivities()方法来获取到能够接收这个intent的所有activity的列表。
若返回的activity列表非空,那么我们才可以安全的使用这个intent。

下面是一个演示了如何创建一个intent来查看通讯录联系人的完整例子,首先验证有app可以处理这个intent,然后启动它

// 新建的隐式intent将由操作以及数据获取位置组成。// 操作为Intent.ACTION_PICK// 数据位置为ContactsContract.Contacts.CONTENT_URI,联系人通讯录Intent i = new Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI);// 检查设备中可以响应的activityPackageManager pm = getActivity().getPackageManager();List<ResolveInfo> activities = pm.queryIntentActivities(i, 0);boolean isIntentSafe = activities.size() > 0;if (isIntentSafe) {    // 需要从打开的activity中获得返回数据    startActivityForResult(i, CONTACT_REQUEST_CODE);}

Note:我们必须在第一次使用之前做这个检查,若是不可行,则应该关闭这个功能。

使用Intent启动Activity

当创建好了intent并且设置好了extra数据后,通过执行startActivity() 将intent发送到系统。若系统确定了多个activity可以处理这个intent,它会显示出一个对话框,让用户选择启动哪个app。如果系统发现只有一个app可以处理这个intent,则系统将直接启动该app。

startActivity(intent);

这里写图片描述

显示分享App的选择界面

当以startActivity()的形式传递一个intent,并且有多个app可以处理时,用户可以在弹出对话框的时候选择默认启动的app(通过勾选对话框下面的选择框,如上图所示)。该功能对于用户有特殊偏好的时候非常有用(例如用户总是喜欢启动某个app来查看网页,总是喜欢启动某个camera来拍照)。

然而,如果用户希望每次都弹出选择界面,而且每次都不确定会选择哪个app启动,例如分享功能,用户选择分享到哪个app都是不确定的,这个时候,需要强制弹出选择的对话框。(这种情况下用户不能选择默认启动的app)。

为了显示选择对话框, 需要使用createChooser()来创建Intent。

Intent intent = new Intent(Intent.ACTION_SEND);...// 分享对话框的标题String title = getResources().getText(R.string.chooser_title);// 创建和启动选择器Intent chooser = Intent.createChooser(intent, title);startActivity(chooser);

这里写图片描述

这样就列出了可以响应createChooser()中Intent的app,并且指定了标题。

隐式Intent示例

// 创建文本信息Intent sendIntent = new Intent();sendIntent.setAction(Intent.ACTION_SEND);sendIntent.putExtra(Intent.EXTRA_TEXT, textMessage);sendIntent.setType("text/plain");// 验证是否有可解析该Intent的activityif (sendIntent.resolveActivity(getPackageManager()) != null) {    startActivity(sendIntent);}

Note:该示例并没有使用 URI,但已声明 Intent 的数据类型,用于指定 Extra 携带的内容。

接收隐式Intent

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

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

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

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

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

系统通过将 Intent 与所有这三个元素进行比较,根据过滤器测试隐式 Intent。隐式 Intent 若要传递给组件,必须通过所有这三项测试。

如果 Intent 甚至无法匹配其中任何一项测试,则 Android 系统不会将其传递给组件。但是,由于一个组件可能有多个 Intent 过滤器,因此未能通过某一组件过滤器的 Intent 可能会通过另一过滤器。

Android学习之基于显式的Intent的通讯

参考资料:
http://developer.android.com/training/basics/intents/sending.html

0 0
原创粉丝点击