(Android数据传递)应用之间的交互
一个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数据传递)应用之间的交互的更多相关文章
- Android数据传递,使用广播BroadcastReceiver;
Android数据传递有很多种,Intent意图传递或使用Bundle去传递,接口监听回调传递数据,也可以把数据保存起来,使用的时候去读取等等等...,"当你知道足够多的数据传递的方式之后, ...
- Android 数据传递(一) Activity之间的数据传递
bundle Google Bundle类说明 Bundle类是一个key-value对.Activity之间的数据通信可以通过bundle类来实现数据的存储.即将数据放入bundle里面,将Bund ...
- (Android数据传递)Intent消息传递机制 “Intent”“数据传递”
Intent类的继承关系: 需要注意的是,该类实现了Parcelable(用于数据传递)和Cloneable接口. Intent是一种(系统级别的)消息传递机制,可以在应用程序内使用,也可以在应用 ...
- Android数据传递
直接用一个例子说明,简单粗暴: 数据传递会用到此界面标注id值的三个控件 Activity_zc.xm l 当点击“注册”按钮,会显示注册信息 Activity._show.xml 下面展示zcAct ...
- (Android数据传递)Service和Activity之间-- 借助BroadcastReceiver--的数据传递
实现逻辑如下: 左侧为Activity中的执行逻辑,右侧为Service中的执行逻辑: /** * <功能描述> Service和Activity之间的数据交互:具体表现为: 1. 从Se ...
- Android 数据传递(二)Activity与fragment之间的通信
在网上找到了一篇总结的非常好的文章,我这里就贴出他的博文地址.自己就不再写这个方面的总结了. Activity与Fragment通信(99%)完美解决方案
- Android数据传递的五种方法汇总
Android开发中,在不同模块(如Activity)间经常会有各种各样的数据需要相互传递,我把常用的几种 方法都收集到了一起.它们各有利弊,有各自的应用场景. 我现在把它们集中到一个例子中展示,在例 ...
- iOS边练边学--通讯录练习之Segue使用,控制器的数据传递
一.什么是segue Storyboard上每一根用来界面跳转的线,都是一个UIStoryboardSegue对象(简称Segue) 二.Segue的属性 每一个segue对象,都有三个属性 < ...
- android第一行代码-3.activity之间的调用跟数据传递
前面两节所有应用都是同一个activity中的,是时候讲activity之间交互的操作了,此后会涉及到intent这个概念,这也算一个新的里程碑开始. 主要内容包括intent的使用,以及activi ...
随机推荐
- Android相关 博客收藏
#1 Android 网络编程 参考博客 :http://blog.csdn.net/kieven2008/article/details/8210737 #2 Could not find com. ...
- phoenix表操作
phoenix表操作 进入命令行,这是sqlline.py 配置到path环境变量的情况下 sqlline.py localhost如果要退出命令行:!q 或者 !quit 3.4.1 创建表 ...
- STL容器之优先队列
STL容器之优先队列 优先级队列,以前刷题的时候用的比较熟,现在竟然我只能记得它的关键字是priority_queue(太伤了).在一些定义了权重的地方这个数据结构是很有用的. 先回顾队列的定义:队列 ...
- TodoMVC:帮助你选择一个MV*框架
开发者现在有很多的MV*框架选择来组织开发web应用程序.Backbone. Ember.AngularJS.Spine… 新的稳定解决方案列表持续增长,但你如何决定在海量的框架中选择哪个使用? 为了 ...
- TFS 生成任务报错:目录不是空的
转到代理目录下,将生成文件夹清空,重新启动生成任务即可
- 在WPF中获取DATAGRIDTEMPLATECOLUMN模板定义的内容控件(转载)
原文:http://www.cnblogs.com/eric_ibm/p/3772516.html xaml格式描述: <DataGrid Name="dataGrid" G ...
- 关于K8S证书生成方面的脚本草稿
周日在家里计划的. 俺不加班,但在家学习的时间一样没少! 还没弄完,只粗粗弄了etcd证书. #! /usr/bin/env bash set -e set -u set -x THIS_HOST=$ ...
- javascript 列表定时滚动效果
HTML结构: <div style="width:200px;height:100px;overflow:hidden;border:1px solid #ddd;margin:20 ...
- sparkStreaming消费kafka-1.0.1方式:direct方式(存储offset到zookeeper)
版本声明: kafka:1.0.1 spark:2.1.0 注意:在使用过程中可能会出现servlet版本不兼容的问题,因此在导入maven的pom文件的时候,需要做适当的排除操作 <?xml ...
- java分页实现
虽然现在有很多好用的框架,对分页进行支持,很简单的就把分页的效果做出来,但是如果自己手写是一个怎样的流程的?今天就来说说它,手动实现分页效果. 一.分页的思路 首先我们得知道写分页代码时的思路,保持思 ...