The Android Developer Challenge is back! Submit your idea before December 2.

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

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

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

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

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

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

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

整数の引数は、リクエストを識別する「要求コード」です。結果の Intent を受け取ると、アプリが正常に結果を識別し、その処理方法を決定することができるように、コールバックが同じ要求コードを提供します。

たとえば、ユーザーが連絡先を選択できるようにするアクティビティの開始方法について、次に例を示します。

Kotlin

    const val PICK_CONTACT_REQUEST = 1  // The request code
    ...
    private fun pickContact() {
        Intent(Intent.ACTION_PICK, Uri.parse("content://contacts")).also { pickContactIntent ->
            pickContactIntent.type = Phone.CONTENT_TYPE // Show user only contacts w/ phone numbers
            startActivityForResult(pickContactIntent, PICK_CONTACT_REQUEST)
        }
    }
    

Java

    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

たとえば、「連絡先を選ぶ」インテントの結果を処理する方法について、次に例を示します。

Kotlin

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent) {
        // Check which request we're responding to
        if (requestCode == PICK_CONTACT_REQUEST) {
            // Make sure the request was successful
            if (resultCode == Activity.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)
            }
        }
    }
    

Java

    @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 を返します(写真を撮影するのクラスを参照)。

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

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

Kotlin

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent) {
        // Check which request it is that we're responding to
        if (requestCode == PICK_CONTACT_REQUEST) {
            // Make sure the request was successful
            if (resultCode == Activity.RESULT_OK) {
                // We only need the NUMBER column, because there will be only one row in the result
                val projection: Array<String> = arrayOf(Phone.NUMBER)

                // Get the URI that points to the selected contact
                data.data?.also { contactUri ->
                    // 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 this 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 <code><a href="/reference/android/content/CursorLoader.html">CursorLoader</a></code> to perform the query.
                    contentResolver.query(contactUri, projection, null, null, null)?.apply {
                        moveToFirst()

                        // Retrieve the phone number from the NUMBER column
                        val column: Int = getColumnIndex(Phone.NUMBER)
                        val number: String? = getString(column)

                        // Do something with the phone number...
                    }
                }
            }
        }
    }
    

Java

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent resultIntent) {
        // 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 = resultIntent.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 <code><a href="/reference/android/content/CursorLoader.html">CursorLoader</a></code> 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 で指定した連絡先以外はクエリできません。

このページのトピックに関する追加情報については、以下のリソースもご覧ください。