在检索发件人 ID 的 FCM 令牌之前未设置 Firebase APNS 设备令牌 - Flutter iOS

Firebase APNS device token not set before retrieving FCM Token for Sender ID - Flutter iOS

提问人:Subhangi Pawar 提问时间:1/18/2022 最后编辑:Subhangi Pawar 更新时间:4/21/2023 访问量:13162

问:

在 iOS 中使用 flutter+firebase 时没有收到通知 使用 connectycube_sdk 2.0.9 进行通话和聊天功能。

在控制台中,警告如下 -

[FlutterVoipPushNotificationPlugin] voip注册

8.10.0 - [Firebase/Messaging][I-FCM002022] 在检索发件人 ID 为“445223936748”的 FCM 令牌之前未设置 APNS 设备令牌。 此 FCM 令牌的通知不会通过 APNS.Be 发送 确保在设置 APNS 设备令牌后重新检索 FCM 令牌。

[FlutterVoipPushNotificationPlugin] didUpdatePushCredentials credentials.token = {长度 = 32,字节 = 0xc42015a5 2ba37137 7af02cb4 E389522D ...d93f5c94 6ce6f0b4 },类型 = PKPushTypeVoIP

[FlutterVoipPushNotification插件] handleRemoteNotificationsRegistered notification.userInfo = { deviceToken = c42015a52ba371377af02cb4e389522d8104a7a603d15418d93f5c946ce6f0b4;}

[FlutterVoipPushNotificationPlugin] didUpdatePushCredentials credentials.token = {长度 = 32,字节 = 0xc42015a5 2ba37137 7af02cb4 E389522D ...d93f5c94 6ce6f0b4 },类型 = PKPushTypeVoIP

[FlutterVoipPushNotification插件] handleRemoteNotificationsRegistered notification.userInfo = { deviceToken = c42015a52ba371377af02cb4e389522d8104a7a603d15418d93f5c946ce6f0b4;}

在 firebase 控制台中添加了 .p8 和 .p12(生产 APNs 证书) AppDelegate 文件 -

import UIKit
import Flutter
import Firebase
import PushKit
import CallKit
import flutter_voip_push_notification
import flutter_call_kit

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate, PKPushRegistryDelegate {
  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
    FirebaseApp.configure()
    GeneratedPluginRegistrant.register(with: self)
    self.voipRegistration()
    if #available(iOS 10.0, *) {
      UNUserNotificationCenter.current().delegate = self as? UNUserNotificationCenterDelegate
    }
     application.registerForRemoteNotifications()
    if #available(iOS 10.0, *) {
      UNUserNotificationCenter.current().delegate = self as? UNUserNotificationCenterDelegate
        let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
          UNUserNotificationCenter.current().requestAuthorization(
            options: authOptions,
            completionHandler: { _, _ in }
          )
    } else {
        let settings: UIUserNotificationSettings =
          UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
        application.registerUserNotificationSettings(settings)
      }
      application.registerForRemoteNotifications()
    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }

   // Handle incoming pushes
    public func pushRegistry(_ registry: PKPushRegistry,
                             didReceiveIncomingPushWith payload: PKPushPayload,
                             for type: PKPushType,
                             completion: @escaping () -> Swift.Void){
        print("didReceiveIncomingPushWith")
        
        FlutterVoipPushNotificationPlugin.didReceiveIncomingPush(with: payload, forType: type.rawValue)
        
        let signalType = payload.dictionaryPayload["signal_type"] as! String
        if(signalType == "endCall" || signalType == "rejectCall"){
            return
        }
        
        let uuid = payload.dictionaryPayload["session_id"] as! String
        let uID = payload.dictionaryPayload["caller_id"] as! Int
        let callerName = payload.dictionaryPayload["caller_name"] as! String
        let isVideo = payload.dictionaryPayload["call_type"] as! Int == 1;
        FlutterCallKitPlugin.reportNewIncomingCall(
            uuid,
            handle: String(uID),
            handleType: "generic",
            hasVideo: isVideo,
            localizedCallerName: callerName,
            fromPushKit: true
        )
        completion()
    }
    
    // Handle updated push credentials
    public func pushRegistry(_ registry: PKPushRegistry, didUpdate pushCredentials: PKPushCredentials, for type: PKPushType) {
        // Process the received pushCredentials
        FlutterVoipPushNotificationPlugin.didUpdate(pushCredentials, forType: type.rawValue);
    }
    
    // Register for VoIP notifications
    func voipRegistration(){
        // Create a push registry object
        let voipRegistry: PKPushRegistry = PKPushRegistry(queue: DispatchQueue.main)
        // Set the registry's delegate to self
        voipRegistry.delegate = self
        // Set the push type to VoIP
        voipRegistry.desiredPushTypes = [PKPushType.voIP]
    }
    
}

