打开custom-tab时如何监听Activity A所属任务的前后台切换回调
问题原因说明
通用的Android前后台检测方案(比如ProcessLifecycleOwner)的底层逻辑是:当当前应用进程内的所有Activity都进入onStop状态时,判定应用进入后台。
Custom Tab本质是运行在浏览器进程的系统级Activity,你从Activity A启动Custom Tab后,Activity A会回调onStop,此时你的应用进程内没有处于活跃状态的Activity,就会触发通用方案的后台回调,属于误触发。
解决方案
方案1:无权限标记位法(推荐)
不需要申请额外权限,侵入性最低,适配所有系统版本。
- 全局定义一个布尔标记位,标识当前是否是启动Custom Tab导致的Activity退出
- 启动Custom Tab前将标记位设为
true - 在你原有前后台检测的
onBackground回调中增加判断逻辑,如果标记位为true,则忽略本次回调,同时重置标记位 - 在Activity A的
onStart回调中重置标记位为false
示例代码:
// 全局标记位,可放在Application类或者全局ViewModel中 var isCustomTabLaunching = false // 启动Custom Tab前的逻辑 fun launchCustomTab(activity: Activity, uri: Uri) { isCustomTabLaunching = true // 原有Custom Tab启动逻辑 CustomTabsIntent.Builder().build().launchUrl(activity, uri) } // 原有前后台检测的后台回调逻辑 fun onAppBackground() { if (isCustomTabLaunching) { isCustomTabLaunching = false return } // 此处写你真正的后台逻辑 } // Activity A中的生命周期回调 override fun onStart() { super.onStart() isCustomTabLaunching = false // 此处写你回到前台的逻辑 }
方案2:任务栈判断法
通过系统任务栈状态判断你的应用任务是否真的进入后台,准确率更高,需要申请少量权限。
- 在
AndroidManifest.xml中添加权限:<!-- 兼容低版本任务栈查询权限 --> <uses-permission android:name="android.permission.GET_TASKS" /> <!-- Android 11及以上需要额外添加包查询权限 --> <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" tools:ignore="QueryAllPackagesPermission" /> - 编写任务栈前台判断工具方法:
fun isAppTaskForeground(context: Context): Boolean { val activityManager = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager // 获取当前运行的前10个任务 val runningTasks = activityManager.getRunningTasks(10) for (task in runningTasks) { if (task.topActivity?.packageName == context.packageName) { return task.isForeground } } return false } - 在Activity A的
onStop中延迟判断,避免Custom Tab启动过程中的状态误判:private var backgroundCheckJob: Job? = null override fun onStop() { super.onStop() backgroundCheckJob?.cancel() backgroundCheckJob = lifecycleScope.launch { // 延迟500ms等待Custom Tab启动完成,避免状态错误 delay(500) if (!isAppTaskForeground(this@ActivityA)) { // 应用任务真的进入后台,执行你的逻辑 } } } override fun onStart() { super.onStart() backgroundCheckJob?.cancel() // 应用回到前台,执行你的逻辑 }
内容的提问来源于stack exchange,提问作者q126y
相关产品推荐
相关产品推荐

