如何在 Xamarin Forms iOS-App 中接收 ASPN 令牌
Posted
技术标签:
【中文标题】如何在 Xamarin Forms iOS-App 中接收 ASPN 令牌【英文标题】:How to receive the ASPN Token in Xamarin Forms iOS-App 【发布时间】:2020-11-04 22:15:23 【问题描述】:我按照this 教程在我的 Xamarin-Forms 应用程序(尤其是 ios 部分)中实现推送通知。现在我的问题是,当我按下注册按钮时,我收到错误消息“无法解析 APNS 的令牌”。 在调试模式下单步执行代码,我可以验证 DeviceInstallationService 中的 Token 属性确实是 null。 所以我往后退了一步,发现 Token 是通过 AppDelegate.cs 中的 RegisteredForRemoteNotification 设置的,但是在我运行 App 的时候从来没有调用过这个方法。
这是一些代码:App-Delegate
using System;
using System.Diagnostics;
using System.Threading.Tasks;
using Foundation;
using Notes.iOS.Extensions;
using Notes.iOS.Services;
using Notes.Services;
using UIKit;
using UserNotifications;
using Xamarin.Essentials;
using System.Collections.Generic;
using System.Linq;
using Syncfusion.SfCalendar.XForms.iOS;
namespace Notes.iOS
[Register("AppDelegate")]
public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate
IPushDemoNotificationActionService _notificationActionService;
INotificationRegistrationService _notificationRegistrationService;
IDeviceInstallationService _deviceInstallationService;
IPushDemoNotificationActionService NotificationActionService
=> _notificationActionService ??
(_notificationActionService =
ServiceContainer.Resolve<IPushDemoNotificationActionService>());
INotificationRegistrationService NotificationRegistrationService
=> _notificationRegistrationService ??
(_notificationRegistrationService =
ServiceContainer.Resolve<INotificationRegistrationService>());
IDeviceInstallationService DeviceInstallationService
=> _deviceInstallationService ??
(_deviceInstallationService =
ServiceContainer.Resolve<IDeviceInstallationService>());
public override bool FinishedLaunching(UIApplication app, NSDictionary options)
global::Xamarin.Forms.Forms.Init();
Bootstrap.Begin(() => new DeviceInstallationService());
if (DeviceInstallationService.NotificationsSupported)
UNUserNotificationCenter.Current.RequestAuthorization(
UNAuthorizationOptions.Alert |
UNAuthorizationOptions.Badge |
UNAuthorizationOptions.Sound,
(approvalGranted, error) =>
if (approvalGranted && error == null)
RegisterForRemoteNotifications();
);
LoadApplication(new App());
using (var userInfo = options?.ObjectForKey(
UIApplication.LaunchOptionsRemoteNotificationKey) as NSDictionary)
ProcessNotificationActions(userInfo);
return base.FinishedLaunching(app, options);
void RegisterForRemoteNotifications()
MainThread.BeginInvokeOnMainThread(() =>
var pushSettings = UIUserNotificationSettings.GetSettingsForTypes(
UIUserNotificationType.Alert |
UIUserNotificationType.Badge |
UIUserNotificationType.Sound,
new NSSet());
UIApplication.SharedApplication.RegisterUserNotificationSettings(pushSettings);
UIApplication.SharedApplication.RegisterForRemoteNotifications();
);
Task CompleteRegistrationAsync(NSData deviceToken)
DeviceInstallationService.Token = deviceToken.ToHexString();
return NotificationRegistrationService.RefreshRegistrationAsync();
void ProcessNotificationActions(NSDictionary userInfo)
if (userInfo == null)
return;
try
var actionValue = userInfo.ObjectForKey(new NSString("action")) as NSString;
if (!string.IsNullOrWhiteSpace(actionValue?.Description))
NotificationActionService.TriggerAction(actionValue.Description);
catch (Exception ex)
Debug.WriteLine(ex.Message);
public override void RegisteredForRemoteNotifications(UIApplication application, NSData deviceToken)
=> CompleteRegistrationAsync(deviceToken).ContinueWith((task)
=> if (task.IsFaulted) throw task.Exception; );
public override void ReceivedRemoteNotification(
UIApplication application,
NSDictionary userInfo)
=> ProcessNotificationActions(userInfo);
public override void FailedToRegisterForRemoteNotifications(
UIApplication application,
NSError error)
=> Debug.WriteLine(error.Description);
DeviceInstallationService:
using System;
using Notes.Models;
using Notes.Services;
using UIKit;
namespace Notes.iOS.Services
public class DeviceInstallationService : IDeviceInstallationService
const int SupportedVersionMajor = 13;
const int SupportedVersionMinor = 0;
public string Token get; set;
public bool NotificationsSupported
=> UIDevice.CurrentDevice.CheckSystemVersion(SupportedVersionMajor, SupportedVersionMinor);
public string GetDeviceId()
=> UIDevice.CurrentDevice.IdentifierForVendor.ToString();
public DeviceInstallation GetDeviceInstallation(params string[] tags)
if (!NotificationsSupported)
throw new Exception(GetNotificationsSupportError());
if (string.IsNullOrWhiteSpace(Token))
throw new Exception("Unable to resolve token for APNS");
var installation = new DeviceInstallation
InstallationId = GetDeviceId(),
Platform = "apns",
PushChannel = Token
;
installation.Tags.AddRange(tags);
return installation;
string GetNotificationsSupportError()
if (!NotificationsSupported)
return $"This app only supports notifications on iOS SupportedVersionMajor.SupportedVersionMinor and above. You are running UIDevice.CurrentDevice.SystemVersion.";
if (Token == null)
return $"This app can support notifications but you must enable this in your settings.";
return "An error occurred preventing the use of push notifications";
如您所见,这实际上是 1:1 的示例代码,唯一的区别是我的项目名为 Notes。
我跳过了 Firebase 和 android 部分,因为到目前为止我只需要 iOS 的推送通知,而且据我所知,这些对于 iOS 来说并不是必需的。
感谢您的帮助!
【问题讨论】:
【参考方案1】:检查RegisteredForRemoteNotification
是否未被调用的几点:
打开Entitlements.plist
并确保在Entitlements
选项卡中查看时选中Enable Push Notifications
。然后,确保在“源”选项卡中查看时 APS 环境设置设置为开发。
确保您在真实设备而不是模拟器中测试远程通知。模拟器不支持远程通知。
确保您同意接收通知权限。
确保您使用的认证已启用推送通知功能。
参考:configuring-the-remote-notifications-environment
【讨论】:
感谢您的帮助!问题是,我在模拟器设备上尝试了该应用程序。使用真实设备修复它。 @SebSeb 你能接受答案吗(点击这个答案左上角的☑️),以便我们可以帮助更多有同样问题的人:)。 这里有同样的问题:模拟器崩溃并出现同样的错误,但真实设备可以工作。但是现在 App Store 团队因为崩溃而拒绝了我们的应用程序。您是如何在商店中获得您的应用程序的?或者有什么方法可以修复注册?【参考方案2】:您可以在您的 App Delegate AppDelegate.cs
中查看以下函数返回的消息
public override void FailedToRegisterForRemoteNotifications(
UIApplication application,
NSError error)
例如
找不到应用程序的有效“aps-environment”权利字符串
【讨论】:
以上是关于如何在 Xamarin Forms iOS-App 中接收 ASPN 令牌的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Xamarin.Forms.Maps(无 Xamarin.Forms.GoogleMaps)在地图中应用样式或更改颜色
在 Xamarin.Forms 中录制语音后如何保存音频文件