他のアプリにデータを送信する

Android では、インテントとそれに関連する追加機能を使用することにより、ユーザーがアプリで情報をすばやく簡単に共有できるようになっています。

Android では、ユーザーがアプリ間でデータを共有するのに、2 つの方法があります。

  • Android Sharesheet は主に、アプリの外部へのコンテンツの送信、別ユーザーへの直接のコンテンツの送信 、またはその両方のために設計されています。たとえば、友人との URL の共有などです。
  • Android インテント リゾルバは、明確に定義されたタスクの 次の段階にデータを渡すのに最適です。たとえば、アプリから PDF を開き、ユーザーが 好みのビューアを選択できるようにする場合などです。

インテントを作成するときは、インテントに実行させるアクションを指定します。 Android は、アクション ACTION_SEND を使用して、あるアクティビティから別のアクティビティにデータを送信します。このとき、プロセス境界を越えることもできます。データとそのタイプを指定する必要があります。システムは、データの受信が可能な互換性のあるアクティビティを自動的に見つけて、ユーザーに表示します。インテント リゾルバの場合、インテントを処理できるアクティビティが 1 つだけであれば、そのアクティビティがすぐに開始されます。

Android Sharesheet を使用する理由

Android Sharesheet を使用して、ユーザーに対するアプリ間での一貫性を持たせることを強くおすすめします。 アプリでは、共有ターゲットの独自のリストを表示すること、および独自の Sharesheet を作成することは行わないでください。

Android Sharesheet を使用すると、ユーザーは適切な人と情報を共有できます。関連するアプリの候補が表示され、すべて 1 回のタップで行うことができます。Sharesheet は、カスタム ソリューションでは利用できないターゲットを、一貫したランキングでおすすめします。 これは、Sharesheet が、システムでのみ利用可能な、アプリとユーザーのアクティビティに関する情報を考慮できるためです。

また、Android Sharesheet には、デベロッパーにとって便利な機能が多数あります。たとえば、次の操作が可能です。

Android Sharesheet を使用する

あらゆるタイプの共有で、インテントを作成し、そのアクションを Intent.ACTION_SEND に設定します。 Android Sharesheet を表示するには、 Intent.createChooser() を呼び出し、その際に作成した Intent オブジェクトを渡す必要があります。 常に Android Sharesheet を表示するバージョンのインテントが返されます。

テキスト コンテンツを送信する

最も簡単で一般的な Android Sharesheet の使用方法は、あるアクティビティから別のアクティビティにテキスト コンテンツを送信することです。たとえば、ほとんどのブラウザでは、現在表示されているページの URL をテキストとして別のアプリと共有できます。これは、メールやソーシャル ネットワーキングを通じて記事やウェブサイトを友人と共有する場合に便利です。以下はその方法の例です。

fun shareText(context: Context) {
    val sendIntent: Intent = Intent().apply {
        action = ACTION_SEND
        putExtra(Intent.EXTRA_TEXT, "This is my text to send.")
        type = "text/plain"
    }

    val shareIntent = Intent.createChooser(sendIntent, null)
    context.startActivity(shareIntent)
}

必要に応じて、メールの宛先(EXTRA_EMAILEXTRA_CCEXTRA_BCC)や件名(EXTRA_SUBJECT)などの情報を、補足情報として追加できます。

注: Gmail などの一部のメールアプリは、EXTRA_EMAILEXTRA_CC のような補足情報に String[] を想定しています。putExtra(String, String[]) を使用してインテントにこれらを追加します。

バイナリ コンテンツを送信する

ACTION_SEND アクションを使用してバイナリデータを共有します。適切な MIME タイプを設定し、次の例に示すように、補足情報 EXTRA_STREAM にデータへの URI を入れます。 これは通常、画像の共有に使用されますが、任意のバイナリ コンテンツの共有にも使用できます。

fun shareBinaryContent(context: Context) {
    val shareIntent: Intent = Intent().apply {
        action = ACTION_SEND
        // Example: content://com.google.android.apps.photos.contentprovider/...
        val imageUri: Uri =
            Uri.parse("content://com.google.android.apps.photos.contentprovider/0/1/mediakey/1")
        putExtra(Intent.EXTRA_STREAM, imageUri)
        type = "image/jpeg"
    }
    context.startActivity(Intent.createChooser(shareIntent, null))
}

