如何在 Xamarin Forms 中实现 CrossPushNotification 插件?

Posted

技术标签:

【中文标题】如何在 Xamarin Forms 中实现 CrossPushNotification 插件?【英文标题】:How to implement the CrossPushNotification plugin in Xamarin Forms? 【发布时间】:2017-02-16 10:57:02 【问题描述】:

我在CrossPushNotificationListener 类中实现了IPushNotificationListener。正如README 文件中所建议的那样。

public class CrossPushNotificationListener : IPushNotificationListener

    void IPushNotificationListener.OnError(string message, DeviceType deviceType)
    
        Application.Current.MainPage.DisplayAlert("error", message, "ok");
    

    void IPushNotificationListener.OnMessage(JObject values, DeviceType deviceType)
    
        Application.Current.MainPage.DisplayAlert("message", values.ToString(), "ok");
    

    void IPushNotificationListener.OnRegistered(string token, DeviceType deviceType)
    
        Application.Current.MainPage.DisplayAlert("token", token, "ok");
    

    void IPushNotificationListener.OnUnregistered(DeviceType deviceType)
    
        Application.Current.MainPage.DisplayAlert("unregistered", "", "ok");
    

    bool IPushNotificationListener.ShouldShowNotification()
    
        Application.Current.MainPage.DisplayAlert("should show notification", "", "ok");
        return true;
    

然后在 ios 的 AppDelegate 中初始化 CrossPushNotification 插件。

public override bool FinishedLaunching(UIApplication app, NSDictionary options)

    global::Xamarin.Forms.Forms.Init ();

    CrossPushNotification.Initialize<CrossPushNotificationListener>();

    LoadApplication(new Origination.App ());
    return base.FinishedLaunching(app, options);

我还使用适当的覆盖扩展了 AppDelegate,如 PushNotificationApplicationDelegate.txt.pp 文件中所示:

public override void FailedToRegisterForRemoteNotifications(UIApplication application, NSError error)

    if (CrossPushNotification.Current is IPushNotificationHandler)
    
        ((IPushNotificationHandler)CrossPushNotification.Current).OnErrorReceived(error);
    


public override void RegisteredForRemoteNotifications(UIApplication application, NSData deviceToken)

    if (CrossPushNotification.Current is IPushNotificationHandler)
    
        ((IPushNotificationHandler)CrossPushNotification.Current).OnRegisteredSuccess(deviceToken);
    



public override void DidReceiveRemoteNotification(UIApplication application, NSDictionary userInfo, Action<UIBackgroundFetchResult> completionHandler)

    if (CrossPushNotification.Current is IPushNotificationHandler)
    
        ((IPushNotificationHandler)CrossPushNotification.Current).OnMessageReceived(userInfo);
    



public override void ReceivedRemoteNotification(UIApplication application, NSDictionary userInfo)

    if (CrossPushNotification.Current is IPushNotificationHandler)
    
        ((IPushNotificationHandler)CrossPushNotification.Current).OnMessageReceived(userInfo);
    

然后,在我的共享代码中,用户注册/登录应用程序并进入其主屏幕后,我调用:

CrossPushNotification.Current.Register();

我知道正在执行此方法,因为我收到了请求权限的警报。但是在CrossPushNotificationListener 中实现的IPushNotificationListener 接口中的任何方法都没有被调用。

我在这里错过了什么?

谢谢。

【问题讨论】:

您使用什么服务来发送推送通知?您应该首先检查设备是否已正确注册,并且推送通知已发送到 Apple Push Notification 服务。 CrossPushNotificationListener 中的方法永远不会被调用,所以我没有得到设备令牌。 AppDelegate 中的方法也不是。当我收到权限警报请求时,就会发生注册。这一点让我更加困惑...... 【参考方案1】:

使用 DependencyService 的自定义实现。此代码基于Xam.Plugin.PushNotification插件提供的解决方案。

共享项目

接口

public interface INotificationListener

    void OnRegister(string deviceToken);
    void OnMessage(JObject values);


public interface INotificationService

    string Token  get; 
    void Register();

实施

public class NotificationListener : INotificationListener

    public void OnMessage(JObject values)
    
        // TOOD: - Handle incoming notifications
    

    public async void OnRegister(string deviceToken)
    
        // TODO: - Register the devices token in the server
    


public class NotificationManager


    private static NotificationManager _current = null;

    /// <summary>
    /// Shared instance of the Notification Manager
    /// </summary>
    public static NotificationManager Current
    
        get
        
            if (_current == null)
            
                _current = new NotificationManager();
            
            return _current;
        
    

    /// <summary>
    /// The member responsible for handling notifications
    /// </summary>
    public static INotificationListener Listener  get; private set; 

    /// <summary>
    /// Initializes the Notification Manager with an instance of the specified handler in type T
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public static void Initialize<T>() where T: INotificationListener, new()
    
        Listener = new T();
    


