ML-Kit文档扫描器打开时无法获取应用生命周期回调问题
ML-Kit文档扫描器后台切换时生命周期回调失效的解决方案
问题根源
ML-Kit的文档扫描器实际启动的是Google Play服务提供的独立Activity,不属于你的App包名/进程范畴。这会导致两个问题:
- 宿主Activity被扫描器界面覆盖,但并未真正进入
onStopped()状态,所以ActivityLifecycleCallbacks的回调不会触发 - 默认的
AppLifecycleObserver会把第三方Activity的启动算入App的Activity计数,导致打开扫描器时误判为进入后台,而真正切后台时计数未归0,无法触发onEnterBackground
可行解决方案
1. 绑定扫描器的返回结果主动处理
利用Activity Result API的回调,不管扫描成功还是取消,都直接执行Utils.removeWindowManager(),完全绕开生命周期的问题:
// 注册扫描器的Activity Result回调 val documentScannerLauncher = registerForActivityResult(ScanDocumentContract()) { result -> // 无论扫描结果如何,都执行Window移除操作 Utils.removeWindowManager(baseContext) // 正常处理扫描结果 result?.let { // 处理扫描得到的文档... } } // 启动扫描器 documentScannerLauncher.launch(ScanDocumentOptions.Builder().build())
2. 修正AppLifecycleObserver的Activity计数逻辑
自定义Application.ActivityLifecycleCallbacks,只统计当前App包名的Activity数量,避免被第三方Activity干扰:
class CustomAppLifecycleObserver(private val context: Context) : Application.ActivityLifecycleCallbacks { private var appActivityCount = 0 override fun onActivityStarted(activity: Activity) { // 仅统计当前App的Activity if (activity.packageName == context.packageName) { appActivityCount++ if (appActivityCount == 1) { // App进入前台,可做对应处理 } } } override fun onActivityStopped(activity: Activity) { if (activity.packageName == context.packageName) { appActivityCount-- if (appActivityCount == 0) { // App真正进入后台,执行Window移除 Utils.removeWindowManager(context) } } } // 实现其他空回调方法 override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) = Unit override fun onActivityResumed(activity: Activity) = Unit override fun onActivityPaused(activity: Activity) = Unit override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) = Unit override fun onActivityDestroyed(activity: Activity) = Unit } // 在Application的onCreate中注册 registerActivityLifecycleCallbacks(CustomAppLifecycleObserver(this))
3. 监听当前Window的焦点变化
给宿主Activity的Window添加焦点监听,当窗口失去焦点且App确实进入后台时,执行移除操作:
// 在Activity的onCreate中设置 window.onWindowFocusChangeListener = { hasFocus -> if (!hasFocus && isScannerActive && isAppInBackground()) { Utils.removeWindowManager(baseContext) } } // 标记扫描器是否处于激活状态 private var isScannerActive = false // 启动扫描器时标记状态 documentScannerLauncher.launch(ScanDocumentOptions.Builder().build()) isScannerActive = true // 辅助方法:判断App是否处于后台 private fun isAppInBackground(): Boolean { val am = getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager am.runningAppProcesses?.forEach { processInfo -> if (processInfo.processName == packageName) { return processInfo.importance != ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND } } return false }
内容的提问来源于stack exchange,提问作者Rabee Elkholy
相关产品推荐
相关产品推荐

