【Android基础】Android利用Intent与其他应用交互

前言:

上一篇博客给大家聊了Intent的定义,分类、属性和功能,相信大家对于Intent在Android中的作用已经清楚,这一篇博客将会给大家聊Intent的用法。

Android系统的一个重要特性就是一个应用程序可以调用另外一个应用程序来完成用户的请求动作。比如你的应用程序需要给用户显示一个地理位置在地图上,你不必在你的应用程序中实现地图功能,而是创建一个显示这个地理位置的Intent,发送出去,Android系统会启动那些可以处理这个请求的应用程序。还比如:你用百度云盘下载了一个pdf文档,你在点击打开这个文档的时候百度云盘是无法打开的,但是也许你系统上安装有其他的能打开pdf文档的阅读器,这个时候就会弹出一个对话框,列举了可以打开pdf文档的应用程序,你可以自由选择一个应用程序打开你下载的文档。

使用隐式Intent:

隐式Intent不会指明要启动的组件名称,而是声明执行的动作,动作指定了你想要做什么事情,比如显示(view),编辑(edit),发送(send),获取一些东西(get something)等。Intent经常会附带一些数据,比如你要查看的地址,发送邮件的内容等。数据形式依赖于你想要做什么事情,数据可以是一个Uri,也可以是其他数据类型(基本数据类型或者对象)之一。数据不是必须的,你的Intent中可以不包含data。

如果你的数据(data)是Uri,可以利用Intent( action,Uri)的构造函数方便的创建Intent,下面的例子就是创建一个打电话的Intent,数据就是一个包含电话号码的Uri:

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

当你在你的应用程序中调用startActivity(Intent intent),传入上面的Intent,电话应用程序就会呼叫你上面指定的电话号码。下面是两个利用Intent实现其他功能的例子。

在地图应用上查看地理位置:

// Map point based on address 
Uri location = Uri.parse("geo:0,0?q=1600+Amphitheatre+Parkway,+Mountain+View,+California");
// Or map point based on latitude/longitude 
// Uri location = Uri.parse("geo:37.422219,-122.08364?z=14"); // z param is zoom level 
Intent mapIntent = new Intent(Intent.ACTION_VIEW, location);

在浏览器上查看请求的网址:

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

上面的Intent都是不带data的,但是有的时候Intent需要附带数据,数据可以是string,可以是基本数据类型,你可以调用putExtra()方法设置多个数据。

Intent数据是有数据类型的,这个数据类型叫做MIME类型,默认情况下系统通过数据中包含的Uri数据来确定数据的MIME类型,如果数据中不包含Uri,那么你需要调用setType()设置Intent数据的MIME类型。设置MIME类型进一步指定了哪些类型的Activity可以响应这个Intent。

注:MIME:全称Multipurpose Internet Mail Extensions,多功能Internet 邮件扩充服务。它是一种多用途网际邮件扩充协议,在1992年最早应用于电子邮件系统,但后来也应用到浏览器。MIME类型就是设定某种扩展名的文件用一种应用程序来打开的方式类型,当该扩展名文件被访问的时候,浏览器会自动使用指定应用程序来打开。多用于指定一些客户端自定义的文件名,以及一些媒体文件打开方式。在Android中通过文件的MIME类型来判断有哪些应用程序可以处理这些文件,并使用其中的某一个应用程序(如果有多个可选的应用程序,则用户必须指定一个)处理之。

下面是附带数据的Intent例子:

发送带有附件的Email:

Intent emailIntent = new Intent(Intent.ACTION_SEND);
// The intent does not have a URI, so declare the "text/plain" MIME type 
emailIntent.setType(HTTP.PLAIN_TEXT_TYPE);
emailIntent.putExtra(Intent.EXTRA_EMAIL, new String[] {"jon@example.com"}); // recipients
emailIntent.putExtra(Intent.EXTRA_SUBJECT, "Email subject");
emailIntent.putExtra(Intent.EXTRA_TEXT, "Email message text");
emailIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse("content://path/to/email/attachment"));
// You can also attach multiple items by passing an ArrayList of Uris

创建日历事件(API level 14 and higher):

Intent calendarIntent = new Intent(Intent.ACTION_INSERT, Events.CONTENT_URI);
Calendar beginTime = Calendar.getInstance().set(2012, 0, 19, 7, 30);
Calendar endTime = Calendar.getInstance().set(2012, 0, 19, 10, 30);
calendarIntent.putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, beginTime.getTimeInMillis());
calendarIntent.putExtra(CalendarContract.EXTRA_EVENT_END_TIME, endTime.getTimeInMillis());
calendarIntent.putExtra(Events.TITLE, "Ninja class");
calendarIntent.putExtra(Events.EVENT_LOCATION, "Secret dojo");