在适当的时候调用它来向用户请求权限

DependencyService.Get<INotificationService>().Register();

IOS 项目

[assembly: Xamarin.Forms.Dependency(typeof (NotificationService))]
namespace App.iOS.Notifications

    public class NotificationService : INotificationService
    

        public string Token
        
            get
            
                return NSUserDefaults.StandardUserDefaults.StringForKey(NotificationKeys.TokenKey);
            

        

        public void Register()
        
            if (UIDevice.CurrentDevice.CheckSystemVersion(8, 0))
            
                UIUserNotificationType notificationTypes = UIUserNotificationType.Alert | UIUserNotificationType.Badge | UIUserNotificationType.Sound;
                var settings = UIUserNotificationSettings.GetSettingsForTypes(notificationTypes, new NSSet());
                UIApplication.SharedApplication.RegisterUserNotificationSettings(settings);
                UIApplication.SharedApplication.RegisterForRemoteNotifications();
            
            else
            
                UIRemoteNotificationType notificationTypes = UIRemoteNotificationType.Alert | UIRemoteNotificationType.Badge | UIRemoteNotificationType.Sound;
                UIApplication.SharedApplication.RegisterForRemoteNotificationTypes(notificationTypes);
            
        

    


应用代理

public override bool FinishedLaunching(UIApplication app, NSDictionary options)

    LoadApplication(new Origination.App ());
    NotificationManager.Initialize<NotificationListener>();
    return base.FinishedLaunching(app, options);


public override void RegisteredForRemoteNotifications(UIApplication application, NSData deviceToken)

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

    // Get previous device token
    var oldDeviceToken = NSUserDefaults.StandardUserDefaults.StringForKey(NotificationKeys.TokenKey);

    // Has the token changed?
    if (string.IsNullOrEmpty(oldDeviceToken) || !oldDeviceToken.Equals(DeviceToken))
    
        NotificationManager.Listener.OnRegister(DeviceToken);
    

    // Save new device token 
    NSUserDefaults.StandardUserDefaults.SetString(DeviceToken, NotificationKeys.TokenKey);
    NSUserDefaults.StandardUserDefaults.Synchronize();



public override void DidReceiveRemoteNotification(UIApplication application, NSDictionary userInfo, Action<UIBackgroundFetchResult> completionHandler)

    HandleNotification(userInfo);


public override void ReceivedRemoteNotification(UIApplication application, NSDictionary userInfo)

    HandleNotification(userInfo);


#region Handle Notification

private static string DictionaryToJson(NSDictionary dictionary)

    NSError error;
    var json = NSJsonSerialization.Serialize(dictionary, NSJsonWritingOptions.PrettyPrinted, out error);
    return json.ToString(NSStringEncoding.UTF8);


public void HandleNotification(NSDictionary userInfo)

    var parameters = new Dictionary<string, object>();
    var json = DictionaryToJson(userInfo);
    JObject values = JObject.Parse(json);

    var keyAps = new NSString("aps");

    if (userInfo.ContainsKey(keyAps))
    
        NSDictionary aps = userInfo.ValueForKey(keyAps) as NSDictionary;

        if (aps != null)
        
            foreach (var apsKey in aps)
            
                parameters.Add(apsKey.Key.ToString(), apsKey.Value);
                JToken temp;
                if (!values.TryGetValue(apsKey.Key.ToString(), out temp))
                    values.Add(apsKey.Key.ToString(), apsKey.Value.ToString());
            
        
    

    NotificationManager.Listener.OnMessage(values);


#endregion

【讨论】:

【参考方案2】:

在 iOS 上你必须尝试调用:

CrossPushNotification.Initialize<CrossPushNotificationListener>();

之后

LoadApplication(new Origination.App ());

像这样:

        public override bool FinishedLaunching(UIApplication app, NSDictionary options)
    
        global::Xamarin.Forms.Forms.Init();

        LoadApplication(new App());

        CrossPushNotification.Initialize<CrossPushNotificationListener>();
        return base.FinishedLaunching(app, options);
    

【讨论】:

不是这样的。我最终创建了一个与插件具有类似实现的依赖服务,并且有效。谢谢。 是否可以分享您的实现并选择它作为您问题的答案,有兴趣了解您是如何使用依赖服务进行的吗?

以上是关于如何在 Xamarin Forms 中实现 CrossPushNotification 插件?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Xamarin Forms App 中实现 SSO?

如何在 Xamarin Forms 中实现标记聚类(谷歌地图)

无法在 Xamarin.Forms 中实现导航

如何使用 Visual Studio for Mac 在 Xamarin.Forms 中实现多目标?

如何在 Xamarin.Forms for android / ios 中实现特定布局

使用 Prism 在 Xamarin Forms 的后台服务中实现依赖注入