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

Android Studio中如何根据当前显示屏幕控制通知是否展示?

实现方案:Jetpack Compose单Activity架构下控制FCM通知展示

核心思路是跟踪应用前台状态+当前活跃界面/会话标识,在FCM消息接收时根据这两个条件判断是否显示通知。以下是具体实现步骤:


1. 跟踪应用前台状态

首先需要判断应用是否处于前台,后台状态下无论什么界面都要展示通知。

实现应用生命周期观察者

class AppLifecycleObserver : DefaultLifecycleObserver {
    var isAppInForeground = false
        private set

    override fun onResume(owner: LifecycleOwner) {
        super.onResume(owner)
        isAppInForeground = true
    }

    override fun onPause(owner: LifecycleOwner) {
        super.onPause(owner)
        isAppInForeground = false
    }
}

在Application类中注册观察者

class MyApp : Application() {
    val appLifecycleObserver = AppLifecycleObserver()

    override fun onCreate() {
        super.onCreate()
        ProcessLifecycleOwner.get().lifecycle.addObserver(appLifecycleObserver)
    }
}

2. 跟踪当前活跃的聊天会话/界面

通过DataStore持久化当前打开的聊天会话ID(或界面标识),确保后台服务能获取到最新状态。

定义DataStore存储类

private val Context.dataStore by preferencesDataStore(name = "app_prefs")

class AppPrefs(private val context: Context) {
    private val dataStore = context.dataStore

    suspend fun setActiveChatId(chatId: String?) {
        dataStore.edit { preferences ->
            preferences[ACTIVE_CHAT_ID] = chatId ?: ""
        }
    }

    fun getActiveChatId(): Flow<String?> {
        return dataStore.data.map { preferences ->
            val id = preferences[ACTIVE_CHAT_ID]
            if (id.isNullOrEmpty()) null else id
        }
    }

    companion object {
        val ACTIVE_CHAT_ID = stringPreferencesKey("active_chat_id")
    }
}

在聊天界面更新会话状态

在聊天界面进入时保存当前会话ID,离开时清空:

@Composable
fun ChatScreen(chatId: String, appPrefs: AppPrefs) {
    // 进入界面时保存当前会话ID
    LaunchedEffect(chatId) {
        appPrefs.setActiveChatId(chatId)
    }

    // 界面销毁时清空会话ID
    DisposableEffect(Unit) {
        onDispose {
            CoroutineScope(Dispatchers.IO).launch {
                appPrefs.setActiveChatId(null)
            }
        }
    }

    // 聊天界面UI逻辑...
}

3. 在FCM服务中判断是否展示通知

在FirebaseMessagingService的onMessageReceived方法中,结合前台状态和活跃会话ID判断:

class MyFirebaseMessagingService : FirebaseMessagingService() {
    private val appPrefs by lazy { AppPrefs(applicationContext) }
    private val appLifecycleObserver by lazy { (application as MyApp).appLifecycleObserver }

    override fun onMessageReceived(remoteMessage: RemoteMessage) {
        super.onMessageReceived(remoteMessage)

        // 从消息中提取目标会话ID(假设消息data字段包含"chat_id")
        val messageChatId = remoteMessage.data["chat_id"]
        val isTargetChatMessage = messageChatId != null

        // 应用在后台:直接展示通知
        if (!appLifecycleObserver.isAppInForeground) {
            showNotification(remoteMessage)
            return
        }

        // 应用在前台:判断是否处于对应聊天界面
        runBlocking {
            val activeChatId = appPrefs.getActiveChatId().first()
            // 非聊天消息,或当前打开的会话与消息目标会话不一致时,展示通知
            if (!isTargetChatMessage || activeChatId != messageChatId) {
                showNotification(remoteMessage)
            }
            // 否则不展示通知
        }
    }

    // 你的通知构建逻辑(示例)
    private fun showNotification(remoteMessage: RemoteMessage) {
        val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
        val notificationChannel = NotificationChannel(
            "chat_channel",
            "Chat Notifications",
            NotificationManager.IMPORTANCE_HIGH
        )
        notificationManager.createNotificationChannel(notificationChannel)

        val notification = NotificationCompat.Builder(this, "chat_channel")
            .setContentTitle(remoteMessage.notification?.title ?: "新消息")
            .setContentText(remoteMessage.notification?.body ?: "你有一条新消息")
            .setSmallIcon(R.drawable.ic_notification)
            .build()

        notificationManager.notify(System.currentTimeMillis().toInt(), notification)
    }
}

额外说明

  • 如果你的聊天界面没有会话ID(比如通用聊天列表),可以直接跟踪界面路由标识(比如通过NavHost的BackStackEntry获取当前路由),替换会话ID的判断逻辑即可。
  • 测试时需覆盖三种场景:应用后台、前台非聊天界面、前台对应聊天界面,确保通知行为符合预期。

内容的提问来源于stack exchange,提问作者Diken Mhrz

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 12:15:31