欢迎访问移动开发之家(rcyd.net),关注移动开发教程。移动开发之家  移动开发问答|  每日更新
页面位置 : > > > 内容正文

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

来源: 开发者 投稿于  被查看 22591 次 评论:40

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


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包含某类数据的位置,那么通常可以从中推测出数据的类型。

可选类别

如果操作用于描述具体要做什么,那么类别通常用来描述我们是何时、何地或者说如何使用某个activity的。
Android的android.intent.category.LAUNCHER类别表明,activity应该显示在顶级应用启动器中。
而android.intent.category.INFO类别表明,虽然activity向用户显示了包信息,但它不应该显示在启动器中。

一个用来查看某个网址的简单隐式intent会包括一个Intent.ACTION_VIEW操作,以及某个具体URL网址的uri数据。

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

举例intent过滤器

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

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


   
      
      
      
   
 

DEFAULT类别必须明确地在intent过滤器中进行设置。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 type
emailIntent.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

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

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

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

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

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

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

// 新建的隐式intent将由操作以及数据获取位置组成。
// 操作为Intent.ACTION_PICK
// 数据位置为ContactsContract.Contacts.CONTENT_URI,联系人通讯录
Intent i = new Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI);

// 检查设备中可以响应的activity
PackageManager pm = getActivity().getPackageManager();
List 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,并且指定了标题。

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

 

用户评论