受信アプリケーションには、Uri が指すデータへのアクセス権が必要です。これを行うには、次の 2 つの方法をおすすめします。

  • 自分の ContentProvider にデータを保存し、他のアプリがこのプロバイダにアクセスするための正しい権限を持つようにする。アクセス権を与えるためのおすすめの方法は、受信アプリケーションへのアクセス権だけを付与する一時的な URI ごとのパーミッションを使用することです。このような ContentProvider を作成する方法の 1 つは、FileProvider ヘルパークラスを使用することです。
  • システム MediaStore を使用する。 MediaStore は本来、動画、音声、画像の MIME タイプのためのものです。ただし、Android 3.0(API レベル 11)以降では、メディア以外のタイプも保存できます。詳細については、MediaStore.Files をご覧ください。scanFile() を使用してファイルを MediaStore に挿入でき、その後、与えられた onScanCompleted() コールバックに、共有に適した content:// スタイルの Uri が渡されます。システム MediaStore に追加されると、そのコンテンツはデバイス上のすべてのアプリからアクセスできるようになることに注意してください。

適切な MIME タイプを使用する

送信するデータに対して利用可能な最も限定的な MIME タイプを指定します。たとえば、プレーン テキストを共有する場合は text/plain を使用します。Android でデータを送信する際の一般的な MIME タイプを以下に示します。

受信者が登録する 送信者が送信する
text/*
  • text/plain
  • text/rtf
  • text/html
  • text/json
`image/*`
  • image/jpg
  • image/png
  • image/gif
video/*
  • video/mp4
  • video/3gp
サポートされているファイル拡張子 application/pdf

MIME タイプの詳細については、 IANA 公式レジストリをご覧ください。

Android Sharesheet は、指定された MIME タイプに応じてコンテンツのプレビューを表示する場合があります。一部の プレビュー機能は、特定のタイプでのみ使用できます。

複数のコンテンツを共有する

複数のコンテンツを共有するには、コンテンツを指す URI のリストを添えて、ACTION_SEND_MULTIPLE アクションを使用します。MIME タイプは、共有しようとしているコンテンツの組み合わせによって異なります。たとえば、3 つの JPEG 画像を共有する場合は、タイプ "image/jpg" を使用します。さまざまなタイプの画像を共有する場合は、"image/*" を使用して、あらゆるタイプの画像を処理するアクティビティと一致させます。さまざまなタイプを共有することもできますが、受信者にとって送信するものが不明確になるため、おすすめしません。複数のタイプを送信する必要がある場合は、"*/*" を使用します。データの解析と処理は、受信アプリケーションで行います。次の例をご覧ください。

fun shareMultiple(context: Context) {
    val imageUris: ArrayList<Uri> = arrayListOf(
        Uri.parse("content://com.google.android.apps.photos.contentprovider/0/1/mediakey/1"),
        Uri.parse("content://com.google.android.apps.photos.contentprovider/0/1/mediakey/2")
    )

    val shareIntent = Intent().apply {
        action = Intent.ACTION_SEND_MULTIPLE
        putParcelableArrayListExtra(Intent.EXTRA_STREAM, imageUris)
        type = "image/*"
    }
    context.startActivity(Intent.createChooser(shareIntent, null))
}

指定した Uri オブジェクトが、受信アプリケーションがアクセスできるデータを指すようにしてください。

テキスト プレビューにリッチ コンテンツを追加する

Android 10(API レベル 29)以降、Android Sharesheet では共有されているテキストのプレビューが表示されます。場合によっては、共有されているテキストが理解しにくいことがあります。https://www.google.com/search?ei=2rRVXcLkJajM0PEPoLy7oA4 のような複雑な URL を共有することを考えてみましょう。リッチなプレビューを表示することで、ユーザーは共有される内容を安心して確認できます。

テキストをプレビューする場合は、タイトルまたはサムネイル画像、あるいはその両方を設定できます。Intent.createChooser() を呼び出す前に Intent.EXTRA_TITLE に説明を追加し、ClipData を使用して関連するサムネイルを追加します。

注: 画像コンテンツの URI は、 FileProvider から提供されます(通常は <cache-path> に構成されています)。 詳細については、ファイルを共有するをご覧ください。必ず、サムネイルとして使用する画像を読み取るための適切な権限を Sharesheet に付与してください。詳細については、Intent.FLAG_GRANT_READ_URI_PERMISSION をご覧ください。

次の例をご覧ください。

