Android不同应用状态下通知点击跳转逻辑实现求助(API 32)
解决方案思路
核心是用一个通知路由Activity(比如NotificationRouterActivity)作为通知点击的唯一入口,所有通知的PendingIntent都指向它,然后在这个Activity的onCreate里实时判断当前应用状态和生物验证状态,再决定跳转逻辑。这样就能彻底解决广播里判断状态过时的问题。
步骤1:创建通知路由Activity
这个Activity做成透明无界面的(避免闪屏),只负责逻辑判断和跳转。
1.1 配置Manifest
在AndroidManifest.xml里注册该Activity,设置透明主题:
<activity android:name=".NotificationRouterActivity" android:theme="@style/Theme.Transparent" android:excludeFromRecents="true" android:launchMode="singleTask"> <intent-filter> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity>
透明主题在styles.xml中定义:
<style name="Theme.Transparent" parent="Theme.AppCompat.Light.NoActionBar"> <item name="android:windowBackground">@android:color/transparent</item> <item name="android:windowIsTranslucent">true</item> <item name="android:windowAnimationStyle">@null</item> </style>
1.2 路由Activity核心逻辑
在NotificationRouterActivity的onCreate中完成实时判断:
class NotificationRouterActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // 1. 获取生物验证状态(BiometricActivity验证成功后存入SharedPreferences) val isBiometricAuthenticated = getSharedPreferences("AppPrefs", MODE_PRIVATE) .getBoolean("is_biometric_authed", false) // 2. 判断应用当前状态 val isAppInForeground = isAppRunningInForeground() val isAppClosed = !isAppProcessRunning() // 3. 按场景处理跳转 when { // 场景3:应用已关闭 isAppClosed -> { val intent = Intent(this, SplashActivity::class.java).apply { putExtra("open_notification", true) flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK } startActivity(intent) finish() } // 场景1:应用前台且已完成生物验证 isAppInForeground && isBiometricAuthenticated -> { val intent = Intent(this, NotificationActivity::class.java).apply { flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_SINGLE_TOP } startActivity(intent) finish() } // 场景2:应用后台 else -> { if (isBiometricAuthenticated) { // 调至前台并打开NotificationActivity val intent = packageManager.getLaunchIntentForPackage(packageName)?.apply { putExtra("open_notification", true) flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_REORDER_TO_FRONT } startActivity(intent) finish() } else { // 先跳转生物验证页面,验证成功后打开目标页 val intent = Intent(this, BiometricActivity::class.java).apply { putExtra("target_activity", "NotificationActivity") flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP } startActivity(intent) finish() } } } } // 判断应用是否在前台运行 private fun isAppRunningInForeground(): Boolean { val activityManager = getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager val appProcesses = activityManager.runningAppProcesses ?: return false for (processInfo in appProcesses) { if (processInfo.processName == packageName && processInfo.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) { return true } } return false } // 判断应用进程是否存活(检测应用是否已关闭) private fun isAppProcessRunning(): Boolean { val activityManager = getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager val runningProcesses = activityManager.runningAppProcesses ?: return false return runningProcesses.any { it.processName == packageName } } }
步骤2:修改AlarmBroadcast的通知逻辑
把原来指向NotificationActivity的PendingIntent改成指向路由Activity:
class AlarmBroadcast : BroadcastReceiver() { override fun onReceive(context: Context?, intent: Intent?) { context ?: return // 创建指向路由Activity的PendingIntent val routerIntent = Intent(context, NotificationRouterActivity::class.java).apply { flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP } val pendingIntent = PendingIntent.getActivity( context, 0, routerIntent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE // API32必须加FLAG_IMMUTABLE ) // 构建并发送通知 val notification = NotificationCompat.Builder(context, "your_channel_id") .setContentTitle("通知标题") .setContentText("通知内容") .setSmallIcon(R.drawable.ic_notification) .setContentIntent(pendingIntent) .setAutoCancel(true) .build() val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager notificationManager.notify(1, notification) } }
步骤3:处理其他页面的跳转衔接
3.1 SplashActivity处理启动标记
当应用从关闭状态启动时,根据标记跳转到目标页:
class SplashActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_splash) // 模拟初始化流程 Handler(Looper.getMainLooper()).postDelayed({ val openNotification = intent.getBooleanExtra("open_notification", false) if (openNotification) { startActivity(Intent(this, NotificationActivity::class.java)) } else { startActivity(Intent(this, BiometricActivity::class.java)) } finish() }, 1000) } }
3.2 BiometricActivity处理目标页跳转
验证成功后,根据路由传递的参数打开指定页面:
class BiometricActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_biometric) biometricButton.setOnClickListener { performBiometricAuthentication() } } private fun performBiometricAuthentication() { // 省略生物验证具体实现 // 验证成功后更新状态 getSharedPreferences("AppPrefs", MODE_PRIVATE) .edit() .putBoolean("is_biometric_authed", true) .apply() // 跳转到目标页 val targetActivity = intent.getStringExtra("target_activity") if (targetActivity == "NotificationActivity") { startActivity(Intent(this, NotificationActivity::class.java)) } else { startActivity(Intent(this, ProfileActivity::class.java)) } finish() } }
步骤4:维护生物验证状态
根据业务需求重置验证状态,比如应用后台时:
class MainActivity : AppCompatActivity() { override fun onStop() { super.onStop() // 示例:应用后台时重置验证状态,需根据实际业务调整 getSharedPreferences("AppPrefs", MODE_PRIVATE) .edit() .putBoolean("is_biometric_authed", false) .apply() } }
关键说明
- 路由Activity的实时判断彻底解决了广播中状态过时的问题,所有逻辑在用户点击通知时才执行。
- 用SharedPreferences存储生物验证状态,确保跨页面/进程的状态一致性。
- 注意API32及以上PendingIntent必须添加
FLAG_IMMUTABLE,避免兼容性报错。 - 透明路由Activity不会产生视觉干扰,用户感知不到中间跳转过程。
内容的提问来源于stack exchange,提问作者Muhammad Umer Naeem Shami
相关产品推荐
相关产品推荐

