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

Android API28下目标页已显示时如何不加FLAG_ACTIVITY_NEW_TASK触发onNewIntent

核心原理说明

API 28(Android 9)开始对后台服务启动 Activity 做了强制限制:从非 Activity 上下文(比如 Service、BroadcastReceiver)启动 Activity 必须携带 FLAG_ACTIVITY_NEW_TASK,否则会抛出异常,这个系统限制无法绕过。下面的方案都是在遵守该限制的前提下,实现不重建 MyScreen 实例、触发 onNewIntent 回调的效果


方案1:配置Activity启动模式+配合Intent Flag(最简便)

仅需修改两处配置,原有业务逻辑完全不用改:

  1. 在 AndroidManifest.xml 中给 MyScreen 设置 singleTop 启动模式:
<activity
    android:name=".MyScreen"
    android:launchMode="singleTop" />
  1. 在 MyFirebaseMessagingService 中构建 Intent 时,除了系统要求的 FLAG_ACTIVITY_NEW_TASK,额外新增 FLAG_ACTIVITY_SINGLE_TOP:
// Java示例
Intent intent = new Intent(this, MyScreen.class);
// 系统强制要求必须加的Flag
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// 配合singleTop启动模式,栈顶已存在MyScreen时就会回调onNewIntent,不会重建
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
// 写入你需要传递的推送参数
intent.putExtra("push_data", 你的推送参数);
startActivity(intent);
// Kotlin示例
val intent = Intent(this, MyScreen::class.java).apply {
    addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
    addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP)
    putExtra("push_data", 你的推送参数)
}
startActivity(intent)

配置完成后如果当前栈顶已经是 MyScreen 实例,系统会直接回调 onNewIntent 方法,和你在 API 27 及以下版本的原有处理逻辑完全一致。


方案2:本地广播中转(完全避免直接从Service启动Activity)

如果不想修改 Activity 启动模式,可以用本地广播做中转,只有当 MyScreen 不在前台时才启动新实例:

  1. 在 MyScreen 中注册本地广播接收器接收推送点击事件:
private val pushReceiver = object : BroadcastReceiver() {
    override fun onReceive(context: Context?, intent: Intent?) {
        intent?.getStringExtra("push_data")?.let { data ->
            // 直接在当前已存在的MyScreen实例处理业务逻辑
            handlePushData(data)
        }
    }
}

override fun onResume() {
    super.onResume()
    LocalBroadcastManager.getInstance(this)
        .registerReceiver(pushReceiver, IntentFilter("ACTION_PUSH_CLICKED"))
}

override fun onPause() {
    super.onPause()
    LocalBroadcastManager.getInstance(this).unregisterReceiver(pushReceiver)
}
  1. 在 MyFirebaseMessagingService 中处理通知点击时先发送广播,广播未被接收(说明 MyScreen 不在前台)再启动 Activity:
val pushBroadcast = Intent("ACTION_PUSH_CLICKED").apply {
    putExtra("push_data", 你的推送参数)
}
val isHandled = LocalBroadcastManager.getInstance(this).sendBroadcast(pushBroadcast)
if (!isHandled) {
    // MyScreen不在前台,正常启动新实例即可
    val activityIntent = Intent(this, MyScreen::class.java).apply {
        addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
        putExtra("push_data", 你的推送参数)
    }
    startActivity(activityIntent)
}

内容的提问来源于stack exchange,提问作者Andrew Kolubov

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 20:09:05