在 main_dev.dart 文件中

Future<void> main() async {

  PrintLog.printLog("ROOT WIDGET ");
  await runZonedGuarded(() async {
    WidgetsFlutterBinding.ensureInitialized();
    SystemChrome.setPreferredOrientations([
      DeviceOrientation.portraitUp,
    ]);

    await Firebase.initializeApp();
    await FirebaseCrashlytics.instance.setCrashlyticsCollectionEnabled(true);
    PushNotificationsManager.instance.init();
   
    FlutterError.onError = FirebaseCrashlytics.instance.recordFlutterError;

    NavigatorKey.notifyLaunch = await NavigatorKey.flutterLocalNotificationsPlugin.getNotificationAppLaunchDetails();

    await SharedPref.getInstance();
    HttpOverrides.global = MyHttpOverrides();
    FlavorConfig(
      variables: {
        "env": "dev",
        "baseUrl": "https://humanquestapi.demo.brainvire.dev/api/",
        "version": "v1/",
      },
    );
    Bloc.observer = HomeBlocObserver();
    runApp(const MyApp());
  }, (error, stackTrace) {
    FirebaseCrashlytics.instance.recordError(error, stackTrace);
  });
}

在 PushNotificationManager.dart 文件中

class PushNotificationsManager {
  static const TAG = "PushNotificationsManager";

  static final PushNotificationsManager _instance =
      PushNotificationsManager._internal();

  late FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin;

  PushNotificationsManager._internal() {
    Firebase.initializeApp();
    flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
  }
  final FlutterVoipPushNotification _voipPush = FlutterVoipPushNotification();

  BuildContext? applicationContext;

  static PushNotificationsManager get instance => _instance;

  Future<dynamic> Function(String? payload)? onNotificationClicked;

