Xamarin.iOS如何在应用程序未关闭时处理推送通知

3

我已经成功处理了后台应用程序的推送通知,使用了方法didReceiveRemoteNotification。如果应用程序在前台而不关闭,有没有一种方法来处理推送通知?谢谢


请查看我最近在这里回答的答案:https://stackoverflow.com/a/50255637/1134836 - valdetero
4个回答

3

你是否已经实现了UserNotification?如果你在iOS 10+上部署你的项目,可以尝试在FinishedLaunching(UIApplication application, NSDictionary launchOptions)中订阅通知,例如:

if (UIDevice.CurrentDevice.CheckSystemVersion(10, 0))
{
    var authOptions = UNAuthorizationOptions.Alert | UNAuthorizationOptions.Badge | UNAuthorizationOptions.Sound;
    UNUserNotificationCenter.Current.RequestAuthorization(authOptions, (granted, error) => {
        Console.WriteLine(granted);
    });
    UNUserNotificationCenter.Current.Delegate = new MyNotificationCenterDelegate();
}

当通知到来且应用在前台运行时,WillPresentNotification() 将触发,此事件处理程序返回通知到来时此应用将响应的操作。最后,您可以在 DidReceiveNotificationResponse() 事件中获取 userInfo:

public class MyNotificationCenterDelegate : UNUserNotificationCenterDelegate
{
    public override void DidReceiveNotificationResponse(UNUserNotificationCenter center, UNNotificationResponse response, Action completionHandler)
    {
        completionHandler();
    }

    public override void WillPresentNotification(UNUserNotificationCenter center, UNNotification notification, Action<UNNotificationPresentationOptions> completionHandler)
    {
        completionHandler(UNNotificationPresentationOptions.Sound | UNNotificationPresentationOptions.Alert);

    }       
}

但是如果您不想实现UserNotification或者只是推送一个带有键content-available为true的静默远程通知,在应用程序前台时,didReceiveRemoteNotification()也会被触发。


我已经订阅了通知,但是我找不到 WillPresentNotification() 方法,当我添加它们时遇到了同样的问题。 - Seif Selmi
我将弱引用的代理修改为强引用的代理。如果您同时订阅了 DidReceiveRemoteNotificationReceivedRemoteNotification 事件,那么 ReceivedRemoteNotification 将永远不会被触发。请阅读文档,您会发现这个 API 在 iOS 10+ 上已经被弃用。 - Ax1le
仍然存在同样的问题,接收通知并不会触发那些方法,唯一触发的方法是 DidReceiveRemoteNotification,只有当应用程序在后台运行时才会触发.. 我不确定我错过了什么。 - Seif Selmi
很奇怪。你使用了哪个第三方库和哪个iOS版本? - Ax1le
iOS 11.2并且不使用第三方库进行通知。 - Seif Selmi

1

处理推送通知事件,无论应用程序在前台还是后台运行。按照以下步骤始终调用DidReceiveRemoteNotification。

1)在AppDelegate.cs中重写DidReceiveRemoteNotification方法。

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

2) 添加所需的后台模式 - 将 remote-notification(value) 添加到 info.plist 中

3) 在有效载荷中将 content-available 设置为 1

{
"aps" : {
    "alert" : {
        "title" : "Game Request",
        "body" : "Bob wants to play poker"
    },
    "badge" : 5,
    "content-available" : 1
}

}


0

AppDelegate中,重写方法ReceivedRemoteNotificationDidReceiveRemoteNotification,当您处于前台接收推送通知时,该方法将被触发。

在此方法中,您可以检查您的应用程序是否处于Active状态,并根据此处理您的通知。

if (UIApplication.SharedApplication.ApplicationState == UIApplicationState.Active) 
{
    //You app is in Foreground state.
    //Process the Pushnotification data, or show alert.
}

Apple文档

尽可能实现应用程序(:didReceiveRemoteNotification:fetchCompletionHandler:)方法,而不是这个方法。如果您的委托实现了两种方法,则应用程序对象调用application(:didReceiveRemoteNotification:fetchCompletionHandler:)方法。

因此,如果您在AppDelegate中实现了两种方法(ReceivedRemoteNotification和DidReceiveRemoteNotification),那么将调用DidReceiveRemoteNotification方法。


遗憾的是,当我在前台收到通知时,“ReceivedRemoteNotification”没有触发。这是我的代码:public override void ReceivedRemoteNotification(UIApplication application, NSDictionary userInfo) { var userInfo1 = userInfo; } public override void DidReceiveRemoteNotification(UIApplication application, NSDictionary userInfo, Action completionHandler) { var value = userInfo; }第二个方法在后台调用时正确调用,但第一个方法根本不触发。 - Seif Selmi
是的,我已经添加了检查应用状态的条件,但仍然没有成功。 - Seif Selmi
它是否应该放在那个if块里面?当您的应用程序在前台时,苹果不会在任何地方显示推送通知。您必须手动处理它,例如在此条件下从应用程序中显示警报。您认为,在应用程序处于前台时,应该采取什么措施? - MilanG
你可以尝试使用 "if (application.ApplicationState == UIApplicationState.Active)" 而不是 UIApplication.SharedApplication.ApplicationState。 - MilanG
抱歉,但这是同样的问题,除非应用程序关闭并重新打开,否则不会进入该块或检查。 - Seif Selmi
显示剩余3条评论

