Android - 和其他APP交互 - 把用户带到其他app

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作为数据来启动拨打电话:

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

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

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

  • 显示地图:

1 // 地址对应的地图上的点
2 Uri location = Uri.parse("geo:0,0?q=1600+Amphitheatre+Parkway,+Mountain+View,+California");
3 // 或者经纬度对应地图上的点
4 // Uri location = Uri.parse("geo:37.422219,-122.08364?z=14"); // z代表缩放等级
5 Intent mapIntent = new Intent(Intent.ACTION_VIEW, location);
  • 显示网页:

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

另外一些模糊Intent需要其他额外的其他类型的数据,比如字符串。可以使用putExtra()方法来添加其他数据。

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

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

  • 发送带附件的邮件

1 Intent emailIntent = new Intent(Intent.ACTION_SEND);
2 // 这个Intent没有URI,所有声明"text/plain" MIME 类型
3 emailIntent.setType(HTTP.PLAIN_TEXT_TYPE);
4 emailIntent.putExtra(Intent.EXTRA_EMAIL, new String[] {"jon@example.com"}); // recipients
5 emailIntent.putExtra(Intent.EXTRA_SUBJECT, "Email subject");
6 emailIntent.putExtra(Intent.EXTRA_TEXT, "Email message text");
7 emailIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse("content://path/to/email/attachment"));
8   // 也可以通过传递Uri的ArrayList来添加多条数据
  • 创建日历事件

1 Intent calendarIntent = new Intent(Intent.ACTION_INSERT, Events.CONTENT_URI);
2 Calendar beginTime = Calendar.getInstance().set(2012, 0, 19, 7, 30);
3 Calendar endTime = Calendar.getInstance().set(2012, 0, 19, 10, 30);
4 calendarIntent.putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, beginTime.getTimeInMillis());
5 calendarIntent.putExtra(CalendarContract.EXTRA_EVENT_END_TIME, endTime.getTimeInMillis());
6 calendarIntent.putExtra(Events.TITLE, "Ninja class");
7 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了,例如:

1 PackageManager packageManager = getPackageManager();
2 List<ResolveInfo> activities = packageManager.queryIntentActivities(intent, 0);
3 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,系统会立刻启动它。

1 startActivity(intent);

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

这里是一个创建intent来显示地图的完整的例子来,确认有app可以处理这个intent,然后启动它:

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

显示一个app选择器

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

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

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

1 Intent intent = new Intent(Intent.ACTION_SEND);
2 ...
3                     
4 // Always use string resources for UI text. This says something like "Share this photo with"
5 String title = getResources().getText(R.string.chooser_title);
6 // Create and start the chooser
7 Intent chooser = Intent.createChooser(intent, title);
8 startActivity(chooser);

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

 

 

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

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

 

posted @ 2013-06-18 23:30  fengquanwang  阅读(906)  评论(0编辑  收藏  举报