一个Android App 通常会有多个Activity。每个Activity的界面都扮演者用户入口的角色,允许用户执行一些特定的任务(例如:查看地图或者拍照等)。为了让用户能够从一个Activity跳转到另一个Activity,必须使用Intent来定义自己的意图。

使用Intent实现与其他App执行的交互,比如:启动另一个App,从其他App接收数据,以及使我们自己的App响应其他App发出的Intent。

主题一:将用户传送到另外一个App

比如:在一个应用中,用户想要接收“本地”应用的数据,并显示出指定数据的地理位置信息;这个时候并不适合在本地的Activity中创建地图数据,而是使用Intent跳转到其他的应用,比如:Map 应用。

Intent有两种:显式的和隐式的

相对于显式Intent,隐式Intent能够携带有指定的意图信息,并跳转到其他App中。how to create an implicit intent for a particular action, and how to use it to start an activity that performs the action in another app.

如何创建隐式Intent?

显然,如果想要使用到显式Intent,必须要知道对应的类名、Action名等信息。Implicit intents do not declare the class name of the component to start, but instead declare an action to perform.

包含有URI的Intent实例:If your data is a Uri, there's a simple Intent() constructor you can use define the action and data.

举一个栗子:

打电话:

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

显示地图:

// 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 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

创建日历事件:

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");

Note: It'simportant that you define your Intent to be as specific as possible.

验证是否有App接收这个Intent

Although the Android platform guarantees that certain intents will resolve to one of the built-in apps (such as thePhone, Email, or Calendar app), you should always include a verification step before invoking an intent. 在发送一个Intent之前,有必要验证是否有App能够接收该Intent。

必须注意的是:Caution: If you invoke an intent and there is no app available on the device that can handle the intent, your app will crash.

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

如果返回的activities集合长度不为0,即不为空时,表示存在Activity能够响应该Intent。

如何启动另一个Activity?

startActivity(intent);

从一个Activity跳转到另一个Activity的方式,系统会分析能够响应该Intent的App。

并以Dialog的形式显示出来。

下述示例程序能够启动地图浏览功能:

// 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,如何选择?若每次的选择都不确定,这种情况如何处理?

显示选择界面,供用户决策

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);
}

主题二:获取Activity的返回数据

Starting another activity doesn't have to be one-way. You can also start another activity and receive a result back. To receive a result, call startActivityForResult() (instead of startActivity()).

具体实现:When it does, it sends the result as another Intent object. Your activity receives it in the onActivityResult() callback. 返回Result时,仍然使用Intent。

Note: You can use explicit or implicit intents when you call startActivityForResult(). When starting one of your own activities to receive a result, you should use an explicit intent to ensure that you receive the expected result. 如果启动自己App的Activity并期望返回结果时,建议使用显式Intent,以确保接收期望的结果。

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);
}

The request code 意味:请求码,用于标识当次请求。When you receive the result Intent, the callback provides the same request code so that your app can properly identify the result and determine how to handle it. 结果返回时,Intent会附带有相同的请求码,以确保请求的正确性。

其中在另一个Activity中会对返回的Intent附加数据:result code

A result code specified by the second activity. This is either RESULT_OK if the operation was successful or RESULT_CANCELED if the user backed out or the operation failed for some reason.

result code 用于标识对Intent处理的结果:

@Override
protected 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)
}
}
}

举个栗子:如何读取联系人信息

@Override
protected 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...
}
}
}

主题三:允许其他App启动自己的Activity

即:让自己的App响应其他App的Intent。

To allow other apps to start your activity, you need to add an <intent-filter> element in your manifest file for the corresponding <activity> element.

当app被安装到设备上时,系统可以识别intent filter并把这些信息记录下来。当其他app使用implicit intent执行 startActivity() 或者 startActivityForResult()时,系统会自动查找出那些可以响应该intent的Activity。

如何增加<intent-filter>?

为了尽可能确切的定义activity能够handle的intent,每一个intent filter都应该尽可能详尽的定义好action与data。

如果一个Activity的<intent-filter>具备以下特征,那么就是比较完善的:

Action:A string naming the action to perform. Usually one of the platform-defined values such as ACTION_SEND or ACTION_VIEW. Specify this in your intent filter with the <action> element. The value you specify in this element must be the full string name for the action, instead of the API constant (see the examples below).

Data:A description of the data associated with the intent. Specify this in your intent filter with the <data> element. Using one or more attributes in this element, you can specify just the MIME type, just a URI prefix, just a URI scheme, or a combination of these and others that indicate the data type accepted.

Category:Provides an additional way to characterize the activity handling the intent, usually related to the user gesture or location from which it's started. There are several different categories supported by the system, but most are rarely used. However, all implicit intents are defined with CATEGORY_DEFAULT by default. Specify this in your intent filter with the <category> element.

举个栗子:

<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只会包含一个action与data类型,但handle这个intent的activity的 <intent-filter>可以声明多个<action>, <category>与<data> 。

如果任何的两对action与data是互相矛盾的,就应该创建不同的intent filter来指定特定的action与type。

<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>

需要注意是:Note: In order to receive implicit intents, you must include the CATEGORY_DEFAULT category in the intent filter. The methods startActivity() and startActivityForResult() treat all intents as if they declared the CATEGORY_DEFAULT category. If you do not declare it in your intent filter, no implicit intents will resolve to your activity. 为了接受implicit intents, 必须在我们的intent filter中包含 CATEGORY_DEFAULT 的category。startActivity()和startActivityForResult()方法将所有intent视为声明了CATEGORY_DEFAULT category。如果没有在的intent filter中声明CATEGORY_DEFAULT,activity将无法对implicit intent做出响应。

