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

Flutter应用终止/锁屏时FCM触发全屏通知页面的实现

解决Flutter应用终止/锁屏时FCM全屏页面跳转问题

核心思路

应用终止或锁屏状态下,FCM消息会由Android系统的FirebaseMessagingService处理,需通过自定义服务解析isfullscreen字段,结合flutter_local_notifications的全屏Intent配置,配合路由跳转实现需求。


1. 自定义Android端FCM消息处理服务

创建MyFirebaseMessagingService继承FirebaseMessagingService,在onMessageReceived中解析payload字段并分发处理逻辑:

package com.your.package.name

import com.google.firebase.messaging.FirebaseMessagingService
import com.google.firebase.messaging.RemoteMessage
import com.dexterous.flutterlocalnotifications.FlutterLocalNotificationsPlugin
import com.dexterous.flutterlocalnotifications.AndroidNotificationDetails
import android.app.PendingIntent
import android.content.Intent
import android.content.pm.PackageManager

class MyFirebaseMessagingService : FirebaseMessagingService() {
    override fun onMessageReceived(remoteMessage: RemoteMessage) {
        super.onMessageReceived(remoteMessage)
        // 解析payload中的isfullscreen字段
        val isFullScreen = remoteMessage.data["isfullscreen"]?.toBoolean() ?: false
        
        if (isFullScreen) {
            showFullScreenNotification(remoteMessage)
        } else {
            showNormalNotification(remoteMessage)
        }
    }

    private fun showFullScreenNotification(remoteMessage: RemoteMessage) {
        val notificationPlugin = FlutterLocalNotificationsPlugin()
        val title = remoteMessage.data["title"] ?: "全屏通知"
        val body = remoteMessage.data["body"] ?: "紧急通知内容"

        // 配置全屏通知参数
        val androidDetails = AndroidNotificationDetails(
            "fullscreen_notif_channel",
            "全屏通知频道",
            channelDescription = "用于触发全屏页面的通知频道",
            priority = AndroidNotificationDetails.Priority.HIGH,
            importance = AndroidNotificationDetails.Importance.HIGH,
            fullScreenIntent = true,
            enableLights = true,
            enableVibration = true
        )

        // 创建跳转至Flutter页面的PendingIntent
        val launchIntent = packageManager.getLaunchIntentForPackage(packageName)?.apply {
            // 添加路由参数,用于Flutter端跳转指定页面
            putExtra("route", "/full-screen-notification")
            flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
        }
        val pendingIntent = PendingIntent.getActivity(
            this,
            0,
            launchIntent,
            PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
        )
        androidDetails.setContentIntent(pendingIntent)

        // 展示全屏通知
        notificationPlugin.show(
            System.currentTimeMillis().toInt(),
            title,
            body,
            com.dexterous.flutterlocalnotifications.NotificationDetails(androidDetails, null)
        )
    }

    private fun showNormalNotification(remoteMessage: RemoteMessage) {
        // 普通通知的常规实现,使用flutter_local_notifications默认逻辑即可
        val notificationPlugin = FlutterLocalNotificationsPlugin()
        val androidDetails = AndroidNotificationDetails(
            "normal_notif_channel",
            "普通通知频道",
            priority = AndroidNotificationDetails.Priority.DEFAULT,
            importance = AndroidNotificationDetails.Importance.DEFAULT
        )
        notificationPlugin.show(
            System.currentTimeMillis().toInt(),
            remoteMessage.data["title"],
            remoteMessage.data["body"],
            com.dexterous.flutterlocalnotifications.NotificationDetails(androidDetails, null)
        )
    }
}

在AndroidManifest.xml中注册该服务:

<service
    android:name=".MyFirebaseMessagingService"
    android:exported="false">
    <intent-filter>
        <action android:name="com.google.firebase.MESSAGING_EVENT" />
    </intent-filter>
</service>

2. Flutter端路由跳转配置

在MaterialApp的onGenerateRoute中监听路由参数,跳转至FullScreenNotificationPage:

import 'package:flutter/material.dart';
import 'full_screen_notification_page.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'FCM Demo',
      onGenerateRoute: (settings) {
        // 处理从Android端传递的路由参数
        if (settings.name == '/full-screen-notification') {
          return MaterialPageRoute(
            builder: (context) => const FullScreenNotificationPage(),
          );
        }
        return MaterialPageRoute(builder: (context) => const HomePage());
      },
      home: const HomePage(),
    );
  }
}

3. 权限配置与申请

AndroidManifest.xml添加权限

<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT" />
<uses-permission android:name="android.permission.WAKE_LOCK" />

Flutter端动态申请权限

使用permission_handler插件申请必要权限:

import 'package:permission_handler/permission_handler.dart';

Future<void> requestNotificationPermissions() async {
  // 申请通知权限
  if (await Permission.notification.isDenied) {
    await Permission.notification.request();
  }
  // Android 12+ 需申请全屏Intent权限
  if (await Permission.fullScreenIntent.isDenied) {
    await Permission.fullScreenIntent.request();
  }
}

// 在应用初始化时调用
@override
void initState() {
  super.initState();
  requestNotificationPermissions();
}

4. 关键注意事项

  • FCM消息类型:必须发送数据消息(或通知+数据混合消息),纯通知消息在应用终止时会由系统直接展示,无法触发自定义服务逻辑。示例payload:
    {
      "data": {
        "isfullscreen": "true",
        "title": "紧急全屏通知",
        "body": "请查看详细内容"
      },
      "to": "设备FCM Token"
    }
    
  • 通知频道优先级:全屏通知对应的频道必须设置为HIGH或MAX级别,确保锁屏状态下能正常触发全屏Intent。
  • Android版本兼容:Android 12及以上需动态申请USE_FULL_SCREEN_INTENT权限,否则全屏Intent无法生效。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 22:37:04