【问题标题】:Xamarin Forms: Have I Covered the bases on iOS Push Notifications?Xamarin Forms:我是否涵盖了 iOS 推送通知的基础?
【发布时间】:2019-10-04 21:51:10
【问题描述】:

问题:3 种不同上下文中的不同行为

好的,好的,在 iOS 中,推送通知似乎会发生三种不同的事情:

  1. 当应用在前台时收到推送通知
    • 通知中心出现了一些东西
    • 如果通过点击通知打开应用程序,会调用AppDelegate.DidReceiveRemoteNotification(...)AppDelegate.ReceivedRemoteNotification(...),显然取决于实现的是哪一个(??)。
    • 如果打开应用程序没有点击通知,只有AppDelegate.WillEnterForeground(...)被调用,没有任何明确提及通知,并且没有别的碰巧承认这一点收到通知。
  2. 当应用程序在前台收到推送通知时,它会导致UNUserNotificationCenterDelegate(如果有)执行UNUserNotificationCenterDelegate.WillPresentNotification(...)。李>

方法:从所有上下文路由到一个方法

因此,要使用 Push 覆盖所有基础,我需要在所有三种方法中实现一些东西:AppDelegate.DidReceiveRemoteNotification(...) / AppDelegate.ReceivedRemoteNotification(...)AppDelegate.WillEnterForeground(...)UNUserNotificationCenterDelegate .WillPresentNotification(...)

这里有一些存根来展示我处理这一切的方法。

首先,我创建了一个自定义UNUserNotificationCenterDelegate,带有一个Shared 静态成员:

public class IncomingNotificationHandler : UNUserNotificationCenterDelegate
{
    public static IncomingNotificationHandler Shared = new IncomingNotificationHandler();

    ...
 }

其次,在该类中,我创建了一个处理程序,在每种情况下我都可以路由到该处理程序(再次强调,这只是一个用于调试目的的存根):

    //sets all parameters to null by default, so it can be called from methods
    //that don't know anything about notifications:

    public void HandleNotificationsIfAny(UIApplication application = null, 
        NSDictionary userInfo = null, 
        Action<UIBackgroundFetchResult> completionHandler = null)
    {
        //checks if userInfo is null, and logs its conclusions about that:

        if (userInfo == null)
        {
            //In the null case, we can get pending notifications from 
            //UNUserNotificationCenter:

            UNNotification[] pendingNotifications = new UNNotification[] { };
            UNUserNotificationCenter.Current.GetDeliveredNotifications(returnedValue => pendingNotifications = returnedValue);

            //Then we log the number of pending notifications:

            Debug.WriteLine("IncomingNotificationHandler: HandleNotificationsIfAny(...): delivered notification count: " + pendingNotifications.Length);

            //And make note of where this was probably called from:

            Debug.WriteLine("IncomingNotificationHandler: HandleNotificationsIfAny(...): may have been called from this.WillPresentNotification(...) OR AppDelegate.WillEnterForeground(...)");
            return;
            });
        }
        else
        {
            //In the non-null case, we log the userInfo

            Debug.WriteLine("IncomingNotificationHandler: HandleNotificationsIfAny(...): just got info: " + userInfo);

            //And make note of where this was probably called from:

            Debug.WriteLine("IncomingNotificationHandler: HandleNotificationsIfAny(...): may have been called from AppDelegate.DidReceiveRemoteNotification(...)");
        }
    }

第三,在同一个类中,我实现了UNUserNotificationCenterDelegate 所需的单个方法,并从中路由到处理程序:

    public override void WillPresentNotification(UNUserNotificationCenter center, UNNotification notification, Action<UNNotificationPresentationOptions> completionHandler)
    {
        HandleNotificationsIfAny();
    }

第四,也是最后,在AppDelegate 中,我从两个相关方法路由到同一个处理程序:

 //I prefer using DidReceiveRemoteNotification because in my experience 
 //the other one is sometimes not reliable:

 public override void DidReceiveRemoteNotification(UIApplication application, 
        NSDictionary userInfo, 
        Action<UIBackgroundFetchResult> completionHandler)
    {              
        //Simply passing on all the parameters called in this method:

         IncomingNotificationHandler.Shared.HandleNotificationsIfAny(application, userInfo, completionHandler);
     }


 //WillEnterForeground also calls the handler without any parameters
 //because it doesn't automatically know anything about notifications:

  public override void WillEnterForeground(UIApplication application)
    {
        IncomingNotificationHandler.Shared.HandleNotificationsIfAny();
    }

