【问题标题】:Xamarin Forms: Push notification is not receiving to ios deviceXamarin Forms:推送通知未接收到 ios 设备
【发布时间】:2019-06-25 04:37:17
【问题描述】:

我做了以下事情:

  1. 在 FCM 控制台中创建了一个项目并将 ios 项目添加到其中。
  2. 下载GoogleService-Info.plist并将其添加到xamarin forms ios项目目录并将构建操作设置为Bundlesource
  3. 在 Info.plist 上启用远程通知后台模式。
  4. 在应用的 Info.plist 文件中添加了 FirebaseAppDelegateProxyEnabled 并将其设置为否。
  5. 创建了配置文件和分发证书并将其安装到钥匙串访问中。此外,将这些证书映射到项目选项中。
  6. 在 FCM 控制台中上传了 .p12 证书。
  7. AppDelegate.cs 中添加了处理推送通知的代码。

我的代码:

    [Register("AppDelegate")]
    public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate, IUNUserNotificationCenterDelegate
    {
        public override bool FinishedLaunching(UIApplication app, NSDictionary options)
        {
            global::Xamarin.Forms.Forms.Init();
            LoadApplication(new App("",""));
            RequestPushPermissionsAsync();
            _launchoptions = options;
            // Register your app for remote notifications.
        if (UIDevice.CurrentDevice.CheckSystemVersion(10, 0))
        {
            // iOS 10 or later
            var authOptions = UNAuthorizationOptions.Alert | UNAuthorizationOptions.Badge | UNAuthorizationOptions.Sound;
            UNUserNotificationCenter.Current.RequestAuthorization(authOptions, (granted, error) => {
                Console.WriteLine(granted);
            });

            // For iOS 10 display notification (sent via APNS)
            UNUserNotificationCenter.Current.Delegate = this;

            // For iOS 10 data message (sent via FCM)
            //Messaging.SharedInstance.RemoteMessageDelegate = 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();
            return base.FinishedLaunching(app, options);
        }
        NSDictionary _launchoptions;
        public override void OnActivated(UIApplication uiApplication)
        {
            base.OnActivated(uiApplication);
            if (_launchoptions != null && _launchoptions.ContainsKey(UIApplication.LaunchOptionsRemoteNotificationKey))
            {
                var notfication = _launchoptions[UIApplication.LaunchOptionsRemoteNotificationKey] as NSDictionary;
                PresentNotification(notfication);
            }
            _launchoptions = null;
        }

        async Task RequestPushPermissionsAsync()
        {
            var requestResult = await UNUserNotificationCenter.Current.RequestAuthorizationAsync(
                 UNAuthorizationOptions.Alert
                | UNAuthorizationOptions.Badge
                | UNAuthorizationOptions.Sound);

            bool approved = requestResult.Item1;
            NSError error = requestResult.Item2;
            if (error == null)
            {
                if (!approved)
                {
                    Console.Write("Permission to receive notification was not granted");
                    return;
                }

                var currentSettings = await UNUserNotificationCenter.Current.GetNotificationSettingsAsync();
                if (currentSettings.AuthorizationStatus != UNAuthorizationStatus.Authorized)
                {
                    Console.WriteLine("Permissions were requested in the past but have been revoked (-Settings  app)");
                    return;
                }
                UIApplication.SharedApplication.RegisterForRemoteNotifications();
            }
            else
            {
                Console.Write($"Error requesting permissions: {error}.");
            }
        }

        public async override void RegisteredForRemoteNotifications(
        UIApplication application, NSData deviceToken)
    {
        //if (deviceToken == null)
        //{
        //    // Can happen in rare conditions e.g. after restoring a device.
        //    return;
        //}

        //Console.WriteLine($"Token received: {deviceToken}");

        // Get current device token
        var DeviceToken = deviceToken.Description;
        if (!string.IsNullOrWhiteSpace(DeviceToken))
        {
            DeviceToken = DeviceToken.Trim('<').Trim('>');
        }

        Console.WriteLine($"deviceToken received: {deviceToken}");
        Console.WriteLine($"DeviceToken received: {DeviceToken}");

        // Get previous device token
        var oldDeviceToken = NSUserDefaults.StandardUserDefaults.StringForKey("PushDeviceToken");

        // Has the token changed?
        if (string.IsNullOrEmpty(oldDeviceToken) || !oldDeviceToken.Equals(DeviceToken))
        {
            //TODO: Put your own logic here to notify your server that the device token has changed/been created!
        }

        // Save new device token
        NSUserDefaults.StandardUserDefaults.SetString(DeviceToken, "PushDeviceToken");

        await SendRegistrationToServerAsync(DeviceToken);
    }

        async Task SendRegistrationTokenToMainPRoject(NSData deviceToken)
        {
            MessagingCenter.Send<object, string>(this, "fcmtoken", deviceToken.ToString());
        }

        public override void FailedToRegisterForRemoteNotifications(UIApplication application, NSError error)
        {
            Console.WriteLine($"Failed to register for remote notifications: {error.Description}");
        }

        public override void DidReceiveRemoteNotification(UIApplication application, NSDictionary userInfo,
            Action<UIBackgroundFetchResult> completionHandler)
        {
            PresentNotification(userInfo);
            completionHandler(UIBackgroundFetchResult.NoData);
            try
            {
                UIApplication.SharedApplication.ApplicationIconBadgeNumber = 0;
                NSDictionary aps = userInfo.ObjectForKey(new NSString("aps")) as NSDictionary;
                var message = (aps[new NSString("webContentList")] as NSString).ToString();
                LoadApplication(new App("", message));
            }
            catch (Exception ex)
            {
                //LogInfo.ReportErrorInfo(ex.Message, ex.StackTrace, "AppDelegate-DidReceiveRemoteNotification");
            }
        }

        void PresentNotification(NSDictionary userInfo)
        {
            NSDictionary aps = userInfo.ObjectForKey(new NSString("aps")) as NSDictionary;

            var msg = string.Empty;

            if (aps.ContainsKey(new NSString("alert")))
            {
                msg = (aps[new NSString("alert")] as NSString).ToString();
            }
            if (string.IsNullOrEmpty(msg))
            {
                msg = "(unable to parse)";
            }
            MessagingCenter.Send<object, string>(this, App.NotificationReceivedKey, msg);
        }
    }

我没有在 ios 部分使用任何 NuGet 包。将项目运行到设备中时,FCM 令牌生成部分正在工作,我可以在 VS 控制台上看到 fcm 令牌。我试图从邮递员向设备发送测试通知,但收到InvalidRegistration 错误。

邮递员回复

{
    "multicast_id": 8754155136812875313,
    "success": 0,
    "failure": 1,
    "canonical_ids": 0,
    "results": [
        {
            "error": "InvalidRegistration"
        }
    ]
}

邮递员身体

 {
    "to" : "d20ad003 7473bfba 85dffc33 1534decf b4b886f1 c738878f fd7f2c60 d9dabc36",
 "collapse_key" : "type_a",
 "data" : {
     "body" : "Body of Your Notification in Data",
     "title": "Title of Your Notification in Title",
     "key_1" : "Value for key_1",
     "key_2" : "Value for key_2"
 },
 "notification" : {
     "body" : "Body of Your Notification",
     "title": "Title of Your Notification",
     "sound": "default",
     "content_available" : true
 }
}

我已经完成了 android 部分的实现,并且在从邮递员推送时收到通知。但是在 ios 部分出现 InvalidRegistration 错误并且在我的 ios 设备中没有收到任何通知。

我关注this youtube 视频进行此实现,完整源代码为here

任何人都建议解决此问题。

提前致谢。

更新

我创建了一个示例项目和一个邮递员集合并将其添加到我的google folder

Postman 集合包含 2 个 REST API,一个用于 Android 设备,另一个用于 ios 设备

如果您导入邮递员集合并运行 Android REST API,我将收到通知,因为我已在其上添加了我的设备 FCM 令牌。但是在 postman 中运行 ios REST API 时会在 postman 中返回 InvalidRegistration 错误。

请通过示例项目,请给我一个解决方案?

【问题讨论】:

  • 我之前没用过FCM,但不知道你是否需要在AppDelegate.cs中为firebase做任何初始化?像这样的东西:FCM.iOS
  • @JackHua-MSFT 我关注this youtube 视频来实现这个实现,完整的源代码是here
  • @JackHua-MSFT 我没有在 ios 部分使用任何 nuget 包,并且在视频中他没有讲述 firebase 的初始化。github.com/Krumelur/XamUAzureNotificationHub/blob/master/…
  • @JackHua-MSFT 我已经用一个示例项目更新了这个问题,你能看看吗?
  • 好的,我去看看。

标签: xamarin.forms xamarin.ios firebase-cloud-messaging


【解决方案1】:

我已审核并可以解决此问题。

  1. 在 iOS 项目中安装插件 Xamarin.Firebase.iOS.CloudMessaging。
  2. AppDelegate 类需要继承 IUNUserNotificationCenterDelegate 和 IMessagingDelegate 接口。
  3. 包含 Firebase.Core.App.Configure ();在注册远程通知之前在 FinishedLaunching 方法中。
  4. 然后您可以添加注册远程通知代码(您可以从给定的链接获取代码)。
  5. 您需要设置用户通知委托和消息共享即时委托(UNUserNotificationCenter.Current.Delegate = this; // 对于 iOS 10 显示通知(通过 APNS 发送)和 Messaging.SharedInstance.Delegate = this;)。
  6. 包含具有相应属性的 DidReceiveRegistrationToken 和 DidReceiveMessage 方法

请参考这个 AppDelegate 类以获得更清晰的信息https://github.com/xamarin/GoogleApisForiOSComponents/blob/master/Firebase.CloudMessaging/samples/CloudMessagingSample/CloudMessagingSample/AppDelegate.cs

相关 Xamarin 论坛主题 https://forums.xamarin.com/discussion/159477/xamarin-forms-push-notification-is-not-receiving-to-ios-device#latest

【讨论】:

    猜你喜欢
    • 2017-05-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-03
    • 2015-02-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多