  init() async {
    FirebaseMessaging firebaseMessaging = FirebaseMessaging.instance;

    await firebaseMessaging.requestPermission(
      alert: true,
      announcement: false,
      badge: true,
      carPlay: false,
      criticalAlert: false,
      provisional: false,
      sound: true,
    );

    const AndroidInitializationSettings initializationSettingsAndroid =
        AndroidInitializationSettings('ic_launcher_foreground');
    final IOSInitializationSettings initializationSettingsIOS =
        IOSInitializationSettings(
      requestSoundPermission: true,
      requestBadgePermission: true,
      requestAlertPermission: true,
      onDidReceiveLocalNotification: onDidReceiveLocalNotification,
    );

    final InitializationSettings initializationSettings =
        InitializationSettings(
            android: initializationSettingsAndroid,
            iOS: initializationSettingsIOS);
    await flutterLocalNotificationsPlugin.initialize(initializationSettings,
        onSelectNotification: onSelectNotification);

    String? token;
    if (Platform.isAndroid) {
      firebaseMessaging.getToken().then((token) {
        log('[getToken] token: $token', TAG);
        subscribe(token);
      }).catchError((onError) {
        log('[getToken] onError: $onError', TAG);
      });
    } else if (Platform.isIOS) {
      token = await firebaseMessaging.getAPNSToken();
      log(
        '[getToken] token: $token',
      );
      _initIosVoIP();
    }

    if (!isEmpty(token)) {
      subscribe(token);
    }

    firebaseMessaging.onTokenRefresh.listen((newToken) {
      subscribe(newToken);
    });

    FirebaseMessaging.onMessage.listen((remoteMessage) {
      PrintLog.printLog('[onMessage] message: $remoteMessage');
      // showNotification(remoteMessage);
      if (remoteMessage.data.isNotEmpty &&
          remoteMessage.data[PARAM_SIGNAL_TYPE] != null &&
          remoteMessage.data[PARAM_CALL_TYPE] != null) {
        processCallNotification(remoteMessage.data);
      } else if (remoteMessage.data.isNotEmpty &&
          remoteMessage.data["message"] != null) {
        showNotification(remoteMessage);
      } else {
        remoteMessage.data.putIfAbsent("message", () => "Notification");
        showNotification(remoteMessage);
      }
    });

    FirebaseMessaging.onBackgroundMessage(onBackgroundMessage);

    FirebaseMessaging.onMessageOpenedApp.listen((remoteMessage) {
      PrintLog.printLog('[onMessageOpenedApp] remoteMessage: $remoteMessage');
      if (onNotificationClicked != null) {
        onNotificationClicked!.call(jsonEncode(remoteMessage.data));
      }
    });
  }

  _initIosVoIP() async {
    await _voipPush.requestNotificationPermissions();
    _voipPush.configure(onMessage: onMessage, onResume: onResume);

    _voipPush.onTokenRefresh.listen((token) {
      log('[onTokenRefresh] VoIP token: $token', TAG);
      subscribe(token);
    });

    _voipPush.getToken().then((token) {
      log('[getToken] VoIP token: $token', TAG);
      if (token != null) {
        subscribe(token);
      }
    });
  }

  Future<dynamic> onDidReceiveLocalNotification(
      int id, String? title, String? body, String? payload) {
    log('[onDidReceiveLocalNotification] id: $id , title: $title, body: $body, payload: $payload',
        PushNotificationsManager.TAG);
    return Future.value();
  }

  Future<dynamic> onSelectNotification(String? payload) {
    log('[onSelectNotification] payload: $payload',
        PushNotificationsManager.TAG);
    if (onNotificationClicked != null) {
      onNotificationClicked!.call(payload);
    }
    return Future.value();
  }
}

我们从 await firebaseMessaging.getAPNSToken() 获取的令牌;无效。邮递员的 PFA

enter image description here

Xcode 的 PFA -enter image description here

在android中收到通知,但在iOS中未收到通知。如何在 flutter 中获取适当的设备令牌以获取推送通知。

提前致谢!!

iOS Firebase Flutter firebase-cloud-messaging apple-push-notifications

评论


答:

1赞 Hardik Mehta 1/18/2022 #1

为什么需要 APNToken for fcm?

在这里,您可以从 FCM 获取令牌,您将收到推送。

FirebaseMessaging.getToken().then((token) async {
      print('Token: $token');
    }).catchError((e) {
      print(e);
    });

    FirebaseMessaging.onTokenRefresh.listen((newToken) async {
      // Save newToken
      print('Token: $newToken');
    
    });

你可以尝试使用此令牌,希望这对你有所帮助。对于iOS,请签入真实设备。

0赞 Valentyn Tereshchenko 1/18/2022 #2

Connectycube 推送通知功能通过 APNS 而不是 FCM 工作。预计您无法向 APNS 接收器发送 FCM 推送通知。

首先,检查您的用户是否在Connectycube管理面板中订阅了?然后尝试从 Connectycube 管理面板发送推送通知并检查已发送通知的队列。如果您的推送通知存在,请单击链接检查报告(您将同时有两行)。您可以在其中下载包含报告的详细 JSON。sent