🗂

【Android】Android 11 以降で Intent を使ってメールアプリを起動する

2022/07/14に公開

Android 11 以降は、AndroidManifest.xml<queries>を定義して パッケージの公開設定の必要性を宣言する 必要があります。

https://developer.android.com/training/package-visibility/declaring?hl=ja

公開設定の必要性の宣言について

  • Android 11 以降をターゲットとするアプリでは、自動的に公開されるアプリ以外と連携が必要なときは、アプリのAndroidManifest.xml<queries>要素を追加する。
  • <queries>内の要素に指定するものは「パッケージ」「インテント」「プロバイダ」がある。
  • Android 10(API レベル 29)以前をターゲットとするアプリでは、すべてのアプリが自動的に公開されるので、この対応は不要。

公開されているアプリの一覧を取得する

以下のコマンドを実行して、forceQueryableの一覧を探します。

forceQueryable以下で表示されているものが、自動で公開されているアプリのパッケージ一覧です。

$ adb shell dumpsys package queries

実装例 : メールアプリを起動する

MainActivity.kt

private fun launchMailer() {

        val intent = Intent(Intent.ACTION_SENDTO).also {
            /**
             * mailto:
             * インテントを確実にメールアプリのみで処理するようにしたい
             * (その他のテキスト メッセージングやソーシャルのアプリで処理されたくない)場合に使用する
             */
            it.data = Uri.parse("mailto:")
            // 「宛先」の受信者のすべてのメールアドレスを格納した文字列配列
            it.putExtra(Intent.EXTRA_EMAIL, arrayOf("sample@gmail.com"))
            // 電子メールの件名となる文字列
            it.putExtra(Intent.EXTRA_SUBJECT, "Subject")
            // 電子メールの本文となる文字列
            it.putExtra(Intent.EXTRA_TEXT, "Message")
        }
        /**
         * 起動できるメールアプリがないときに null が返ってくる。
	 * そのまま startActivity をコールするとクラッシュしてしまうので、
	 * 事前にメールアプリが存在するか判定している
         */
        if (intent.resolveActivity(packageManager) != null) {
            startActivity(intent)
        }
    }

AndroidManifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <application ...>
        <activity
            android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

    <!-- Add -->
    <queries>
        <intent>
            <action android:name="android.intent.action.SENDTO" />
            <data android:scheme="mailto" />
        </intent>
    </queries>

</manifest>

intent.resolveActivityについては、一般的なインテント に注意書きとして、以下のように記載されています。

注意:端末に暗黙的インテントを受け取ることができるアプリがない場合、startActivity() を呼び出すとアプリがクラッシュします。まず、インテントを受け取るアプリの存在を確認するために、Intent オブジェクトの resolveActivity() を呼び出してください。結果が null 以外の場合は、インテントを処理できるアプリが少なくとも 1 つあるということなので、startActivity() を安全に呼び出すことができます。結果が null の場合は、そのインテントは使用しないでください。可能であればそのインテントを呼び出す機能を無効にしてください。

Discussion