首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >iOS 14+上的Flutter FCM 9+

iOS 14+上的Flutter FCM 9+
EN

Stack Overflow用户
提问于 2021-10-09 07:49:05
回答 1查看 214关注 0票数 0

如何在IOS版本14+上实现FCM 9+?

EN

Stack Overflow用户

回答已采纳

发布于 2021-10-09 08:07:22

我之前关于Flutter FCM 7 implementation的回答很有帮助,所以我决定为新的FCM 9+版本编写相同的说明,并在几分钟内展示如何在我们的Flutter应用程序中实现流畅的消息传递。

迁移到空安全和FCM版本9+ (IOS 14+)情况后,看起来也不会更好。我们得到了相同的问题,但在一个新的包装器中:). 

下面描述的指令可以帮助实现FCM 9+,并提供一些代码示例。也许这些指令可以帮助某些人,防止浪费时间。

XCode设置

AppDelegate.swift

代码语言:javascript
运行
复制
import UIKit
import Flutter
import Firebase
import FirebaseMessaging

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

    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }
}

Info.plist

代码语言:javascript
运行
复制
<key>FirebaseAppDelegateProxyEnabled</key>
<false/>
<key>FirebaseScreenReportingEnabled</key>
<true/>

消息示例(可调用函数)

您的邮件必须使用以下选项发送:

代码语言:javascript
运行
复制
{
   mutableContent: true,
   contentAvailable: true,
   apnsPushType: "background"
}

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

代码语言:javascript
运行
复制
exports.sendNotification = functions.https.onCall(
    async (data) => {
        console.log(data, "send notification");
        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"};
    });

颤动消息服务

代码语言:javascript
运行
复制
import 'dart:convert' as convert;
import 'dart:io' show Platform;

import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter_app_badger/flutter_app_badger.dart';
import 'package:octopoos/entities/notification.dart';
import 'package:flutter/foundation.dart';
import 'package:hive/hive.dart';
import 'package:uuid/uuid.dart';

class MessagingService {
  final Box prefs = Hive.box('preferences');
  final FirebaseMessaging fcm = FirebaseMessaging.instance;
  static final instance = MessagingService._();

  bool debug = true;

  /// Private Singleton Instance
  MessagingService._();

  /// Set FCM Presentation Options
  Future<void> setPresentationOptions() async {
    await FirebaseMessaging.instance.setForegroundNotificationPresentationOptions(
      alert: true,
      badge: true,
      sound: true,
    );
  }

  /// Check PUSH permissions for IOS
  Future<bool> requestPermission({bool withDebug = true}) async {
    NotificationSettings settings = await fcm.requestPermission(
      alert: true,
      announcement: false,
      badge: true,
      carPlay: false,
      criticalAlert: false,
      provisional: false,
      sound: true,
    );

    // if (withDebug) debugPrint('[ FCM ] Push: ${settings.authorizationStatus}');
    bool authorized = settings.authorizationStatus == AuthorizationStatus.authorized;
    return (Platform.isIOS && authorized || Platform.isAndroid) ? true : false;
  }

  /// Initialize FCM stream service
  Future<void> initializeFcm() async {
    final String? currentToken = await fcm.getToken();
    final String storedToken = prefs.get('fcmToken', defaultValue: '');

    /// Refresh Device token & resubscribe topics
    if (currentToken != null && currentToken != storedToken) {
      prefs.put('fcmToken', currentToken);
      /// resubscribeTopics();
    }

    if (debug) {
      debugPrint('[ FCM ] token: $currentToken');
      debugPrint('[ FCM ] service initialized');
    }
  }

  /// Store messages to Hive Storage 
  void store(RemoteMessage message) async {
    final FirebaseAuth auth = FirebaseAuth.instance;
    final Map options = message.data['options'] != null && message.data['options'].runtimeType == String
        ? convert.json.decode(message.data['options'])
        : message.data['options'];

    final AppNotification notificationData = AppNotification(
      id: const Uuid().v4(),
      title: message.data['title'] ?? '',
      body: message.data['body'] ?? '',
      image: message.data['image'] ?? '',
      type: message.data['type'] ?? 'notification',
      options: options,
      createdAt: DateTime.now().toString(),
    );

    late Box storage;
    switch (message.data['type']) {
      default:
        storage = Hive.box('notifications');
        break;
    }

    try {
      String id = const Uuid().v4();
      storage.put(id, notificationData.toMap());
      updateAppBadge(id);

      if (debug) debugPrint('Document $id created');
    } catch (error) {
      if (debug) debugPrint('Something wrong! $error');
    }
  }

