啟用另一個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