Subhangi Pawar
Subhangi Pawar

Reputation: 499

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

Not getting notification in iOS using flutter+firebase Using connectycube_sdk 2.0.9 for calling and chat functionality.

In console getting below warning -

[FlutterVoipPushNotificationPlugin] voipRegistration

8.10.0 - [Firebase/Messaging][I-FCM002022] APNS device token not set before retrieving FCM Token for Sender ID '445223936748'. Notifications to this FCM Token will not be delivered over APNS.Be sure to re-retrieve the FCM token once the APNS device token is set.

[FlutterVoipPushNotificationPlugin] didUpdatePushCredentials credentials.token = {length = 32, bytes = 0xc42015a5 2ba37137 7af02cb4 e389522d ... d93f5c94 6ce6f0b4 }, type = PKPushTypeVoIP

[FlutterVoipPushNotificationPlugin] handleRemoteNotificationsRegistered notification.userInfo = { deviceToken = c42015a52ba371377af02cb4e389522d8104a7a603d15418d93f5c946ce6f0b4; }

[FlutterVoipPushNotificationPlugin] didUpdatePushCredentials credentials.token = {length = 32, bytes = 0xc42015a5 2ba37137 7af02cb4 e389522d ... d93f5c94 6ce6f0b4 }, type = PKPushTypeVoIP

[FlutterVoipPushNotificationPlugin] handleRemoteNotificationsRegistered notification.userInfo = { deviceToken = c42015a52ba371377af02cb4e389522d8104a7a603d15418d93f5c946ce6f0b4; }

Added .p8 and .p12(Production APNs certificate) in firebase console AppDelegate file -

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]
    }
    
}

In main_dev.dart file

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);
  });
}

In PushNotificationManager.dart file

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();
  }
}

The token we are getting from await firebaseMessaging.getAPNSToken(); is not valid. PFA of Postman

enter image description here

PFA of Xcode - enter image description here

In android receiving notification but in iOS not receiving notification. How to get proper device token in flutter to get push notification.

Thanks in advance.!!!

Upvotes: 3

Views: 14082

Answers (2)

Valentyn Tereshchenko
Valentyn Tereshchenko

Reputation: 636

The Connectycube push notification feature works via APNS not via FCM. It is expected that you can't send an FCM push notification to the APNS receivers.

First of all, check does your user has a subscription in the Connectycube admin panel? Then try to send push notification from the Connectycube admin panel and check the queue of sent notifications. If your push notification is present there check the reports (you will have two rows at the same time) by clicking on the sent link. There you can download the detailed JSON with the report.

Upvotes: 0

Hardik Mehta
Hardik Mehta

Reputation: 2425

Why you need APNToken for fcm ?

here you can get token from fcm and you will receive push.

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

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

You can try by using this token hope this will help you. For iOS , Please check in real device.

Upvotes: 1

Related Questions