  /// Update app badge
  Future<void> updateAppBadge(String id) async {
    final bool badgeIsAvailable = await FlutterAppBadger.isAppBadgeSupported();

    if (badgeIsAvailable && id.isNotEmpty) {
      final int count = Hive.box('preferences').get('badgeCount', defaultValue: 0) + 1;
      Hive.box('preferences').put('badgeCount', count);
      FlutterAppBadger.updateBadgeCount(count);
    }
  }

  /// Subscribe topic
  Future<void> subscribeTopic({required String name}) async {
    await fcm.subscribeToTopic(name);
  }

  /// Unsubscribe topic
  Future<void> unsubscribeTopic({required String name}) async {
    await fcm.unsubscribeFromTopic(name);
  }

  /// Resubscribe to topics
  Future<int> resubscribeTopics() async {
    final List topics = prefs.get('topics', defaultValue: []);
    if (topics.isNotEmpty) {
      for (String topic in topics) {
        subscribeTopic(name: topic);
      }
    }

    return topics.length;
  }
}

AppNotification模型

代码语言:javascript
运行
复制
class AppNotification {
  String id;
  String title;
  String body;
  String image;
  String type;
  Map options;
  String createdAt;

  AppNotification({
    this.id = '',
    this.title = '',
    this.body = '',
    this.image = '',
    this.type = 'notification',
    this.options = const {},
    this.createdAt = '',

  });

  AppNotification.fromMap(Map snapshot, this.id)
      : title = snapshot['title'],
        body = snapshot['body'],
        image = snapshot['image'],
        type = snapshot['type'] ?? 'notification',
        options = snapshot['options'] ?? {},
        createdAt = (DateTime.parse(snapshot['createdAt'])).toString();

  Map<String, dynamic> toMap() => {
        "id": id,
        "title": title,
        "body": body,
        "image": image,       
        "type": type,
        "options": options,
        "createdAt": createdAt,
      };
}

main.dart

代码语言:javascript
运行
复制
import 'dart:async';

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:hive/hive.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:provider/provider.dart';
import 'package:octopoos/services/messaging.dart';
import 'package:timezone/data/latest.dart' as tz;

Future<void> fcm(RemoteMessage message) async {
    MessagingService.instance.store(message);

 /// Show foreground Push notification
 /// !!! Flutter Local Notification Plugin REQUIRED
 await notificationsPlugin.show(
      0,
      message.data['title'],
      message.data['body'],
      NotificationDetails(android: androidChannelSpecifics, iOS: iOSChannelSpecifics),
    );
}

Future<void> main() async {
  /// Init TimeZone
  tz.initializeTimeZones();

  /// Init Firebase Core Application
  await Firebase.initializeApp();

  /// FCM Permissions & Background Handler
  MessagingService.instance.setPresentationOptions();
  FirebaseMessaging.onBackgroundMessage(fcm);
  
  runApp(
    MultiProvider(
      providers: kAppProviders,
      child: App(),
    ),
  );
}

app.dart

代码语言:javascript
运行
复制
  @override
  void initState() {
    super.initState();
    initFcmListeners();
  }

  Future<void> initFcmListeners() async {
    MessagingService.instance.initializeFcm();
    FirebaseMessaging.instance.getInitialMessage().then((message) {
      if (message != null) _handleMessage(message);
    });

    FirebaseMessaging.onMessage.listen(_handleMessage);
    FirebaseMessaging.onMessageOpenedApp.listen(_handleMessage);
  }

  void _handleMessage(RemoteMessage message) {
   MessagingService.instance.store(message);
  }

就这样。别忘了在真正的IOS设备上测试。FCM在IOS模拟器上不起作用。

票数 3
EN
查看全部 1 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69504770

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档