与其他APP进行交互
来源:互联网 发布:vue.js深入浅出pdf 编辑:程序博客网 时间:2024/05/13 05:14
来自:https://developer.android.com/training/basics/intents/index.html
前言:我们都知道在APP中共享数据是非常重要的。比如我们经常会在微信中打开腾讯新闻APP进行新闻的查看,然后还可以选择是留在腾讯新闻APP界面还是返回微信原界面,这就涉及到APP之间进行数据传输问题。还有一个强需求场景就是:在图库中选择图片进行发送,这时候就会弹出各种供选择的APP,我一般选择发送到电脑,然后就会启动QQ中的发送到电脑的Activity界面,实现图片的发送。所以,掌握怎样在APP之间传递数据是非常重要的。
Android 应用一般具有若干个Activity。每个Activity显示一个用户界面,用户可通过该界面执行特定任务(比如,查看地图或拍照)。要将用户从一个Activity转至另一Activity,您的应用必须使用Intent
定义您的应用做某事的“意向”。当您使用诸如startActivity()
的方法将Intent
传递至系统时,系统会使用Intent
识别和启动相应的应用组件。使用意向甚至可以让您的应用开始另一个应用中包含的Activity。
Intent
可以为显式以便启动特定组件(特定的Activity
实例)或隐式以便启动处理意向操作(比如“拍摄照片”)的任何组件。
向另一个应用发送用户
Android 最重要的功能之一是应用能够基于它要执行的“操作”向另一个应用发送用户。 例如,如果您的应用有您要在地图上显示的公司地址,您无需在显示地图的应用中构建Activity。而是可以创建使用Intent
查看地址的请求。Android 系统之后启动可以在地图上显示该地址的应用。
您必须使用意向在自己应用中的Activity之间进行导航。您通常使用明确意向执行此操作,该意向定义您希望启动的组件的确切类名称。 但是,当您希望另一应用执行操作时,比如“查看地图”,您必须使用隐含意向。
构建隐含意向
隐含意向不声明要启动的组件的类名称,而是声明要执行的操作。 该操作指定您要执行的操作,比如查看、编辑、发送或 获取 某项。 意向通常还包含与操作关联的数据,比如您要查看的地址或您要发送的电子邮件消息。根据要创建的意向,数据可能是 Uri
、多种其他数据类型之一,或意向可能根本就不需要数据。
如果您的数据是 Uri
,有一个简单的Intent()
构造函数,您可用来定义操作和数据。
例如,此处显示如何使用指定电话号码的Uri
数据创建发起电话呼叫的意向:
Uri number = Uri.parse("tel:5551234");Intent callIntent = new Intent(Intent.ACTION_DIAL, number);
当您的应用通过调用startActivity()
调用此意向时,“电话”应用会发起向指定电话号码的呼叫。
这里有一些其他意向及其操作和Uri
数据对:
// Map point based on addressUri 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 levelIntent mapIntent = new Intent(Intent.ACTION_VIEW, location);查看网页:
Uri webpage = Uri.parse("http://www.android.com");Intent webIntent = new Intent(Intent.ACTION_VIEW, webpage);
其他类型的隐含意向需要提供不同数据类型(比如,字符串)的“额外”数据。 您可以使用各种putExtra()
方法添加一条或多条额外数据。
默认情况下,系统基于所包含的Uri
数据确定意向需要的相应 MIME 类型。如果您未在意向中包含Uri
,您通常应使用setType()
指定与意向关联的数据的类型。设置 MIME 类型可进一步指定哪些类型的Activity应接收意向。
此处有更多添加额外数据以指定所需操作的意向:
- 发送带附件的电子邮件:
Intent emailIntent = new Intent(Intent.ACTION_SEND);// The intent does not have a URI, so declare the "text/plain" MIME typeemailIntent.setType(HTTP.PLAIN_TEXT_TYPE);emailIntent.putExtra(Intent.EXTRA_EMAIL, new String[] {"jon@example.com"}); // recipientsemailIntent.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
- 创建日历事件:
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");
注意:只有 API 级别 14 或更高级别支持此日历事件意向。
注意:尽可能具体地定义您的 Intent
非常重要。例如,如果您想要使用 ACTION_VIEW
意向显示图像,您应指定 image/*
的 MIME 类型。 这可防止可“查看”数据的其他类型的应用(比如地图应用)被意向触发。
确认是否存在接收意向的应用
尽管 Android 平台保证某些意向可以分解为内置应用之一(比如,“电话”、“电子邮件”或“日历”应用),您应在调用意向之前始终包含确认步骤。
注意:如果您调用了意向,但设备上没有可用于处理意向的应用,您的应用将崩溃。
要确认是否存在可响应意向的可用Activity,请调用queryIntentActivities()
来获取能够处理您的Intent
的Activity列表。如果返回的List
不为空,您可以安全地使用该意向。例如:
PackageManager packageManager = getPackageManager();List activities = packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);boolean isIntentSafe = activities.size() > 0;
如果isIntentSafe
是true
,则至少有一个应用将响应该意向。 如果它是false
,则没有任何应用处理该意向。
开始具有意向的Activity
一旦您已创建您的Intent
并设置附加信息,调用startActivity()
将其发送给系统 。如果系统识别可处理意向的多个Activity,它会为用户显示对话框供其选择要使用的应用,如图 1 所示。如果只有一个Activity处理意向,系统会立即开始这个Activity。
startActivity(intent);
此处显示完整的示例:如何创建查看地图的意向,确认是否存在处理意向的应用,然后启动它:
// Build the intentUri location = Uri.parse("geo:0,0?q=1600+Amphitheatre+Parkway,+Mountain+View,+California");Intent mapIntent = new Intent(Intent.ACTION_VIEW, location);// Verify it resolvesPackageManager packageManager = getPackageManager();List<ResolveInfo> activities = packageManager.queryIntentActivities(mapIntent, 0);boolean isIntentSafe = activities.size() > 0;// Start an activity if it's safeif (isIntentSafe) { startActivity(mapIntent);}
显示应用选择器
注意,当您通过将您的Intent
传递至startActivity()
而开始Activity时,有多个应用响应意向,用户可以选择默认使用哪个应用(通过选中对话框底部的复选框;见图 1)。当执行用户通常希望每次使用相同应用进行的操作时,比如当打开网页(用户可能只使用一个网页浏览器)或拍照(用户可能习惯使用一个照相机)时,这非常有用。
但是,如果要执行的操作可由多个应用处理并且用户可能习惯于每次选择不同的应用,—比如“共享”操作,用户有多个应用分享项目—,您应明确显示选择器对话框,如图 2 所示。选择器对话框强制用户选择用于每次操作的应用(用户不能对此操作选择默认的应用)。
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 chooserIntent chooser = Intent.createChooser(intent, title);// Verify the intent will resolve to at least one activityif (intent.resolveActivity(getPackageManager()) != null) { startActivity(chooser);}
这将显示一个对话框,其中有响应传递给createChooser()
方法的意向的应用列表,并且将提供的文本用作对话框标题。
获取Activity的结果
开始并不一定是单向的另一个Activity。您还可以开始另一个Activity并 接收返回的结果。要接收结果,请调用startActivityForResult()
(而不是startActivity()
)。
例如,您的应用可启动照相机应用并接收拍摄的照片作为结果。或者,您可以启动“联系人”应用以便用户选择联系人,并且您将接收联系人详细信息作为结果。
当然,响应的Activity必须设计为返回结果。当它这样做时,它会作为另一Intent
对象发送结果。您的Activity在onActivityResult()
回调中接收它。
注意:当您调用startActivityForResult()
时,您可以使用明确或隐含意向。当开始您自己的Activity以接收结果时,您应使用明确意向确保您可收到预期结果。
开始Activity
开始针对结果的Activity时,您所使用的Intent
对象并没有什么特别之处,但您需要向startActivityForResult()
方法传递额外的整数参数。
该整数参数是识别您的请求的“请求代码”。当您收到结果Intent
时,回调提供相同的请求代码,以便您的应用可以正确识别结果并确定如何处理它。
例如,此处显示如何开始允许用户选择联系人的Activity:
static final int PICK_CONTACT_REQUEST = 1; // The request code...private void pickContact() { Intent pickContactIntent = new Intent(Intent.ACTION_PICK, Uri.parse("content://contacts")); pickContactIntent.setType(Phone.CONTENT_TYPE); // Show user only contacts w/ phone numbers startActivityForResult(pickContactIntent, PICK_CONTACT_REQUEST);}
接收结果
当用户完成后续Activity并且返回时,系统会调用您的ActivityonActivityResult()
的方法。此方法包括三个参数:
- 您向
startActivityForResult()
传递的请求代码。 - 第二个Activity指定的结果代码。如果操作成功,这是
RESULT_OK
;如果用户退出或操作出于某种原因失败,则是RESULT_CANCELED
。 - 传送结果数据的
Intent
。
本例说明您可以如何处理“选择联系人”意向的结果。
@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) { // Check which request we're responding to if (requestCode == PICK_CONTACT_REQUEST) { // Make sure the request was successful if (resultCode == RESULT_OK) { // The user picked a contact. // The Intent's data Uri identifies which contact was selected. // Do something with the contact here (bigger example below) } }}
在本例中,Android的“联系人”应用返回的结果Intent
提供识别用户所选联系人的内容Uri
。
为了成功处理结果,您必须了解结果的Intent
的格式。当返回结果的Activity是您自己的Activity之一时,这便非常容易。 Andriod平台附带的应用提供它们自己的API,您可用这些API获取特定结果数据。 例如,“联系人” 应用(在一些较旧的版本中是 Contacts 应用)始终返回带内容 URI(识别所选联系人)的结果,并且“照相机” 应用在"data"
额外项中返回Bitmap
(请参阅有关拍摄照片的课程)。
接收联系人数据
显示如何从“联系人”应用获取结果的代码不会详细说明如何实际从结果读取数据,但它需要对内容提供商进行更深入的探讨。但是,如果您很好奇,此处提供了更多的代码向您展示如何查询结果数据,从所选联系人获取电话号码:
@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) { // Check which request it is that we're responding to if (requestCode == PICK_CONTACT_REQUEST) { // Make sure the request was successful if (resultCode == RESULT_OK) { // Get the URI that points to the selected contact Uri contactUri = data.getData(); // We only need the NUMBER column, because there will be only one row in the result String[] projection = {Phone.NUMBER}; // Perform the query on the contact to get the NUMBER column // We don't need a selection or sort order (there's only one result for the given URI) // CAUTION: The query() method should be called from a separate thread to avoid blocking // your app's UI thread. (For simplicity of the sample, this code doesn't do that.) // Consider using CursorLoader to perform the query. Cursor cursor = getContentResolver() .query(contactUri, projection, null, null, null); cursor.moveToFirst(); // Retrieve the phone number from the NUMBER column int column = cursor.getColumnIndex(Phone.NUMBER); String number = cursor.getString(column); // Do something with the phone number... } }}注意:在 Android 2.3(API 级别 9)之前,在
Contacts Provider
上执行查询(如以上所示)需要您的应用声明READ_CONTACTS
权限(请参阅安全与权限)。 但是,自 Android 2.3 版本开始,“联系人”应用授予您的应用在联系人提供商向您返回结果时从联系人提供商临时读取信息的权限。该临时权限仅适用于所请求的特定联系人,因此您只能查询意向的 Uri
指定的联系人,除非您声明READ_CONTACTS
权限。允许其他应用开始您的Activity
前两课重点讲述一方面:从您的应用开始另一个应用的Activity。但如果您的应用可以执行对另一个应用可能有用的操作,您的应用应准备好响应来自其他应用的操作请求。例如,如果您构建一款可与用户的好友分享消息或照片的社交应用,您最关注的是支持ACTION_SEND
意向以便用户可以从另一应用发起“共享”操作并且启动您的应用执行该操作。
要允许其他应用开始您的Activity,您需要<intent-filter>
在相应元素的宣示说明文件中添加一个<activity>
元素。
当您的应用安装在设备上时,系统会识别您的意向过滤器并添加信息至所有已安装应用支持的意向内部目录。当应用通过隐含意向调用startActivity()
或startActivityForResult()
时,系统会找到可以响应该意向的Activity。
添加意向过滤器
为了正确定义您的Activity可处理的意向,您添加的每个意向过滤器在操作类型和Activity接受的数据方面应尽可能具体。
如果Activity具有满足以下Intent
对象条件的意向过滤器,系统可能向Activity发送给定的Intent
:
- 操作
- 对要执行的操作命名的字符串。通常是平台定义的值之一,比如
ACTION_SEND
或ACTION_VIEW
。使用
<action>
元素在您的意向过滤器中指定此值。您在此元素中指定的值必须是操作的完整字符串名称,而不是API常数(请参阅以下示例)。 - 数据
- 与意向关联的数据描述。
用
<data>
元素在您的意向过滤器中指定此内容。使用此元素中的一个或多个属性,您可以只指定MIME类型、URI前缀、URI架构或这些的组合以及其他指示所接受数据类型的项。注意:如果您无需声明关于数据的具体信息
Uri
(比如,您的Activity处理其他类型的“额外”数据而不是 URI 的时间),您应只指定android:mimeType
属性声明您的Activity处理的数据类型,比如text/plain
或image/jpeg
。 - 类别
- 提供另外一种表征处理意向的Activity的方法,通常与用户手势或Activity开始的位置有关。 系统支持多种不同的类别,但大多数都很少使用。 但是,所有隐含意向默认使用
CATEGORY_DEFAULT
进行定义。用
<category>
元素在您的意向过滤器中指定此内容。
在您的意向过滤器中,您可以通过声明嵌套在<intent-filter>
元素中的具有相应 XML 元素的各项,来声明您的Activity接受的条件。
例如,此处有一个在数据类型为文本或图像时处理ACTION_SEND
意向的意向过滤器:
<activity android:name="ShareActivity"> <intent-filter> <action android:name="android.intent.action.SEND"/> <category android:name="android.intent.category.DEFAULT"/> <data android:mimeType="text/plain"/> <data android:mimeType="image/*"/> </intent-filter></activity>
每个入站意向仅指定一项操作和一个数据类型,但可以在每个<intent-filter>
中声明<action>
、<category>
和<data>
元素的多个实例。
如果任何两对操作和数据的行为相斥,您应创建单独的意向过滤器指定与哪种数据类型配对时哪些操作可接受。
比如,假定您的Activity同时处理ACTION_SEND
和ACTION_SENDTO
意向的文本和图像。在这种情况下,您必须为两个操作定义两种不同的意向过滤器,因为ACTION_SENDTO
意向必须使用数据Uri
指定使用send
或sendto
URI架构的收件人地址。 例如:
<activity android:name="ShareActivity"> <!-- filter for sending text; accepts SENDTO action with sms URI schemes --> <intent-filter> <action android:name="android.intent.action.SENDTO"/> <category android:name="android.intent.category.DEFAULT"/> <data android:scheme="sms" /> <data android:scheme="smsto" /> </intent-filter> <!-- filter for sending text or images; accepts SEND action and text or image data --> <intent-filter> <action android:name="android.intent.action.SEND"/> <category android:name="android.intent.category.DEFAULT"/> <data android:mimeType="image/*"/> <data android:mimeType="text/plain"/> </intent-filter></activity>
注意:为了接收隐含意向,您必须在意向过滤器中包含CATEGORY_DEFAULT
类别。方法startActivity()
和startActivityForResult()
就像声明CATEGORY_DEFAULT
类别那样处理所有意向。如果您不在意向过滤器中声明它,则没有隐含意向分解为您的Activity。
如需了解有关发送和接收ACTION_SEND
执行社交共享行为的意向的详细信息,请参阅有关从其他应用接收简单数据的课程。
处理您的Activity中的意向
为了决定在您的Activity执行哪种操作,您可读取用于开始Activity的Intent
。
当您的Activity开始时,调用getIntent()
检索开始Activity的Intent
。您可以在Activity生命周期的任何时间执行此操作,但您通常应在早期回调时(比如,onCreate()
或onStart()
)执行。
例如:
@Overrideprotected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); // Get the intent that started this activity Intent intent = getIntent(); //在启动Activity的时候获得Intent,进而获得数据然后显示出来 Uri data = intent.getData(); // Figure out what to do based on the intent type if (intent.getType().indexOf("image/") != -1) { // Handle intents with image data ... } else if (intent.getType().equals("text/plain")) { // Handle intents with text ... }}
返回结果
setResult()
指定结果代码和结果Intent
。当您的操作完成且用户应返回原始Activity时,调用finish()
关闭(和销毁)您的Activity。 例如:// Create intent to deliver some kind of result dataIntent result = new Intent("com.example.RESULT_ACTION", Uri.parse("content://result_uri");setResult(Activity.RESULT_OK, result);finish();
您必须始终为结果指定结果代码。通常,它为RESULT_OK
或RESULT_CANCELED
。您之后可以根据需要为Intent
提供额外的数据。
注意:结果默认设置为 RESULT_CANCELED
。因此,如果用户在完成操作动作或设置结果之前按了返回按钮,原始Activity会收到“已取消”的结果。
Intent
,您可以调用setResult()
并且仅传递结果代码。 例如:setResult(RESULT_COLOR_RED);finish();
在这种情况下,只有几个可能的结果,因此结果代码是一个本地定义的整数(大于 0)。 当您向自己应用中的Activity返回结果时,这将非常有效,因为接收结果的Activity可引用公共常数来确定结果代码的值。
注意:无需检查您的Activity是使用startActivity()
还是startActivityForResult()
开始的。如果开始您的Activity的意向可能需要结果,只需调用setResult()
。如果原始Activity已调用startActivityForResult()
,则系统将向其传递您提供给setResult()
的结果;否则,会忽略结果。
- 与其他APP进行交互
- 实现自己与其他app交互
- 【Android Training - 05】与其他Apps进行交互 [ Lesson 1 - 启动到另外一个app ]
- 与其他Apps进行交互 [ Lesson 1 - 启动到另外一个app ]
- app内嵌H5页面与其他app的交互
- 【Android Training - 05】与其他Apps进行交互 [ Lesson 3 - 允许其他app启动你的activity ]
- 5.3 与其他Fragment交互
- 与其他应用交互 Intent
- Training--与其他APP通信
- App与其他应用交互之隐式意图的使用
- 【Android Training - 05】与其他Apps进行交互 [ Lesson 0 - 章节概览 ]
- 【Android Training - 05】与其他Apps进行交互 [ Lesson 2 - 从activity获取Result ]
- android开发实战系列(18)-- 与其他应用程序进行交互
- Java语言如何与其他语言进行交互(主要是c/c++)?以及JNI是什么
- (六)Interacting with Other Apps与其他应用进行交互
- android 与其他程序交互(一)
- PHP与其他语言交互-总结
- IOS与其他客户端音频交互
- iOS<咸鱼APP>新特性界面-视频动画
- 第十六周实践项目-阅读程序(4)
- 流媒体整理
- ACdream 1213 Matrix Multiplication 其实是一道思维题
- Mapper XML 文件
- 与其他APP进行交互
- 219. Contains Duplicate II [easy] (Python)
- CART
- 静态成员应用
- python scikit-learn计算tf-idf词语权重
- jQuery 全选
- CVPR 2016 论文集
- 第十六周项目3—阅读程序(3)
- HTML5 Web Workers