アクティビティから結果を取得する

別のアクティビティを開始する場合、必ずしも一方向である必要はありません。別のアクティビティを開始して、結果を受け取ることもできます。 結果を受け取るには、(startActivity() ではなく)startActivityForResult() を呼び出します。

たとえば、自分のアプリでカメラアプリを起動し、結果として撮影した写真を受け取ることができます。または、ユーザーが連絡先を選択するケースにおいて、連絡帳アプリを起動し、結果として連絡先の詳細を受け取ることができます。

もちろん、応答するアクティビティは結果を返すように設計されていなければなりません。その場合は、別の Intent オブジェクトとして結果を送信します。 自分のアクティビティ側では、onActivityResult() コールバック内で結果を受け取ります。

注: startActivityForResult() を呼び出す際は、明示的または暗黙的インテントを使用することができます。自分のアクティビティのいずれかを開始して結果を受け取ろうとする場合は、想定通りの結果を受け取れるようにするため、明示的なインテントを使用する必要があります。

アクティビティを開始する

結果を受け取るためにアクティビティを開始する際、使用する Intent オブジェクトに関して特に記すべき内容はありませんが、startActivityForResult() メソッドに対して追加で整数の引数を渡す必要があります。

整数の引数は、リクエストを識別する「要求コード」です。結果の 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);
}

結果を受け取る

ユーザーが、その後のアクティビティを終えて復帰すると、システムは自分のアクティビティの onActivityResult() メソッドを呼び出します。このメソッドには、次の 3 つの引数が含まれます。

  • startActivityForResult() に渡した要求コード。
  • 第 2 のアクティビティによって指定された結果コード。これは、操作が成功した場合の RESULT_OK か、ユーザーがバックアウトしたり、なんらかの理由で失敗したりした場合の RESULT_CANCELED のいずれか一方です。
  • 結果のデータを運ぶ 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)
        }
    }
}

この例では、Android の連絡先または連絡帳アプリから返される結果の Intent は、ユーザーが選択した連絡先を識別するコンテンツ Uri を提供します。

正常に結果を処理するためには、結果の Intent の形式がどうなるかを理解する必要があります。これは、結果を返すアクティビティが自分のアクティビティの 1 つである場合には簡単です。 Android プラットフォームに付属のアプリでは、特定の結果データに対して役立つ、独自の API を提供しています。 たとえば、連絡帳アプリは常に選択した連絡先を識別するコンテンツ URI を含む結果を返し、カメラアプリは別に "data" エクストラで Bitmap を返します(写真を撮影するのクラスを参照)。

補足: 連絡先データを読み取る

連絡帳アプリから結果を取得する方法を示した上記のコードでは、実際に結果からデータを読み取る方法の詳細には触れていませんが、これは、コンテンツ プロバイダに関する高度な説明が必要であるためです。 ここでは興味がある方向けに、結果データをクエリして、選択された連絡先から電話番号を取得する方法について、次にコード例を示します。

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

注: Android 2.3(API レベル 9)以前では、Contacts Provider でクエリ(上記のような)を実行する場合、自分のアプリで READ_CONTACTS パーミッション(セキュリティとパーミッションを参照)を宣言する必要があります。 ただし、Android 2.3 からは連絡先または連絡帳アプリにより、結果を返すときに連絡先プロバイダから読み取るための一時的パーミッションが付与されます。 一時的なパーミッションは要求された特定の連絡先にのみ適用されるため、READ_CONTACTS パーミッションを宣言した場合を除き、インテントの Uri で指定した連絡先以外はクエリできません。