首页 > 解决方案 > Xamarin Firebase iOS 未收到 FCM 消息

问题描述

我尝试在我的 Xamarin Forms 应用程序中实现 Firebase 推送通知和消息。在 Android 中它工作正常,而在 iOS 中我收到推送通知,但我没有收到 FCM 仅数据消息。

我正在使用 Xamarin.Firebase.iOS.CloudMessaging 包,我也遵循了这个指南另一个

这是我的 AppDelegate.cs 代码:

[Register("AppDelegate")]
public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate, IUNUserNotificationCenterDelegate, IMessagingDelegate
{
    //
    // This method is invoked when the application has loaded and is ready to run. In this 
    // method you should instantiate the window, load the UI into it and then make the window
    // visible.
    //
    // You have 17 seconds to return from this method, or iOS will terminate your application.
    //
    public override bool FinishedLaunching(UIApplication app, NSDictionary options)
    {
        Forms.SetFlags("Brush_Experimental");
        Rg.Plugins.Popup.Popup.Init();
        //Ascetic.Plugins.PopupDecorations.iOS.PrettyPopup.Init();
        global::Xamarin.Forms.Forms.Init();
        SfListViewRenderer.Init();
        new Syncfusion.SfAutoComplete.XForms.iOS.SfAutoCompleteRenderer();
        Syncfusion.XForms.iOS.TabView.SfTabViewRenderer.Init();
        iOSMaterialFrameRenderer.Init();
        LoadApplication(new App());

        // Register your app for remote notifications.
        configureFirebase();


        var result = base.FinishedLaunching(app, options);
        app.KeyWindow.TintColor = UIColor.White;
        foreach (var fs in UIFont.FamilyNames.OrderBy(c => c).ToList())
        {
            Console.WriteLine(" * " + fs);
            foreach (var f in UIFont.FontNamesForFamilyName(fs).OrderBy(c => c).ToList())
            {
                Console.WriteLine(" *-- " + f);
            }
        }

        return result;
    }

    private void configureFirebase()
    {
        Firebase.Core.App.Configure();
        if (UIDevice.CurrentDevice.CheckSystemVersion(10, 0))
        {
            // For iOS 10 display notification (sent via APNS)
            UNUserNotificationCenter.Current.Delegate = this;

            // iOS 10 or later
            var authOptions = UNAuthorizationOptions.Alert | UNAuthorizationOptions.Badge | UNAuthorizationOptions.Sound;
            UNUserNotificationCenter.Current.RequestAuthorization(authOptions, (granted, error) =>
            {
            });

            // For iOS 10 data message (sent via FCM)
            Messaging.SharedInstance.Delegate = this;
        }
        else
        {
            // iOS 9 or before
            var allNotificationTypes = UIUserNotificationType.Alert | UIUserNotificationType.Badge | UIUserNotificationType.Sound;
            var settings = UIUserNotificationSettings.GetSettingsForTypes(allNotificationTypes, null);
            UIApplication.SharedApplication.RegisterUserNotificationSettings(settings);
        }
        UIApplication.SharedApplication.RegisterForRemoteNotifications();
    }

    //Firebase
    [Export("messaging:didReceiveRegistrationToken:")]
    public void DidReceiveRegistrationToken(Messaging messaging, string fcmToken)
    {
        Preferences.Set("tokenNotifica", fcmToken);
        Console.WriteLine("\nValue: " + (fcmToken));
    }

    //APP IN BACKGROUND
    public override void DidReceiveRemoteNotification(UIApplication application, NSDictionary userInfo, Action<UIBackgroundFetchResult> completionHandler)
    {
        handleNotification(userInfo);
        completionHandler(UIBackgroundFetchResult.NewData);
    }

    [Export("userNotificationCenter:willPresentNotification:withCompletionHandler:")]
    public void WillPresentNotification(UNUserNotificationCenter center, UNNotification notification,
    Action<UNNotificationPresentationOptions> completionHandler)
    {
        handleNotification(notification.Request.Content.UserInfo);
        completionHandler(UNNotificationPresentationOptions.Sound | UNNotificationPresentationOptions.Alert);
    }

    [Export("userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler:")]
    public void DidReceiveNotificationResponse(UNUserNotificationCenter center, UNNotificationResponse response, Action
    completionHandler)
    {
        completionHandler();
        NSDictionary userInfo = response.Notification.Request.Content.UserInfo;
        try
        {
            var Data = userInfo[new NSString("gcm.notification.data")] as NSString;
            if (Data != null && Data != "")
            {
                string[] tokens = Data.ToString().Split(',');
                string Username = tokens[0];
                string Password = tokens[1];
                var Title = string.IsNullOrEmpty(response.Notification.Request.Content.Title) ? "No Notification available" : response.Notification.Request.Content.Title;
                var Body = string.IsNullOrEmpty(response.Notification.Request.Content.Body) ? "No Message available" : response.Notification.Request.Content.Body;
            }
        }
        catch (Exception)
        {

        }
    }

    [Export("messaging:didReceiveMessage:")]
    public void DidReceiveMessage(Messaging messaging, RemoteMessage message)
    {
        handleNotification(message.AppData);
    }

    public override void RegisteredForRemoteNotifications(UIApplication application, NSData deviceToken)
    {
        Messaging.SharedInstance.ApnsToken = deviceToken;
    }

    public void ApplicationReceivedRemoteMessage(RemoteMessage remoteMessage)
    {
        ;
    }
}

使用令牌调用DidReceiveRegistrationToken方法。如果我向该令牌发送通知,则会调用方法 DidReceiveRemoteNotification,并且设备会成功显示通知。但是,如果我向该令牌发送仅数据消息,则不会调用任何内容。

我尝试禁用 swizzling,启用它,从头开始重新配置 Firebase,并在 Apple Dev 网站中删除并重新创建证书和配置文件,但没有任何效果。另外,我认为所有配置都正确,因为我的应用程序正在接收通知。

我希望我提供了足够的信息,我为此苦苦挣扎了好几个星期

编辑

我在 php 中使用此函数将纯数据消息发送到设备

function sendMessage($deviceKey, $data){
    $curl = curl_init();

    curl_setopt($curl, CURLOPT_HTTPHEADER, array(
        "Content-Type: application/json", 
        "project_id: ***",
        "Authorization: key=***"
    ));

    // Set some options - we are passing in a useragent too here
    curl_setopt_array($curl, [
        CURLOPT_URL => 'https://fcm.googleapis.com/fcm/send',
        CURLOPT_RETURNTRANSFER => 1,
        CURLOPT_USERAGENT => 'Codular Sample cURL Request',
        CURLOPT_POST => 1,
    ]);

    $body = [
        'to'  => $deviceKey,
        "data" => $data
    ];

    curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($body));
    $res = json_decode(curl_exec($curl), true);
    curl_close($curl);

    return $res;
}

该函数等同于发送通知的函数,但 $body 数组不包含“通知”键。我想做的是在应用程序中使用消息的数据有效负载而不显示通知,这在 Android 中工作得很好,但在 iOS 中却不行。

标签: iosfirebasexamarinfirebase-cloud-messagingapple-push-notifications

解决方案


推荐阅读