繁体   English   中英

iOS 14 上的 Flutter FCM 7

[英]Flutter FCM 7 on iOS 14

对于更新到 iOS14 和 Xcode12 后从 FCM 发疯的每个人。 我花了2天时间解决了这些问题。 在模拟器上,它可以工作,但在真实设备上,它没有。 也许这些说明可以帮助某人并防止浪费时间。 此外,如果所有这些步骤都可以改进,那么听取 Flutter Guru 的一些想法会很棒:)。

注意: 新 FCM 版本 9+ 的说明

XCode 设置

在此处输入图片说明

AppDelegate.swift

import UIKit
import Flutter
import GoogleMaps
import Firebase
import FirebaseMessaging

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
    if #available(iOS 10.0, *) {
      UNUserNotificationCenter.current().delegate = self as UNUserNotificationCenterDelegate
    }
    GMSServices.provideAPIKey("")
    GeneratedPluginRegistrant.register(with: self)
    application.registerForRemoteNotifications()
    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }

    override func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        Auth.auth().setAPNSToken(deviceToken, type: .prod)
    }

    override func application(_ application: UIApplication,
        didReceiveRemoteNotification notification: [AnyHashable : Any],
        fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
        if Auth.auth().canHandleNotification(notification) {
          completionHandler(.noData)
          return
        }
    }

    override func application(_ application: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any]) -> Bool {
        if Auth.auth().canHandle(url) {
          return true
        }
        return false;
      }
}

信息表

    <key>FirebaseAppDelegateProxyEnabled</key>
    <false/>
    <key>FirebaseScreenReportingEnabled</key>
    <true/>

消息示例(可调用函数)

您的消息必须使用以下选项发送:

{
   mutableContent: true,
   contentAvailable: true,
   apnsPushType: "background"
}

只是在可调用函数中使用的示例

exports.sendNotification = functions.https.onCall(
    async (data) => {
        console.log(data, "this sendNotification data");
        var userTokens = [USERTOKEN1,USERTOKEN2,USERTOKEN3];
        var payload = {
            notification: {
                title: '',
                body: '',
                image: '',
            },
            data: {
                type:'',
            },
        };
        
        for (const [userToken,userUID] of Object.entries(userTokens)) {
            admin.messaging().sendToDevice(userToken, payload, {
                mutableContent: true,
                contentAvailable: true,
                apnsPushType: "background"
            });
        }
        
        return {code: 100, message: "notifications send successfully"};
    });

Flutter 消息服务

import 'dart:io';
import 'package:hive/hive.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:octopoos/providers/app.dart';

Future<dynamic> backgroundMessageHandler(Map<String, dynamic> message) async {}

class FirebaseMessagingService {
  final _app = AppProvider();
  var _prefs = Hive.box('preferences');
  FirebaseMessaging _firebaseMessaging = FirebaseMessaging();
  FlutterLocalNotificationsPlugin _flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();

  void initialise() {
    var android = AndroidInitializationSettings('mipmap/ic_launcher');
    var ios = IOSInitializationSettings();
    var platform = InitializationSettings(android, ios);
    _flutterLocalNotificationsPlugin.initialize(platform);

    _firebaseMessaging.configure(
      onLaunch: (Map<String, dynamic> message) async {
        _app.storeNotification(message);
      },
      onResume: (Map<String, dynamic> message) async {
        _app.storeNotification(message);
      },
      onMessage: (Map<String, dynamic> message) async {
        _app.storeNotification(message);
        if (_prefs.get('pushServiceState') == true) _showNotification(message);
      },
      onBackgroundMessage: Platform.isIOS ? null : backgroundMessageHandler,
    );

    if (Platform.isIOS) iOSPermission();
    _firebaseMessaging.getToken().then((token) {
      _prefs.put('fcmToken', token);
    });
  }

  void iOSPermission() {
    _firebaseMessaging.requestNotificationPermissions(
        IosNotificationSettings(sound: true, badge: true, alert: true, provisional: true));
    _firebaseMessaging.onIosSettingsRegistered.listen((IosNotificationSettings settings) {
      print('IOS Setting Registed');
    });
  }

  Future<void> _showNotification(Map<String, dynamic> message) async {
    var android = AndroidNotificationDetails(
      'messages',
      "Octopoos",
      "channelDescription",
    );
    var iOS = IOSNotificationDetails();

    await _flutterLocalNotificationsPlugin.show(
      0,
      message['notification']['title'],
      message['notification']['body'],
      NotificationDetails(android, iOS),
    );
  }
}

调用小部件

final FirebaseMessagingService _fcm = FirebaseMessagingService();

  @override
  void afterFirstLayout(BuildContext context) {
    _fcm.initialise();
  }

只有在所有这些步骤之后,我的 FCM 才能正常工作。

对于更新到 iOS14 和 Xcode12 后从 FCM 发疯的每个人。 我花了 2 天时间来解决这些问题。 在模拟器上,它可以工作,但在真实设备上,它没有。 也许这些说明可以帮助某人并防止浪费时间。 此外,如果所有这些步骤都可以改进,那么听取 Flutter Guru 的一些想法会很棒:)。 谢谢!

