启用另一个activity不一定是单向的。也可以启用另一个activity并且获得返回值。要获得返回值的话,调用startActivityForResult()(而不是startActivity())。
比如,app可以打开相机然后接收一张照片作为返回值。或者,为了让用户选择一个联系人可以让用户启动联系人相关app,然后收到联系人详情作为结果。
当然,这个响应的activity必须设计为有返回值的。当返回的时候,它用Intent对象作为返回值。activity会在onActivityResult()回调方法中收到。
注意:用明确的和模糊的intent都可以使用startActivityForResult()。当使用自己的activity来接收结果时,需要使用一个明确的intent来保证你可以收到结果。
开始一个Activity
当启动一个activity来获取返回值时Intent对象没有什么特别的,但是需要另外传递一个integer参数给startActivityForResult()方法。
这个integer参数是一个"request code",用来标识请求。当收到Intent结果,回调时会返回同样的"request code"这样app可以很好的识别结果和决定如何处理它。
例如,这里有一个如何启动activity来让用户选择一个联系人:
1 static final int PICK_CONTACT_REQUEST = 1; // The request code
2 ...
3 private void pickContact() {
4 Intent pickContactIntent = new Intent(Intent.ACTION_PICK, Uri.parse("content://contacts"));
5 pickContactIntent.setType(Phone.CONTENT_TYPE); // Show user only contacts w/ phone numbers
6 startActivityForResult(pickContactIntent, PICK_CONTACT_REQUEST);
7 }
接收返回值
当用户完成了后来activity中的操作并且返回时,系统会调用activity的onActivityResult()方法。这个方法包含三个参数:
- 在startActivityForResult()中传递的请求码。
- 第二个activity的返回码。它会时RESULT_OK如果操作成功,或者RESULT_CANCELED如果用户退回去或者操作由于某些原因失败。
- 一个带有结果数据的Intent
例如,这里是如何处理选择联系人的返回值:
1 @Override
2 protected void onActivityResult(int requestCode, int resultCode, Intent data) {
3 // 检查返回的结果
4 if (requestCode == PICK_CONTACT_REQUEST) {
5 // 确保请求成功了
6 if (resultCode == RESULT_OK) {
7 // 用户选择了一个联系人
8 // Intent的数据Uri标识了联系人被选中了
9
10 // 用这个联系人做点什么(下面会有示例)
11 }
12 }
13 }
这个例子中,由Android联系人或其他联系人相关app返回的Intent提供了一个Uri可以标识用户选择了哪个联系人。
为了成功的处理结果,必须要了解返回的Intent的格式是什么样的。当返回值的activity是自己的activity时处理起来很简单。Android平台自带的app,对于这些结果可以根据他们提供的API来处理。例如,联系人app总是返回一个content URI来标识选中的联系人,相机app在附加数据中返回一个Bitmap(可以在Capturing Photos中查看)。
附加:读取联系人数据
上面的代码展示了如何从联系人app中获得结果但是没有详细的展示如何读结果数据,因为需要更多的关于content providers的探讨。然而,如果你好奇的话,这里由一些代码展示了如果从选择的联系人中获得电话号码:
1 @Override
2 protected void onActivityResult(int requestCode, int resultCode, Intent data) {
3 // 查看返回的是哪个请求
4 if (requestCode == PICK_CONTACT_REQUEST) {
5 // 确保请求成功了
6 if (resultCode == RESULT_OK) {
7 // 获得指向选中联系人的URI
8 Uri contactUri = data.getData();
9 // 我们只需要NUMBER列,因为结果中只有一行
10 String[] projection = {Phone.NUMBER};
11
12 // 在联系人上执行查询来获得NUMBER列
13 // 我们不需要选择排序方法(只有一个结果)
14 // 注意:query()应该在另外一个线程调用,为了避免阻塞app的UI线程。(为了简单,这里就不那么做了)
15 // 用CursorLoader来执行查询
16 Cursor cursor = getContentResolver()
17 .query(contactUri, projection, null, null, null);
18 cursor.moveToFirst();
19
20 //从NUMBER列获得电话号码
21 int column = cursor.getColumnIndex(Phone.NUMBER);
22 String number = cursor.getString(column);
23
24 //用电话号码所点什么
25 }
26 }
27 }
注意:在Android2.3(API等级9)之前,使用Contracts Provider(就像上面展示的)来查询需要app声明READ_CONTACTS权限(查看Security and Permissions)。然后,从Android2.3开始,联系人app允许app用临时权限来用Contacts Provider获得结果。这个临时权限只适用于明确的联系人请求,所以除非是由intent的Uri明确指定的联系人,其他的都不能查询,或者可以声明READ_CONTACTS权限。
上一篇:Android - 和其他APP交互 - 把用户带到其他APP
下一篇:Android - 和其他APP交互 - 让其他APP启动你的Activity
学习