【发布时间】:2018-11-14 00:16:58
【问题描述】:
如果应用程序在后台,我设法使用didReceiveRemoteNotification 方法处理推送通知。如果应用程序处于前台且未关闭,是否有办法处理推送通知?谢谢
【问题讨论】:
-
在这里查看我最近回答的答案:stackoverflow.com/a/50255637/1134836
标签: c# push-notification xamarin.ios
如果应用程序在后台,我设法使用didReceiveRemoteNotification 方法处理推送通知。如果应用程序处于前台且未关闭,是否有办法处理推送通知?谢谢
【问题讨论】:
标签: c# push-notification xamarin.ios
我通过下面显示的示例 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
{ [注册("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
}
}
【讨论】:
无论应用程序在前台还是后台运行,都可以处理推送通知事件。按照这些步骤获取 DidReceiveRemoteNotification 总是被调用
1) 重写 AppDelegate.cs 中的 DidReceiveRemoteNotification 方法
public override void DidReceiveRemoteNotification(UIApplication application, NSDictionary userInfo, Action<UIBackgroundFetchResult> completionHandler)
2) 在 info.plist 中添加所需的后台模式 - remote-notification(value)
3) 将有效负载中的内容可用设置为 1
{
"aps" : {
"alert" : {
"title" : "Game Request",
"body" : "Bob wants to play poker"
},
"badge" : 5,
"content-available" : 1
}
}
【讨论】:
你实现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() 方法,当我添加它们时,我遇到了同样的问题。
DidReceiveRemoteNotification 和 ReceivedRemoteNotification 事件。 ReceivedRemoteNotification 永远不会被解雇,阅读 documentation 你会发现这个 api 在 ios 10+ 上被弃用了。
DidReceiveRemoteNotification 仅当应用程序在后台时.. 我不确定我在做什么这里不见了。
AppDelegate 中的覆盖方法ReceivedRemoteNotification 或DidReceiveRemoteNotification,当您在前台收到推送通知时将被触发。
通过这种方法,您可以检查您的应用是否处于Active 状态,并根据它来处理您的通知。
if (UIApplication.SharedApplication.ApplicationState == UIApplicationState.Active)
{
//You app is in Foreground state.
//Process the Pushnotification data, or show alert.
}
实施 应用程序(:didReceiveRemoteNotification:fetchCompletionHandler:) 尽可能使用这种方法而不是这种方法。如果你的代表 实现了这两种方法,应用程序对象调用 应用程序(: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<UIBackgroundFetchResult> completionHandler) { var value = userInfo; } 第二个方法在后台应用时正确调用,第一个根本不会触发。