【问题标题】:How to implement the CrossPushNotification plugin in Xamarin Forms?如何在 Xamarin Forms 中实现 CrossPushNotification 插件?
【发布时间】: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 中的方法也不是。当我收到权限警报请求时,就会发生注册。这一点让我更加困惑......

标签: c# xamarin push-notification xamarin.ios xamarin.forms


【解决方案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);
        }
    

    【讨论】:

    • 不是这样的。我最终创建了一个与插件具有类似实现的依赖服务,并且有效。谢谢。
    • 是否可以分享您的实现并选择它作为您问题的答案,有兴趣了解您是如何使用依赖服务进行的吗?
    猜你喜欢
    • 1970-01-01
    • 2021-11-05
    • 1970-01-01
    • 1970-01-01
    • 2019-08-26
    • 2017-10-15
    • 1970-01-01
    • 2019-02-24
    • 1970-01-01
    相关资源
    最近更新 更多