Android通知操作唤起后台应用失效,偶现崩溃问题求助
通知操作唤起后台应用失效+崩溃问题修复
我给通知添加了一个操作按钮,需求是当应用处于后台(最小化)状态时,点击该按钮能唤起应用。但按以下代码实现后,功能未生效,还偶尔出现应用崩溃的情况:
原操作代码:
val answerIntent = Intent(context, ActionReceiver::class.java).apply { action = "ACTION_ANSWER" } val answerPendingIntent: PendingIntent = PendingIntent.getBroadcast(context, acceptPendingId, answerIntent, 0)
原接收器代码:
"ACTION_ANSWER" -> { if (!singleton.isAppInForeground(context)) { val openAppIntent = Intent(context, MainActivity::class.java) context.startActivity(openAppIntent) } // ...其他业务代码 }
原前台状态判断方法:
fun isAppInForeground(context: Context): Boolean { val activityManager = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager val runningAppProcesses = activityManager.runningAppProcesses ?: return false for (processInfo in runningAppProcesses) { if (processInfo.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) { if (processInfo.processName == context.packageName) { return true } } } return false }
问题根源
- 后台启动Activity缺少必要标记:在后台环境下启动Activity必须添加
FLAG_ACTIVITY_NEW_TASK,否则系统会抛出ActivityNotFoundException直接导致崩溃。 - PendingIntent Flag设置不合规:Android 12及以上版本强制要求指定
FLAG_IMMUTABLE或FLAG_MUTABLE,旧的0值会导致PendingIntent无法正常触发,甚至引发权限异常。 - 前台状态判断方法过时且不准确:
runningAppProcesses在API 29已被废弃,且该方法依赖系统返回的进程快照,容易出现判断偏差,导致逻辑执行错误。
修复方案
1. 修正PendingIntent的Flag
根据Android版本适配设置正确的Flag,保证PendingIntent能正常触发:
val flags = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { // Android 12+ 优先用IMMUTABLE,若需要动态修改Intent内容则用FLAG_MUTABLE PendingIntent.FLAG_IMMUTABLE } else { PendingIntent.FLAG_UPDATE_CURRENT } val answerPendingIntent: PendingIntent = PendingIntent.getBroadcast(context, acceptPendingId, answerIntent, flags)
2. 修复后台启动Activity的逻辑
添加必要的启动Flag,同时避免重复创建任务栈:
"ACTION_ANSWER" -> { if (!singleton.isAppInForeground(context)) { val openAppIntent = Intent(context, MainActivity::class.java).apply { // 必须添加NEW_TASK标记才能在后台启动Activity addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) // 可选:清除现有任务栈,直接回到主页面,避免多实例 addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP) } context.startActivity(openAppIntent) } // ...其他业务代码 }
3. 替换准确的前台状态判断方法
使用UsageStatsManager实现更可靠的前台状态判断,兼容API 21+:
fun isAppInForeground(context: Context): Boolean { val usageStatsManager = context.getSystemService(Context.USAGE_STATS_SERVICE) as UsageStatsManager val currentTime = System.currentTimeMillis() // 查询最近10秒内的应用使用统计 val usageStatsList = usageStatsManager.queryUsageStats( UsageStatsManager.INTERVAL_DAILY, currentTime - 10000, currentTime ) if (!usageStatsList.isNullOrEmpty()) { // 按最后使用时间倒序,取最顶部的应用包名 val sortedStats = usageStatsList.sortedByDescending { it.lastTimeUsed } val topPackageName = sortedStats.firstOrNull()?.packageName return topPackageName == context.packageName } return false }
注意:需要在AndroidManifest.xml中添加权限:
<uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" tools:ignore="ProtectedPermissions" />
该权限为特殊权限,无法通过代码直接申请,需要引导用户在系统设置的「应用使用权限」中开启对应权限。
内容的提问来源于stack exchange,提问作者steind.VY
相关产品推荐
相关产品推荐