响应Intent,那如何获取该Intent呢?

最好是在onCreate()和onStart()中获取该Intent。

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// Get the intent that started this activity
Intent intent = getIntent();
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 ...
}
}

如何返回结果?

// Create intent to deliver some kind of result data
Intent result = new Intent("com.example.RESULT_ACTION", Uri.parse("content://result_uri");
setResult(Activity.RESULT_OK, result);
finish();

在返回结果的Activity端,需要设置result code。Generally, it's either RESULT_OK or RESULT_CANCELED.

Note: The result is set to RESULT_CANCELED by default. So, if the user presses the Back button before completing the action and before you set the result, the original activity receives the "canceled" result.

(Android数据传递)应用之间的交互的更多相关文章

  1. Android数据传递,使用广播BroadcastReceiver;

    Android数据传递有很多种,Intent意图传递或使用Bundle去传递,接口监听回调传递数据,也可以把数据保存起来,使用的时候去读取等等等...,"当你知道足够多的数据传递的方式之后, ...

  2. Android 数据传递(一) Activity之间的数据传递

    bundle Google Bundle类说明 Bundle类是一个key-value对.Activity之间的数据通信可以通过bundle类来实现数据的存储.即将数据放入bundle里面,将Bund ...

  3. (Android数据传递)Intent消息传递机制 “Intent”“数据传递”

    Intent类的继承关系:   需要注意的是,该类实现了Parcelable(用于数据传递)和Cloneable接口. Intent是一种(系统级别的)消息传递机制,可以在应用程序内使用,也可以在应用 ...

  4. Android数据传递

    直接用一个例子说明,简单粗暴: 数据传递会用到此界面标注id值的三个控件 Activity_zc.xm l 当点击“注册”按钮,会显示注册信息 Activity._show.xml 下面展示zcAct ...

  5. (Android数据传递)Service和Activity之间-- 借助BroadcastReceiver--的数据传递

    实现逻辑如下: 左侧为Activity中的执行逻辑,右侧为Service中的执行逻辑: /** * <功能描述> Service和Activity之间的数据交互:具体表现为: 1. 从Se ...

  6. Android 数据传递(二)Activity与fragment之间的通信

    在网上找到了一篇总结的非常好的文章,我这里就贴出他的博文地址.自己就不再写这个方面的总结了. Activity与Fragment通信(99%)完美解决方案

  7. Android数据传递的五种方法汇总

    Android开发中,在不同模块(如Activity)间经常会有各种各样的数据需要相互传递,我把常用的几种 方法都收集到了一起.它们各有利弊,有各自的应用场景. 我现在把它们集中到一个例子中展示,在例 ...

  8. iOS边练边学--通讯录练习之Segue使用,控制器的数据传递

    一.什么是segue Storyboard上每一根用来界面跳转的线,都是一个UIStoryboardSegue对象(简称Segue) 二.Segue的属性 每一个segue对象,都有三个属性 < ...

  9. android第一行代码-3.activity之间的调用跟数据传递

    前面两节所有应用都是同一个activity中的,是时候讲activity之间交互的操作了,此后会涉及到intent这个概念,这也算一个新的里程碑开始. 主要内容包括intent的使用,以及activi ...

随机推荐

  1. vue-cli watch简单用法

    创建一个vue单文件 <template> <div id="test"> <h4 @click="changeMsg()" id ...

  2. 开启或停止website

    1.添加:Microsoft.Web.Administration 2.代码: static void Main(string[] args) { var server = new ServerMan ...

  3. IOU和非极大值抑制

    如何判断对象检测算法运作良好呢? 一.交并比(Intersection over union,IoU) 是产生的候选框(candidate bound)与原标记框(ground truth bound ...

  4. WPF编程之找不到资源mainWindow.xaml

    原文: WPF编程之找不到资源“window1.xaml”之谜 因为将启动窗口移动到了一个新建的文件夹中,启动调试时报找不到资源mainWindow.xaml,原来是App.xaml里面设置的启动窗口 ...

  5. Git基础(四) 查看已暂存和未暂存的修改

    比较工作目录中当前文件和暂存区域快照之间的差异(也就是修改之后还没有暂存起来的变化内容) git diff 比较已暂存的将要添加到下次提交里的内容 git diff --cached Git 1.6. ...

  6. Appearance-and-Relation Networks for Video Classification论文笔记 (ARTnet)

    ARTnet: caffe实现:代码 1 Motivation:How to model appearance and relation (motion) 主要工作是在3D卷积的基础上,提升了acti ...

  7. Oracle Instant Client(即时客户端) 安装与配置

    一.下载 下载地址:http://www.oracle.com/technetwork/database/features/instant-client/index-097480.html 这是Ora ...

  8. 【Android】Android 多个APK数据共享

    Android给每个APK进程分配一个单独的用户空间,其manifest中的userid就是对应一个Linux用户(Android 系统是基于Linux)的.所以不同APK(用户)间互相访问数据默认是 ...

  9. md5爆破工具

    http://www.myhack58.com/Article/html/3/8/2015/65021.htm http://xlixli.net/?p=410 http://blog.csdn.ne ...

  10. Centos 6.5 本地局域网基于HTTP搭建YUM

    服务端配置 init 3 文本  init5 图形  init 0 关机 init 1 重启 ls 查看  mkdir创建文件 关闭防火墙service iptables stop chkconfig ...