0
我通过下面的示例app.delegte.cs代码在Xamarin iOS中获得了前台和后台通知。
   using Foundation;
   using System;
   using System.Diagnostics;
   using System.Linq;
   using UIKit;
   using UserNotifications;
   using WindowsAzure.Messaging;
   using Firebase.Core;
   using Firebase.CloudMessaging;
   using System.Runtime.CompilerServices;
   using ObjCRuntime;

   namespace NotificationHubSample.iOS

{ [Register("AppDelegate")]

   public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate
{
    private SBNotificationHub Hub { get; set; }
    

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

        

        base.FinishedLaunching(app, options);

        Firebase.Core.App.Configure();

        RegisterForRemoteNotifications();

        UIApplication.SharedApplication.SetMinimumBackgroundFetchInterval(UIApplication.BackgroundFetchIntervalMinimum);


        return true;
    }

    void RegisterForRemoteNotifications()
    {
        // register for remote notifications based on system version
        if (UIDevice.CurrentDevice.CheckSystemVersion(10, 0))
        {
            
            

            UNUserNotificationCenter.Current.RequestAuthorization(UNAuthorizationOptions.Alert |
                UNAuthorizationOptions.Sound |
                UNAuthorizationOptions.Sound,
                (granted, error) =>
                {
                    if (granted)
                        InvokeOnMainThread(UIApplication.SharedApplication.RegisterForRemoteNotifications);
                });
        }
        else if (UIDevice.CurrentDevice.CheckSystemVersion(8, 0))
        {
            var pushSettings = UIUserNotificationSettings.GetSettingsForTypes(
            UIUserNotificationType.Alert | UIUserNotificationType.Badge | UIUserNotificationType.Sound,
            new NSSet());

            UIApplication.SharedApplication.RegisterUserNotificationSettings(pushSettings);
            UIApplication.SharedApplication.RegisterForRemoteNotifications();
        }
        else
        {
            UIRemoteNotificationType notificationTypes = UIRemoteNotificationType.Alert | UIRemoteNotificationType.Badge | UIRemoteNotificationType.Sound;
            UIApplication.SharedApplication.RegisterForRemoteNotificationTypes(notificationTypes);
        }
        UIApplication.SharedApplication.RegisterForRemoteNotifications();
    }

    public override void RegisteredForRemoteNotifications(UIApplication application, NSData deviceToken)
    {
        Hub = new SBNotificationHub(AppConstants.ListenConnectionString, AppConstants.NotificationHubName);

        // update registration with Azure Notification Hub
        Hub.UnregisterAll(deviceToken, (error) =>
        {
            if (error != null)
            {
                Debug.WriteLine($"Unable to call unregister {error}");
                return;
            }

            var tags = new NSSet(AppConstants.SubscriptionTags.ToArray());
            Hub.RegisterNative(deviceToken, tags, (errorCallback) =>
            {
                if (errorCallback != null)
                {
                    Debug.WriteLine($"RegisterNativeAsync error: {errorCallback}");
                }
            });

            var templateExpiration = DateTime.Now.AddDays(120).ToString(System.Globalization.CultureInfo.CreateSpecificCulture("en-US"));
            Hub.RegisterTemplate(deviceToken, "defaultTemplate", AppConstants.APNTemplateBody, templateExpiration, tags, (errorCallback) =>
            {
                if (errorCallback != null)
                {
                    if (errorCallback != null)
                    {
                        Debug.WriteLine($"RegisterTemplateAsync error: {errorCallback}");
                    }
                }
            });
        });

        // Firebase ios Registration
        Messaging.SharedInstance.ApnsToken = deviceToken;
        
       }
   // Process the notification when the app is open.
   
public override void ReceivedRemoteNotification(UIApplication application, NSDictionary userInfo)
    {
        ProcessNotification(userInfo, false);
        

    }   // End of the ReceiveRemoteNotification method

    

    // Process the notification when the app is closed.
    public override void DidReceiveRemoteNotification(UIApplication application, NSDictionary userInfo, Action<UIBackgroundFetchResult> completionHandler)
    {
        ProcessNotification(userInfo, false);            
        
    }


    void ProcessNotification(NSDictionary options, bool fromFinishedLaunching)
    {
        // make sure we have a payload
        if (options != null && options.ContainsKey(new NSString("aps")))
        {
            // get the APS dictionary and extract message payload. Message JSON will be converted
            // into a NSDictionary so more complex payloads may require more processing
            NSDictionary aps = options.ObjectForKey(new NSString("aps")) as NSDictionary;
            
            string payload = string.Empty;
            NSString payloadKey = new NSString("alert");
            
            if (aps.ContainsKey(payloadKey))
            {
                payload = aps[payloadKey].ToString();
            }

          
            
            if (!string.IsNullOrWhiteSpace(payload))
            {
                (App.Current.MainPage as MainPage)?.AddMessage(payload);
            }

        }
        else
        {
            Debug.WriteLine($"Received request to process notification but there was no payload.");
        } 
     } // End of the ProcessNotification method





}

}


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接