fun richContentToTextPreviewShares(context: Context) {
    val share = Intent.createChooser(
        Intent().apply {
            action = ACTION_SEND
            putExtra(Intent.EXTRA_TEXT, "https://developer.android.com/training/sharing/")

            // (Optional) Here you're setting the title of the content
            putExtra(Intent.EXTRA_TITLE, "Introducing content previews")

            // (Optional) Here you're passing a content URI to an image to be displayed
            data =
                Uri.parse("content://com.google.android.apps.photos.contentprovider/0/1/mediakey/A123456789")
            flags = Intent.FLAG_GRANT_READ_URI_PERMISSION
        },
        null
    )
    context.startActivity(share)
}

プレビューは次のようになります。

Sharesheet にカスタム アクションを追加する

Android Sharesheet のカスタム アクションのスクリーンショット。

Android 14(API レベル 34)以降では、アプリで Android Sharesheet にカスタム アクションを追加できます。 カスタム アクションは、Android Sharesheet の上部に小さなアクション アイコンとして表示されます。アプリは、アイコンがクリックされたときに呼び出されるアクションとして任意の Intent を指定できます。

Android Sharesheet にカスタム アクションを追加するには、まず ChooserActionChooserAction.Builder使用して作成します。 アイコンがクリックされたときに呼び出されるアクションとして PendingIntent を指定できます。すべてのカスタム アクションを含む配列を作成し、共有 IntentEXTRA_CHOOSER_CUSTOM_ACTIONS として指定します。

fun sharesheetCustomActions(context: Context, previewText: String) {
    val sendIntent = Intent(ACTION_SEND)
        .setType("text/plain")
        .putExtra(Intent.EXTRA_TEXT, previewText)
    val shareIntent = Intent.createChooser(sendIntent, null)
    val customActions = arrayOf(
        ChooserAction.Builder(
            Icon.createWithResource(context, R.drawable.ic_logo),
            "Custom",
            PendingIntent.getBroadcast(
                context,
                1,
                Intent(Intent.ACTION_VIEW),
                PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_CANCEL_CURRENT
            )
        ).build()
    )
    shareIntent.putExtra(Intent.EXTRA_CHOOSER_CUSTOM_ACTIONS, customActions)
    context.startActivity(shareIntent)
}

カスタム ターゲットを追加する

Android Sharesheet では、ChooserTarget オブジェクトを最大 2 つ指定できます。これらは、ChooserTargetServices から読み込まれた共有ショートカットと選択ツール ターゲットの前に表示されます。また、アプリの候補の前に一覧表示されるアクティビティを指すインテントを最大 2 つ指定することもできます。

Intent.createChooser() を呼び出した後 に、共有インテントに Intent.EXTRA_CHOOSER_TARGETSIntent.EXTRA_INITIAL_INTENTS を追加します。

val share = Intent.createChooser(shareIntent, null).apply {
    putExtra(
        Intent.EXTRA_CHOOSER_TARGETS,
        arrayOf(chooserTargetJessica, chooserTargetSpyros)
    )
    putExtra(
        Intent.EXTRA_INITIAL_INTENTS,
        arrayOf(intentTargetNearbyShare, intentTargetMaps)
    )
}

この機能の使用には注意が必要です。カスタムの IntentChooserTarget を追加するたびに、システムが提案する候補の数が少なくなります。通常、カスタム ターゲットを追加することはおすすめしません。Intent.EXTRA_INITIAL_INTENTS を追加する一般的で適切な例は、共有コンテンツに対してユーザーが実行できる追加のアクションを提供する場合です。たとえば、ユーザーが画像を共有し、Intent.EXTRA_INITIAL_INTENTS を使用して、画像の代わりにリンクを送信できるようにします。Intent.EXTRA_CHOOSER_TARGETS を追加する一般的で適切な例は、アプリが提供する関連するユーザーやデバイスを表示する場合です。

特定コンポーネントのターゲットの除外

Intent.EXTRA_EXCLUDE_COMPONENTS を指定して特定のターゲットを除外できます。これは、制御可能なターゲットの削除にのみ使用してください。一般的なユースケースは、ユーザーのインテントがアプリの外部で共有される可能性が高いため、ユーザーがアプリ内から共有するときに、アプリの共有ターゲットを非表示にする場合です。

Intent.createChooser() を呼び出した後、インテントに Intent.EXTRA_EXCLUDE_COMPONENTS を追加します。

