Flutter消息推送插件firebase_messaging的使用

发布于 1周前 作者 vueper 来自 Flutter

Flutter消息推送插件firebase_messaging的使用

Firebase Messaging Plugin for Flutter

这是一个Flutter插件,用于使用FCM(Firebase Cloud Messaging API)。要了解更多关于Firebase Cloud Messaging的信息,请访问Firebase网站

Getting Started

要开始使用Flutter的Firebase Cloud Messaging,请参考官方文档

Usage 示例代码

下面是一个完整的示例应用,演示了如何在Flutter应用程序中使用firebase_messaging插件:

import 'dart:async';
import 'dart:convert';

import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:http/http.dart' as http;

import 'firebase_options.dart'; // 请确保你已经配置了你的Firebase项目

// 定义一个顶级命名处理程序,用于处理后台/终止状态的消息。
@pragma('vm:entry-point')
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
  await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
  await setupFlutterNotifications();
  showFlutterNotification(message);
  print('Handling a background message ${message.messageId}');
}

// 创建一个Android通知通道用于高优先级的通知
late AndroidNotificationChannel channel;

bool isFlutterLocalNotificationsInitialized = false;

Future<void> setupFlutterNotifications() async {
  if (isFlutterLocalNotificationsInitialized) {
    return;
  }
  channel = const AndroidNotificationChannel(
    'high_importance_channel', // id
    'High Importance Notifications', // title
    description:
        'This channel is used for important notifications.', // description
    importance: Importance.high,
  );

  flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();

  // 创建一个Android Notification Channel
  await flutterLocalNotificationsPlugin
      .resolvePlatformSpecificImplementation<AndroidFlutterLocalNotificationsPlugin>()
      ?.createNotificationChannel(channel);

  // 更新iOS前景通知呈现选项以允许弹出通知
  await FirebaseMessaging.instance.setForegroundNotificationPresentationOptions(
    alert: true,
    badge: true,
    sound: true,
  );
  isFlutterLocalNotificationsInitialized = true;
}

void showFlutterNotification(RemoteMessage message) {
  RemoteNotification? notification = message.notification;
  AndroidNotification? android = message.notification?.android;
  if (notification != null && android != null && !kIsWeb) {
    flutterLocalNotificationsPlugin.show(
      notification.hashCode,
      notification.title,
      notification.body,
      NotificationDetails(
        android: AndroidNotificationDetails(
          channel.id,
          channel.name,
          channelDescription: channel.description,
          icon: 'launch_background',
        ),
      ),
    );
  }
}

// 初始化FlutterLocalNotificationsPlugin包
late FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin;

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
  // 尽早设置后台消息处理程序
  FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);

  if (!kIsWeb) {
    await setupFlutterNotifications();
  }

  runApp(MessagingExampleApp());
}

class MessagingExampleApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Messaging Example App',
      theme: ThemeData.dark(),
      routes: {
        '/': (context) => Application(),
        '/message': (context) => MessageView(),
      },
    );
  }
}

// 简单计数器使消息唯一
int _messageCount = 0;

String constructFCMPayload(String? token) {
  _messageCount++;
  return jsonEncode({
    'token': token,
    'data': {
      'via': 'FlutterFire Cloud Messaging!!!',
      'count': _messageCount.toString(),
    },
    'notification': {
      'title': 'Hello FlutterFire!',
      'body': 'This notification (#$_messageCount) was created via FCM!',
    },
  });
}

class Application extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => _Application();
}

class _Application extends State<Application> {
  String? _token;
  String? initialMessage;
  bool _resolved = false;

