You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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
    }

问题根源

  1. 后台启动Activity缺少必要标记:在后台环境下启动Activity必须添加FLAG_ACTIVITY_NEW_TASK,否则系统会抛出ActivityNotFoundException直接导致崩溃。
  2. PendingIntent Flag设置不合规:Android 12及以上版本强制要求指定FLAG_IMMUTABLE或FLAG_MUTABLE,旧的0值会导致PendingIntent无法正常触发,甚至引发权限异常。
  3. 前台状态判断方法过时且不准确: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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 18:23:24