让用户转移到另一个应用程序
http://docs.eoeandroid.com/training/basics/intents/sending.html
http://training.eoeandroid.com/#Sending_the_User_to_Another_App
作者:handsomedylan
目录 |
Sending the User to Another App-把用户送往其他应用
Android最重要的特性之一就是:一个应用可以基于不同的 action,把用户推送到其他应用中去。比如说,如果你想在你的应用中显示一张带有商店地址的地图,你并不需要在自己的应用中去实现一个显示地图的Activity,而是可以通过Intent来发出一个请求来显示这个商店的地址,Android系统会自动帮你打开一个合适的应用。
正如在第一节课——创建你的第一个应用——里学到的,在你的应用中,你必须使用Intents来在你应用里的Activity之间游走。通常你都需要一个显式的Intent,即包含有确切类名信息的Intent.但是当你想要从一个独立应用中去完成一个action,比如打开一个地图,那么你必须使用隐式的Intent. 这节课向你展示,如何创建一个隐式的intent来完成一个特定的action,以及如何使用它来启动一个activity并且在别的应用里实现该action。
创建一个隐式的Intent
创建一个隐式的Intent并不声明要启动的组件的类名,而是声明要执行的一个动作(action),这个action详述了你想要做的事,比如观看,编辑,发送或是获取一些数据。Intent也经常在action里附加相关的数据,比如你想访问的地址,或是你发送邮件的内容。根据你想创建的intent,数据可能是一个Uri或是其它数据类型,也可能不包含任何数据。
如果你的数据是一个Uri,那么你可以很调用一个很简单的Intent()构造函数来定义action和数据。
例如,以下是如何创建一个Intent来打电话,在这里我们用Uri数据来表示电话号码。
Uri number = Uri.parse("tel:5551234"); Intent callIntent = new Intent(Intent.ACTION_DIAL, number);
当你的应用通过startActivity来使用该intent时,电话应用程序就会朝给定的号码打电话。
以下是一些其它的intent以及他们的action和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需要"附加的"其它类型的数据,比如string,你可以通过不同的putExtra()方法来增加一个或多个附加数据。
默认情况下,系统通过intent附加的Uri数据来决定适合的MIME类型,如果你的intent里并没有Uri,那么你需要使用setType()来明确intent相关的数据类型。而确定MIME类型更加明确了哪一类activity才是最应该接受该intent的。
以下是包含附加数据的intent:
- 发送带附件的email:
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"}); // 收件人 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来附加多个数据
- 创建一个月历事件。
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,仅可在API14及以上的版本中才可使用。
注意:把你的Intent定义的尽可能明确是什么重要的,比如说,如果你想要通ACTION_VIEW来显示一张图片,你应该明确MIME类型为image/*.这样就可以防止误启动别的支持该action的可以显示别的数据类型的应用,比如map应用。
Verify There is an App to Receive the Intent-确保有一个应用接收了Intent
尽管Android平台确保特定的intent会被解析到一个内建的应用程序(比如电话,短信,日历),你仍然需要在使用intent前进行一下确认。
小心:如果你发起一个在设备上无法被任何应用程序处理的intent,那么你的程序就会崩溃。
为了确认有一个activity能响应该intent,可以使用queryIntentActivities()来获取一个能处理该intent的activity列表,如果返回的列表非空,那么你就可以安全的使用这个intent了。例如:
PackageManager packageManager = getPackageManager(); List<ResolveInfo> activities = packageManager.queryIntentActivities(intent, 0); boolean isIntentSafe = activities.size() > 0;
如果 isIntentSafe为真,那么至少有一个程序会响应该intent,反之,则没有。
注意:你应该在程序一开始时就进行该项检查,从而在用户尝试使用该intent之前移除这个功能。如果你知道一个特定的应用程序可以处理这个intent,那么你也可以提共一个链接来让用户下载该应用程序(查看如何在GooglePlay上连接你的产品)
用Intent来启动一个Activity
一旦你创建了你的Intent并设置好了附加信息,就可以调用startActivity()来把它发送到系统中去,如果系统发现多个程序匹配该intent,那么它会显示一个对话框供用户挑选,如图1所示。如果只有一个,系统会直接启动它。
图 1.当多个应用匹配intent会弹出的选择对话框。
startActivity(intent);
以下是一个完整的例子,它向你展示了如何创建一个可以访问地图的的intent。先确定有一个可以处理该intent的程序,再启动它。
//创建intent Uri location = Uri.parse("geo:0,0?q=1600+Amphitheatre+Parkway,+Mountain+View,+California"); Intent mapIntent = new Intent(Intent.ACTION_VIEW, location); // 确定它可以被处理 PackageManager packageManager = getPackageManager(); List<ResolveInfo> activities = packageManager.queryIntentActivities(mapIntent, 0); boolean isIntentSafe = activities.size() > 0; // 如果安全的话,启动一个activity if (isIntentSafe) { startActivity(mapIntent); }
显示一个应用程序选择框
当你调用startActivity()来传递Intent,而且有多个应用程序区配该intent时,用户可以选择一个默认选项(通过选中对话框底的一个checkbox)。这对于一个用户通常想用一个固定程序的action(比如浏览网页和拍照)来说,是很好的,但是对于一个用户更愿意去每次选择不同应用程序来执行的action而言,你需要显式的弹出一个选择对话框,并强制用户每次使用都做出选择。(用户无法选择默认程序)。
图 2. 当你用 createChooser()来强制显示匹配你intent的应用列表时,弹出的选择对话框。
为了显示选择器,调用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); // 创建并打开一个选择器 Intent chooser = Intent.createChooser(intent, title); startActivity(chooser);
以上把intent传入createChooser()方法,从而显示了一个应用程序选择对话框,并将提供的文字作为对话框标题。