fun excludeSpecificTargets(context: Context) {
    val share = Intent.createChooser(Intent(ACTION_SEND), null).apply {
        // Only use for components you have control over
        val excludedComponentNames =
            arrayOf(ComponentName("com.example.android", "ExampleClass"))
        putExtra(Intent.EXTRA_EXCLUDE_COMPONENTS, excludedComponentNames)
    }
    context.startActivity(share)
}

共有に関する情報を取得する

ユーザーがいつ共有しているか、どのターゲットを選択しているかを知ることは、役に立つ場合があります。Android Sharesheet では、ユーザーが IntentSender を使用して選択したターゲットの ComponentName を提供することで、この情報を取得できます。

まず、BroadcastReceiverPendingIntent を作成し、その IntentSenderIntent.createChooser() に指定します。

fun infoAboutSharing(context: Context, requestCode: Int) {
    var share = Intent(ACTION_SEND)
    // ...
    val pi = PendingIntent.getBroadcast(
        context, requestCode,
        Intent(context, ShareBroadcastReceiver::class.java),
        PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
    )
    share = Intent.createChooser(share, null, pi.intentSender)
    context.startActivity(share)
}

MyBroadcastReceiver でコールバックを受け取り、Intent.EXTRA_CHOOSER_RESULT を確認します。

override fun onReceive(context: Context?, intent: Intent) {
    val TAG = ShareBroadcastReceiver::class.simpleName
    val chooserResult: ChooserResult? = IntentCompat.getParcelableExtra(
        intent,
        Intent.EXTRA_CHOOSER_RESULT,
        ChooserResult::class.java,
    )
    chooserResult?.let {
        Log.i(TAG,
            "Share callback: isShortcut: ${it.isShortcut}, type: ${typeToString(it.type)}, componentName: ${it.selectedComponent}",
        )
    } ?: Log.i(TAG, "chooserResult is null")
}
詳細については、プラットフォーム共有のサンプルをご覧ください。

Sharesheet  にカスタム アクションを追加する

Android 14(API レベル 34)以降では、アプリで Android Sharesheet にカスタム アクションを追加できます。 を使用して ChooserAction を作成します。 ChooserAction.Builderアイコンがクリックされたときに呼び出されるアクションとして PendingIntent を指定できます。すべてのカスタム アクションを含む配列を作成し、共有 IntentEXTRA_CHOOSER_CUSTOM_ACTIONS として指定します。

fun customActions(context: Context, text: String) {
    val sendIntent = Intent(ACTION_SEND)
        .setType("text/plain")
        .putExtra(Intent.EXTRA_TEXT, text)
    val shareIntent = Intent.createChooser(sendIntent, null)
    val customActions = arrayOf(
        ChooserAction.Builder(
            Icon.createWithResource(context, R.drawable.ic_logo),
            "Custom",
            PendingIntent.getBroadcast(
                context,
                1,
                Intent(Intent.ACTION_VIEW),
                PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_CANCEL_CURRENT
            )
        ).build()
    )
    shareIntent.putExtra(Intent.EXTRA_CHOOSER_CUSTOM_ACTIONS, customActions)
    context.startActivity(shareIntent)
}

Android インテント リゾルバを使用する

ACTION_SEND インテント リゾルバのスクリーンショット。

Android インテント リゾルバが最もよく使われるのは、明確に定義されたタスクフローの一部として別のアプリにデータを渡す場合です。

Android インテント リゾルバを使用するには、Android Sharesheet を呼び出す場合と同じように、インテントを作成して補足情報を追加します。ただし、呼び出さないでください Intent.createChooser()

ACTION_SEND および MIME タイプが一致するフィルタを持つアプリケーションが複数インストールされている場合、システムは、インテント リゾルバと呼ばれる曖昧さ回避のダイアログを表示して、ユーザーが共有先を選択できるようにします。一致するアプリケーションが 1 つであれば、そのアプリケーションが実行されます。

Android インテント リゾルバを使用してテキストを送信する例を以下に示します。

fun intentResolver(context: Context) {
    val sendIntent: Intent = Intent().apply {
        action = ACTION_SEND
        putExtra(Intent.EXTRA_TEXT, "This is my text to send.")
        type = "text/plain"
    }
    context.startActivity(sendIntent)
}

詳細

データの送信に関する詳細については、 インテントとインテント フィルタをご覧ください。