  @override
  void initState() {
    super.initState();

    FirebaseMessaging.instance.getInitialMessage().then(
          (value) => setState(
            () {
              _resolved = true;
              initialMessage = value?.data.toString();
            },
          ),
        );

    FirebaseMessaging.onMessage.listen(showFlutterNotification);

    FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
      print('A new onMessageOpenedApp event was published!');
      Navigator.pushNamed(
        context,
        '/message',
        arguments: MessageArguments(message, true),
      );
    });
  }

  Future<void> sendPushMessage() async {
    if (_token == null) {
      print('Unable to send FCM message, no token exists.');
      return;
    }

    try {
      await http.post(
        Uri.parse('https://api.rnfirebase.io/messaging/send'),
        headers: <String, String>{
          'Content-Type': 'application/json; charset=UTF-8',
        },
        body: constructFCMPayload(_token),
      );
      print('FCM request for device sent!');
    } catch (e) {
      print(e);
    }
  }

  Future<void> onActionSelected(String value) async {
    switch (value) {
      case 'subscribe':
        {
          print(
            'FlutterFire Messaging Example: Subscribing to topic "fcm_test".',
          );
          await FirebaseMessaging.instance.subscribeToTopic('fcm_test');
          print(
            'FlutterFire Messaging Example: Subscribing to topic "fcm_test" successful.',
          );
        }
        break;
      case 'unsubscribe':
        {
          print(
            'FlutterFire Messaging Example: Unsubscribing from topic "fcm_test".',
          );
          await FirebaseMessaging.instance.unsubscribeFromTopic('fcm_test');
          print(
            'FlutterFire Messaging Example: Unsubscribing from topic "fcm_test" successful.',
          );
        }
        break;
      case 'get_apns_token':
        {
          if (defaultTargetPlatform == TargetPlatform.iOS ||
              defaultTargetPlatform == TargetPlatform.macOS) {
            print('FlutterFire Messaging Example: Getting APNs token...');
            String? token = await FirebaseMessaging.instance.getAPNSToken();
            print('FlutterFire Messaging Example: Got APNs token: $token');
          } else {
            print(
              'FlutterFire Messaging Example: Getting an APNs token is only supported on iOS and macOS platforms.',
            );
          }
        }
        break;
      default:
        break;
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Cloud Messaging'),
        actions: <Widget>[
          PopupMenuButton(
            onSelected: onActionSelected,
            itemBuilder: (BuildContext context) {
              return [
                const PopupMenuItem(
                  value: 'subscribe',
                  child: Text('Subscribe to topic'),
                ),
                const PopupMenuItem(
                  value: 'unsubscribe',
                  child: Text('Unsubscribe to topic'),
                ),
                const PopupMenuItem(
                  value: 'get_apns_token',
                  child: Text('Get APNs token (Apple only)'),
                ),
              ];
            },
          ),
        ],
      ),
      floatingActionButton: Builder(
        builder: (context) => FloatingActionButton(
          onPressed: sendPushMessage,
          backgroundColor: Colors.white,
          child: const Icon(Icons.send),
        ),
      ),
      body: SingleChildScrollView(
        child: Column(
          children: [
            MetaCard('Permissions', Permissions()),
            MetaCard(
              'Initial Message',
              Column(
                children: [
                  Text(_resolved ? 'Resolved' : 'Resolving'),
                  Text(initialMessage ?? 'None'),
                ],
              ),
            ),
            MetaCard(
              'FCM Token',
              TokenMonitor((token) {
                _token = token;
                return token == null
                    ? const CircularProgressIndicator()
                    : SelectableText(
                        token,
                        style: const TextStyle(fontSize: 12),
                      );
              }),
            ),
            ElevatedButton(
              onPressed: () {
                FirebaseMessaging.instance
                    .getInitialMessage()
                    .then((RemoteMessage? message) {
                  if (message != null) {
                    Navigator.pushNamed(
                      context,
                      '/message',
                      arguments: MessageArguments(message, true),
                    );
                  }
                });
              },
              child: const Text('getInitialMessage()'),
            ),
            MetaCard('Message Stream', MessageList()),
          ],
        ),
      ),
    );
  }
}

// UI组件,用于显示元数据
class MetaCard extends StatelessWidget {
  final String _title;
  final Widget _children;

  MetaCard(this._title, this._children);

  @override
  Widget build(BuildContext context) {
    return Container(
      width: double.infinity,
      margin: const EdgeInsets.only(left: 8, right: 8, top: 8),
      child: Card(
        child: Padding(
          padding: const EdgeInsets.all(16),
          child: Column(
            children: [
              Container(
                margin: const EdgeInsets.only(bottom: 16),
                child: Text(_title, style: const TextStyle(fontSize: 18)),
              ),
              _children,
            ],
          ),
        ),
      ),
    );
  }
}

此代码展示了如何集成和使用firebase_messaging插件进行消息推送,并且包括了处理前台、后台和应用终止状态下的消息接收逻辑。通过flutter_local_notifications插件实现了本地通知功能。为了使这个例子工作,你需要完成平台特定的设置和要求,并根据你的Firebase项目配置好相应的参数。

注意事项:

  1. 平台特定设置:遵循官方指南完成平台特定设置,如添加必要的依赖项到build.gradle文件中等。
  2. 服务端API Key:发送推送消息时使用的API Key需要从Firebase控制台获取。
  3. 设备Token:发送消息的目标设备Token可以通过FirebaseMessaging.instance.getToken()方法获得。
  4. 权限:确保应用拥有接收推送通知所需的权限。
  5. 测试环境:最好在真实设备上测试推送通知,因为模拟器可能不支持所有的推送特性。

更多关于Flutter消息推送插件firebase_messaging的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter消息推送插件firebase_messaging的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是一个关于如何在Flutter应用中使用firebase_messaging插件来实现消息推送的示例代码。这个示例将涵盖基本的配置和消息接收处理。

1. 添加依赖