注意:你的Intent尽可能的详细说明你的意图,设定Intent数据MIME类型是很重要的。比如你想打开一个图片通过ACTION_VIEW intent,你应该设置MIME 类型为"image/*",这样就可以阻止调用到其他类型的应用程序,比如地图应用,而是明确只有能查看图片的应用程序才能响应这个Intent。

验证Intent是否有效:

尽管Android系统内置的应用程序(比如:电话,邮件,日历)能够保证一些Intent肯定会被响应,但是你在发送一个Intent之前最好是要验证一下Intent能否会被系统处理。如果你发送的Intent没有应用程序能够处理,那么你的应用程序会出现crash现象。

你可以调用queryIntentActivities()方法来验证Intent是否会有Activity响应,queryIntentActivities()返回一个能够响应该Intent的Activity列表,如果列表不为空,那么你就可以放心的发送这个Intent了。验证Intent的代码如下:

PackageManager packageManager = getPackageManager();
List activities = packageManager.queryIntentActivities(intent,
        PackageManager.MATCH_DEFAULT_ONLY);
boolean isIntentSafe = activities.size() > 0;

下面的例子是完整的启动地图应用的例子,包含启动前Intent的安全检查:

// Build the intent 
Uri location = Uri.parse("geo:0,0?q=1600+Amphitheatre+Parkway,+Mountain+View,+California");
Intent mapIntent = new Intent(Intent.ACTION_VIEW, location);
 
// Verify it resolves 
PackageManager packageManager = getPackageManager();
List<ResolveInfo> activities = packageManager.queryIntentActivities(mapIntent, 0);
boolean isIntentSafe = activities.size() > 0;
 
// Start an activity if it's safe 
if (isIntentSafe) {
    startActivity(mapIntent);
}

显示应用选择器:

有的时候你在调用startActivity()向系统请求Activity处理你的请求时会有多个应用程序响应,用户需要选择一个应用程序来处理这个意图请求,这种体验非常好,用户可以自由选择应用程序,也可以指定默认用哪个应用程序响应这个请求,比如拍照,查看图片,上网。给用户显示这种应用选择器需要调用creatChooser()创建你的Intent,例如:

Intent intent = 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 chooser 
Intent chooser = Intent.createChooser(intent, title);
 
// Verify the intent will resolve to at least one activity 
if (intent.resolveActivity(getPackageManager()) != null) {
    startActivity(chooser);
}

上面的例子会弹出一个包含很多应用的Dialog,这些应用都是能够响应这个Intent的应用。


原文发布于微信公众号 - 程序员互动联盟(coder_online)

原文发表时间:2015-08-10

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏非著名程序员

我所理解的Intent 和Intent-filter

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

1899
来自专栏ios 技术积累

利用Runtime实现NScoding

最近项目需要缓存,因为项目都是用的对象,要缓存对象必须实现NSCoding协议,但是每个Model都要实现

1191
来自专栏女程序员的日常

STM8S——Flash program memory and data EEPROM

1、简介   STM8S内部的FLASH程序存储器和数据EEPROM是由一组通用寄存器来控制的;所以我们可以通过这些通用寄存器来编程或擦除存储器的内容、设置写保...

2541
来自专栏程序员互动联盟

【Android基础】Android中的Intent详解

前言: 每个应用程序都有若干个Activity组成,每一个Activity都是一个应用程序与用户进行交互的窗口,呈现不同的交互界面。因为每一个Acticity...

3417
来自专栏非著名程序员

Android 图片选择到裁剪之步步深坑

前言 最近在自己的项目里实现了一个头像选择的功能,就是先从相册里选取一张图片再调用系统的裁剪功能来制作头像,效果就像下面这样: ? 本以为很小的一个功能,却远远...

3268
来自专栏分享达人秀

四大组件的纽带——Intent

前面学习Activity时己经多次使用了 Intent,当一个Activity需要启动另一个Activity时, 程序并没有直接告诉系统要启动哪个Act...

2135
来自专栏向治洪

软件更新时候出现和原包名冲突

如果你是一个开发人员,那么出现这个问题可能是因为,较旧的版本你是使用eclipse自动发布到模拟器上的,而eclipse自动发布时使用的是一个测试用签名,这个签...

1856
来自专栏码农笔录

Android N 7.0 上安装apk问题

1183
来自专栏Android干货

Android项目实战(四十九):Andoird 7.0+相机适配

一、在AndroidManifest.xml 文件中添加 四大组件之一的 <provider>

770
来自专栏WD学习记录

8-25 Android 学习ing

1>intent.setClass(this,OtherActivity.class)

1172

扫码关注云+社区