アプリ開発備忘録

PlayStationMobile、Android、UWPの開発備忘録。

Android14におけるenableOnBackInvokedCallbackの不具合と回避策(In-App Messagingがジェスチャーで消せない)

予測型「戻る」ジェスチャーをManifestで有効化するenableOnBackInvokedCallbackについて。Android14でのみ挙動が違う不具合と思われるものがあります。
https://developer.android.com/guide/navigation/custom-back/predictive-back-gesture?hl=ja

問題

このようにapplicationにandroid:enableOnBackInvokedCallback="true"と書いて有効化します。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">

    <application
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:enableOnBackInvokedCallback="true"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.BackInvokeCallbackTest">

        <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>

</manifest>

以下のようにWindowManagerでViewを追加し、KEYCODE_BACKが来たらwindowを消し、activityの方で追加したonBackInvokedDispatcherが呼ばれる想定です。

package com.example.backinvokecallbacktest

import android.graphics.Color
import android.os.Bundle
import android.util.Log
import android.view.KeyEvent
import android.view.View
import android.view.WindowManager
import android.window.OnBackInvokedDispatcher
import androidx.activity.ComponentActivity

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        windowManager.addView(
            object : View(this) {
                init {
                    setBackgroundColor(Color.RED)
                }

                override fun dispatchKeyEvent(event: KeyEvent?): Boolean {
                    when(event?.keyCode) {
                        KeyEvent.KEYCODE_BACK -> {
                            windowManager.removeView(this)
                        }
                    }
                    return super.dispatchKeyEvent(event)
                }
            },
            WindowManager.LayoutParams().apply {
                width = 100
                height = 100
            }
        )

        onBackInvokedDispatcher.registerOnBackInvokedCallback(OnBackInvokedDispatcher.PRIORITY_DEFAULT) { // PRIORITY_OVERLAYでも同じ
            Log.d(this::class.simpleName, "onBackInvoked")
        }
    }
}

しかし、Android14でだけ、キーイベントが流れてきませんでした。

Firebase In-App Messagingが、予測型バックを使用しているとジェスチャーで消せない事からこの問題が発覚しました。
関連Issue: https://github.com/firebase/firebase-android-sdk/issues/6642

enableOnBackInvokedCallback=true としてしまうと、windowManager経由で追加したViewがジェスチャーで消せなくなってしまうという問題です。

解決策

ApplicationのenableOnBackInvokedCallbackを消し、Activity全てにenableOnBackInvokedCallback=trueを設定する事で回避が可能です。
ApplicationのenableOnBackInvokedCallbackをfalseに設定する影響が未知数な為、何も設定しないのが良いかと思います。Android14,15ではデフォルトではfalseとなっていて、Android16からデフォルトがtrueになる為、影響が最小限になります。