XCode 设置

在此处输入图片说明

AppDelegate.swift

import UIKit
import Flutter
import GoogleMaps
import Firebase
import FirebaseMessaging

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
    if #available(iOS 10.0, *) {
      UNUserNotificationCenter.current().delegate = self as UNUserNotificationCenterDelegate
    }
    GMSServices.provideAPIKey("")
    GeneratedPluginRegistrant.register(with: self)
    application.registerForRemoteNotifications()
    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }

    override func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        Auth.auth().setAPNSToken(deviceToken, type: .prod)
    }

    override func application(_ application: UIApplication,
        didReceiveRemoteNotification notification: [AnyHashable : Any],
        fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
        if Auth.auth().canHandleNotification(notification) {
          completionHandler(.noData)
          return
        }
    }

    override func application(_ application: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any]) -> Bool {
        if Auth.auth().canHandle(url) {
          return true
        }
        return false;
      }
}

信息表

    <key>FirebaseAppDelegateProxyEnabled</key>
    <false/>
    <key>FirebaseScreenReportingEnabled</key>
    <true/>

消息示例(可调用函数)

您的消息必须使用以下选项发送:

{
   mutableContent: true,
   contentAvailable: true,
   apnsPushType: "background"
}

只是在可调用函数中使用的示例

exports.sendNotification = functions.https.onCall(
    async (data) => {
        console.log(data, "this sendNotification data");
        var userTokens = [USERTOKEN1,USERTOKEN2,USERTOKEN3];
        var payload = {
            notification: {
                title: '',
                body: '',
                image: '',
            },
            data: {
                type:'',
            },
        };
        
        for (const [userToken,userUID] of Object.entries(userTokens)) {
            admin.messaging().sendToDevice(userToken, payload, {
                mutableContent: true,
                contentAvailable: true,
                apnsPushType: "background"
            });
        }
        
        return {code: 100, message: "notifications send successfully"};
    });

Flutter 消息服务

import 'dart:io';
import 'package:hive/hive.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:octopoos/providers/app.dart';

Future<dynamic> backgroundMessageHandler(Map<String, dynamic> message) async {}

class FirebaseMessagingService {
  final _app = AppProvider();
  var _prefs = Hive.box('preferences');
  FirebaseMessaging _firebaseMessaging = FirebaseMessaging();
  FlutterLocalNotificationsPlugin _flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();

  void initialise() {
    var android = AndroidInitializationSettings('mipmap/ic_launcher');
    var ios = IOSInitializationSettings();
    var platform = InitializationSettings(android, ios);
    _flutterLocalNotificationsPlugin.initialize(platform);

    _firebaseMessaging.configure(
      onLaunch: (Map<String, dynamic> message) async {
        _app.storeNotification(message);
      },
      onResume: (Map<String, dynamic> message) async {
        _app.storeNotification(message);
      },
      onMessage: (Map<String, dynamic> message) async {
        _app.storeNotification(message);
        if (_prefs.get('pushServiceState') == true) _showNotification(message);
      },
      onBackgroundMessage: Platform.isIOS ? null : backgroundMessageHandler,
    );

    if (Platform.isIOS) iOSPermission();
    _firebaseMessaging.getToken().then((token) {
      _prefs.put('fcmToken', token);
    });
  }

  void iOSPermission() {
    _firebaseMessaging.requestNotificationPermissions(
        IosNotificationSettings(sound: true, badge: true, alert: true, provisional: true));
    _firebaseMessaging.onIosSettingsRegistered.listen((IosNotificationSettings settings) {
      print('IOS Setting Registed');
    });
  }

  Future<void> _showNotification(Map<String, dynamic> message) async {
    var android = AndroidNotificationDetails(
      'messages',
      "Octopoos",
      "channelDescription",
    );
    var iOS = IOSNotificationDetails();

    await _flutterLocalNotificationsPlugin.show(
      0,
      message['notification']['title'],
      message['notification']['body'],
      NotificationDetails(android, iOS),
    );
  }
}

调用小部件

final FirebaseMessagingService _fcm = FirebaseMessagingService();

  @override
  void afterFirstLayout(BuildContext context) {
    _fcm.initialise();
  }

只有在所有这些步骤之后,我的 FCM 才能正常工作。

如果有效,您可以尝试示例有效负载吗?

在这里说明

let payload = {
        notification: {
            title: 'Match',
            body: `${user2name} Match with You`,

        },
        data: {
            key: 'Match',
            id: user2,
            body: user2name,
            click_action: "FLUTTER_NOTIFICATION_CLICK"
        },
        android: {
            priority: "high",
        },
        apns: {
            payload: {
                aps: {
                    contentAvailable: true,
                },
            },
            headers: {
                "apns-push-type": "background",
                "apns-priority": "5", // Must be `5` when `contentAvailable` is set to true.
                "apns-topic": "io.flutter.plugins.firebase.messaging", // bundle identifier
            },
        },

        token: deviceTokenuUser1.data()['tokens'],
    };

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM