Android的重要功能之一就是app可以根据要执行的操作让用户启动另外一个app。例如,app有一个商业地址然后想要在地图上显示,并不需要在app中加一个显示地图的activity,可以直接用Intent创建一个要显示地址的请求,Android系统会启动一个可以显示地图的app。

就像以前讲到的,可以使用Intent在app中的activity之间切换。基本上是使用的明确的Intent,也就是明确定义了要启动的组件的类名。然而,当要启动另外一个app来执行操作时,比如展示地图,就要使用模糊的Intent了。

这里将要介绍如何为特定的操作创建模糊的Intent,和如何使用它来启动其他app中的activity来执行操作。

创建一个模糊的Intent

模糊的Intent不会声明要启动的组件的类名,但是声明要执行的操作。这个操作指定了要做的事情,比如展示,编辑,发送或者获得一些东西。Intent通常包含了操作相关的数据,比如要展示的地址,要发送的email的内容。根据创建的Intent,数据可能是Uri,或者很多其他类型的数据,或者根本就不需要数据。

如果数据是Uri,有一个简单的Intent()构造函数可以定义操作和数据。

例如,这里就是如何创建一个Intent来用代表电话号码的Uri作为数据来启动拨打电话:

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

当app通过调用startActivity()调用Intent时,电话app就会用给的电话号码发起一个电话。

这里有一些其他的Intent和它们的操作还有Uri数据:

  • 显示地图:

 // 地址对应的地图上的点
Uri location = Uri.parse("geo:0,0?q=1600+Amphitheatre+Parkway,+Mountain+View,+California");
// 或者经纬度对应地图上的点
// Uri location = Uri.parse("geo:37.422219,-122.08364?z=14"); // z代表缩放等级
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需要其他额外的其他类型的数据,比如字符串。可以使用putExtra()方法来添加其他数据。

默认情况,系统会根据Uri包含的数据决定Intent需要的合适的MIME类型。如果Intent中不包含Uri,通常应该用setType()来指定Intent相关的数据类型。设置MIME类型在后面可以指定哪种activity会接收这个Intent。

这里有一些加了额外数据来指定特殊操作的intent:

  • 发送带附件的邮件

 Intent emailIntent = new Intent(Intent.ACTION_SEND);
// 这个Intent没有URI,所有声明"text/plain" MIME 类型
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"));
// 也可以通过传递Uri的ArrayList来添加多条数据
  • 创建日历事件

 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只在API等级14或更高版本中支持

注意:定义Intent要越明确越好。比如,如果用ACTION_VIEWintent来显示一张图片,应该指定MIME类型为image/*。这样可以防止显示其他类型的数据(比如显示地图)的app被intent调用了。

检测是否有app来接收intent

虽然Android平台保证一些确定的intent会被内置的App(比如电话,email或者日历)处理,但是在调用intent之前也应该加上确认步骤。

注意:如果调用了一个intent,然后设备上没有能处理这个intent的app,程序会崩溃。

要检测是否有可以响应intent的activity的话,调用queryIntentActivities()来获得可以处理Intent的activity列表。如果返回的列表不为空,就可以安全的使用Intent了,例如:

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

如果isIntentSafe为true,那么至少有一个app可以响应intent。如果为false,那么没有app能响应intent。

注意:在activity第一次启动时就应该做这个检测,这样是为了防止在用户打算用intent时你需要屏蔽这个功能。如果明确的知道有一个app可以处理这个intent,也可以提供一个链接让用户来下载app(查看link to your product on Google Play)。

用Intent来启动一个Activity

在创建Intent然后设置附加信息后,调用startActivity()来把它发送给系统。如果系统发现超过一个activity可以处理这个Intent,会显示一个对话框让用户选择用哪个app,如图1所展示的。如果只有一个activity可以处理这个intent,系统会立刻启动它。

 startActivity(intent);

图1.超过一个app可以处理intent时的对话框示例

这里是一个创建intent来显示地图的完整的例子来,确认有app可以处理这个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);
}

显示一个app选择器

当用户通过传递Intent给startActivity()来启动一个activity,并且有超过一个app可以响应这个intent。用户可以选择一个默认的使用的app(通过勾选一个对话框下面的复选框;见图1)。当用户每次都要用同一个app时这是个很好的方法,比如打开网页(用户通常只喜欢一种浏览器)或者照相(用户一般只喜欢一种相机)。但是,如果这个动作可以被多个app处理并且用户可能每次都会选择不一样的ap,比如分享功能,用户可能会很多个app来分享,很明显需要显示一个选择对话框,它可以强迫用户每次都选择哪个app来执行操作(用户不能选择默认的app来执行这个操作)。

图2.用createChooser()来保证用户每次都要从列表种选择app的例子

要显示选择器,创建用createChooser()创建一个Intent然后传递个startActivity(),例如:

 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().getText(R.string.chooser_title);
// Create and start the chooser
Intent chooser = Intent.createChooser(intent, title);
startActivity(chooser);

它显示了能响应传递给createChooser()的intent的app列表对话框并且使用了提供的字符串作为对话框的标题。

上一篇:Android - 和其他APP交互

下一篇:Android - 和其他APP交互 - 获得activity的返回值

Android - 和其他APP交互 - 把用户带到其他app的更多相关文章

  1. Android - 和其他APP交互 - 获得activity的返回值

    启用另一个activity不一定是单向的.也可以启用另一个activity并且获得返回值.要获得返回值的话,调用startActivityForResult()(而不是startActivity()) ...

  2. Android - 和其他APP交互

    一个Android app通常有好几个activity.每个activity显示一个可以让用户执行特殊操作(例如看地图,照相等)的界面.要让用户从一个activity切换到另一个activity,ap ...

  3. Android - 和其他APP交互 - 让其他app启动你的activity

    前面的两篇文章主要讲了一个方面:从app中启动其他app.但是如果你的app可以处理对其他app有用的操作,你的app也应该响应其他app的操作请求.例如,如果你创建了一个社交app可以分享信息和图片 ...

  4. Android开发5:应用程序窗口小部件App Widgets的实现

    前言 本次主要是实现一个Android应用,实现静态广播.动态广播两种改变 widget内容的方法,即在上篇博文中实验的基础上进行修改,所以此次实验的重点是AppWidget小部件的实现啦~ 首先,我 ...

  5. Android 5.0 Default SMS App以及运营商授权SMS App

    已同步更新至个人blog:http://dxjia.cn/2015/08/android-5-default-sms-app/ 题外话:博友们有没有好用的写博客客户端推荐啊,cnblogs推荐的win ...

  6. Android 实现切换主题皮肤功能(类似于众多app中的 夜间模式,主题包等)

    首先来个最简单的一键切换主题功能,就做个白天和晚上的主题好了. 先看我们的styles文件: <resources> <!-- Base application theme. --& ...

  7. Android官方技术文档翻译——Gradle 插件用户指南(4)

    最近赶项目,白天基本没时间,只有晚上在家的时候才能看一看.昨天晚上只翻译完了第四章,今天就只发第四章吧. 本文译自Android官方技术文档<Gradle Plugin User Guide&g ...

  8. [Unity][安卓]Unity和Android Studio 3.0 交互通讯(1)Android Studio 3.0 设置

    [安卓]Android Studio 3.0 JDK安卓环境配置(2017.10) http://blog.csdn.net/bulademian/article/details/78387052 [ ...

  9. 如何用Axure快速制作APP交互原型

    对于产品经理来说,熟练使用一些常用软件是一项十分必要的技能.其中,作为一个专业的快速原型设计工具,Axure RP无疑在产品人心中拥有一个难以撼动的地位.但就要PS一样,虽然足够专业,但同样也会存在使 ...

随机推荐

  1. setChecked方法触发onCheckedChanged监听器问题

    有时须要在程序初始化界面时,讲有些比如toggleButton等控件依照需求勾选,此时会发现,当我setChecked时会触发onCheckedChanged监听器,导致这部分代码被调用两次.解决方法 ...

  2. ZOJ 1610 间隔染色段树

    要长8000仪表板.间染色的范围,问:最后,能看到的颜色,而且颜色一共有段出现 覆盖段 数据对比水   水可太暴力 段树: #include "stdio.h" #include ...

  3. Unity3D ITween!

    percentage +=0.001f; iTween.PutOnPath(gameObject,path,percentage); //You can cause the object to ori ...

  4. configure: error: zlib not installed

    export LDFLAGS="-L/usr/local/zlib/lib" export CPPFLAGS="-I/usr/local/zlib/include&quo ...

  5. C++内存管理学习笔记(7)

    /****************************************************************/ /*            学习是合作和分享式的! /* Auth ...

  6. 物联网 开发板 基于ESP8266

    The ESP8266 The ESP8266 is a highly integrated chip designed for the needs of an increasingly connec ...

  7. SVN的revert和update命令的区别

    svn中的revert和update 今天有人问到revert和update的问题. 刚开始还真被问住了. 因为感觉revert和update都可以将本地的copy更新到以前的一个版本,会有什么不同呢 ...

  8. java导入excel

    package com.duosen.gate.test; import java.io.File; import java.io.FileInputStream; import java.io.Fi ...

  9. java中final的意义

    1.如果一个数据既是static又是final,那么它会拥有一块无法改变的存储空间. 2.final data: 当final用于基本数据类型时,final让其值(value)保持不变,但是当用于ob ...

  10. swift 进阶笔记 (一) —— 可选型

    swift定义可选型的时候,要用"?",可是在swift的标准库中,可选型的定义是Optional<T>,"? "仅仅是个简写形式. var myN ...