首先,在pubspec.yaml文件中添加firebase_messaging依赖:

dependencies:
  flutter:
    sdk: flutter
  firebase_core: ^1.10.0  # 确保也添加了firebase_core,用于Firebase初始化
  firebase_messaging: ^11.2.0  # 使用最新版本

然后运行flutter pub get来安装依赖。

2. 配置Firebase项目

在Firebase控制台中创建一个新的项目,并添加Flutter应用的包名。然后下载google-services.json文件并将其放置在android/app/目录下。对于iOS,你需要配置Runner/GoogleService-Info.plist文件。

3. 初始化Firebase和Firebase Messaging

main.dart文件中,初始化Firebase和Firebase Messaging。

import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_messaging/firebase_messaging.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Firebase Messaging Demo'),
        ),
        body: MyHomePage(),
      ),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final FirebaseMessaging _firebaseMessaging = FirebaseMessaging.instance;

  @override
  void initState() {
    super.initState();
    _configureFirebaseMessaging();
  }

  void _configureFirebaseMessaging() {
    // 当应用在前台时接收到消息
    _firebaseMessaging.onMessage.listen((RemoteMessage message) {
      print('A new FCM message arrived!');
      print('Message data: ${message.data}');

      // 在这里可以显示本地通知或其他UI更新
      _showLocalNotification(message.data);
    });

    // 当应用在后台时接收到消息(点击通知后触发)
    _firebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
      print('A user tapped on a notification!');
      print('Message data: ${message.data}');
    });
  }

  Future<void> _showLocalNotification(Map<String, dynamic> message) async {
    // 显示本地通知的代码(需要添加flutter_local_notifications依赖)
    // 此处为示例,实际使用时请根据需要配置
  }

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Text('Firebase Messaging is configured!'),
    );
  }
}

4. (可选)显示本地通知

为了显示本地通知,你需要添加flutter_local_notifications依赖,并在配置Firebase Messaging时调用它。

pubspec.yaml中添加依赖:

dependencies:
  flutter_local_notifications: ^9.0.0  # 使用最新版本

然后在_MyHomePageState类中配置本地通知:

import 'package:flutter_local_notifications/flutter_local_notifications.dart';

class _MyHomePageState extends State<MyHomePage> {
  // ...

  final FlutterLocalNotificationsPlugin _notificationsPlugin =
      FlutterLocalNotificationsPlugin();

  var _initializationSettingsAndroid;
  var _initializationSettingsIOS;
  var _initializationSettings;

  @override
  void initState() {
    super.initState();
    _configureLocalNotifications();
    _configureFirebaseMessaging();
  }

  Future<void> _configureLocalNotifications() async {
    const AndroidInitializationSettings initializationSettingsAndroid =
        AndroidInitializationSettings('@mipmap/ic_launcher');
    _initializationSettingsAndroid = initializationSettingsAndroid;

    // 对于iOS,请根据需要配置初始化设置
    // const IOSInitializationSettings initializationSettingsIOS = IOSInitializationSettings(
    //   requestAlertPermission: true,
    //   requestBadgePermission: true,
    //   requestSoundPermission: true,
    // );
    // _initializationSettingsIOS = initializationSettingsIOS;

    // 统一初始化设置
    _initializationSettings = InitializationSettings(
      android: _initializationSettingsAndroid,
      // iOS: _initializationSettingsIOS,
    );

    await _notificationsPlugin.initialize(_initializationSettings,
        onSelectNotification: (String? payload) async {
      if (payload != null) {
        // 处理通知点击事件
        print('Notification payload: $payload');
      }
    });
  }

  void _showLocalNotification(Map<String, dynamic> message) async {
    var androidPlatformChannelSpecifics = AndroidNotificationDetails(
        'your_channel_id', 'Your channel name', 'Your channel description',
        importance: Importance.max,
        priority: Priority.high,
        ticker: 'ticker');
    var iOSPlatformChannelSpecifics = IOSNotificationDetails();
    var platformChannelSpecifics = NotificationDetails(
        android: androidPlatformChannelSpecifics,
        iOS: iOSPlatformChannelSpecifics);

    await _notificationsPlugin.show(
      0, // 通知ID
      message['title'] ?? '',
      message['body'] ?? '',
      platformChannelSpecifics,
      payload: jsonEncode(message),
    );
  }

  // ...
}

请确保在Android项目中配置通知渠道(your_channel_id),并在Firebase控制台中发送消息时包含titlebody字段。

总结

上述代码展示了如何在Flutter应用中使用firebase_messaging插件来接收和处理Firebase Cloud Messaging消息。通过结合flutter_local_notifications插件,你还可以显示本地通知来通知用户。请确保在实际项目中根据需要进行进一步的配置和优化。

回到顶部