就目前而言,我认为我正在以相同的方式处理通知事件,无论我的应用如何收到有关它的警报,即使它根本没有收到警报。

有谁知道我现在是否已经涵盖了它,或者我是否需要处理其他一些情况?

【问题讨论】:

    标签: ios xamarin.forms push-notification


    【解决方案1】:

    对于第一种情况:AppDelegate.ReceivedRemoteNotification

    它反映了客观的 c 方法:application:didReceiveRemoteNotification:,但自 iOS 10 起,此事件已被弃用:https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1623117-application?language=objc。所以我认为没有必要处理这个事件。

    对于第二种情况:AppDelegate.DidReceiveRemoteNotification

    如果您还没有实现UNUserNotificationCenter,您现在仍然可以使用它来处理通知,请注意它仅在iOS 7+ 之后有效。此外,当应用程序在前台时会触发此事件,如果您的应用程序在后台,则仅当用户单击通知打开您的应用程序时才会触发此事件。如果用户单击图标打开应用程序,则无法访问通知信息。

    我不认为处理AppDelegate.WillEnterForeground 是一个好方法,因为每次应用程序从后台恢复到前台时都会调用它,即使没有通知。

    对于场景:UNUserNotificationCenterDelegate

    您只能在 iOS 10 之后使用此功能。一旦您在 iOS 10+ 设备上实现此功能,DidReceiveRemoteNotificationReceivedRemoteNotification 将永远不会被触发。 WillPresentNotification 将在应用程序处于前台时调用。 DidReceiveNotificationResponse 将在应用程序处于后台并且用户单击通知打开它时触发。

    作为结论,如果你想轻松处理通知AppDelegate.DidReceiveRemoteNotification就足够了。如果你想消费UNUserNotificationCenter的新特性,AppDelegate.DidReceiveRemoteNotificationUNUserNotificationCenter应该都参与。前一种适用于 iOS 7+ 设备,后一种适用于 iOS 10+ 设备。

    更新:

    对于 iOS 10+,您可以使用UNUserNotificationCenter.Current.GetDeliveredNotifications 获取仍然显示在通知中心的通知。如果您只想支持 iOS 10 及更高版本。我觉得UNUserNotificationCenter就够了,没必要实现AppDelegate.DidReceiveRemoteNotification(...)或者AppDelegate.ReceivedRemoteNotification(...)

    • 如果应用程序处于后台/已终止状态并且用户单击通知以 打开应用程序,将调用 DidReceiveNotificationResponse。
    • 如果 用户单击图标打开您的应用程序,该应用程序被杀死,您应该 将您的逻辑代码放在FinishedLaunching 中。
    • 如果用户点击图标 打开你的应用程序和应用程序在后台,你可以处理 WillEnterForeground 就像你以前一样。
    • 如果应用程序在前台, 处理WillPresentNotification

    【讨论】:

    • 你似乎知道你的东西,谢谢你的插话。你最后的总结与我的经验相矛盾。我正在实施我概述的方法,它似乎正在工作:当用户点击应用程序外部的通知时,应用程序中会打开相应的窗口;当用户看到通知并在没有点击通知的情况下转到应用程序时,应用程序中会打开相应的窗口;当应用打开并收到通知时,应用中会打开相应的窗口。
    • @LeMotJuiced 啊,这是我的错。我从未使用过此 API,但您似乎是对的。在 iOS 10+ 上,我们可以使用 UNUserNotificationCenter 来获取仍然显示在通知中心的通知。但是,这只能在 iOS 10+ 上实现。如果您的应用程序仅支持 iOS 10+,那么 UNUserNotificationCenter 足以满足您的要求。当应用处于后台状态且用户点击通知打开应用时,将调用DidReceiveNotificationResponse
    猜你喜欢
    • 2016-08-16
    • 1970-01-01
    • 1970-01-01
    • 2017-05-23
    • 1970-01-01
    • 2016-06-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多