ios didReceiveRemoteNotification 在后台不起作用
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/31450403/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
didReceiveRemoteNotification not working in the background
提问by YogevSitton
I'm working on a big app with a huge chunk of legacy code. Currently - there's an implementation for:
我正在开发一个包含大量遗留代码的大型应用程序。目前 - 有一个实现:
- (void) application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
The problem is that it is only called when the app is in the foreground OR when the user taps the the notification while the app is in the background. I tried to implement:
问题是它仅在应用程序处于前台或用户在应用程序处于后台时点击通知时调用。我试图实现:
- (void) application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
But the app behaves the same. In any case - this method is not called when the app is in the background. What could be the problem?
但该应用程序的行为相同。无论如何 - 当应用程序在后台时不会调用此方法。可能是什么问题呢?
回答by Baris Akar
Implementing didReceiveRemoteNotification
and didReceiveRemoteNotification:fetchCompletionHandler
is the correct way, but you also need to do the following:
实现didReceiveRemoteNotification
anddidReceiveRemoteNotification:fetchCompletionHandler
是正确的方法,但是你还需要做以下几点:
Make sure to register for remote notifications, see documentation here:
确保注册远程通知,请参阅此处的文档:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound)];
return YES;
}
Also make sure to edit Info.plist
and check the "Enable Background Modes" and "Remote notifications" check boxes:
还要确保编辑Info.plist
并选中“启用后台模式”和“远程通知”复选框:
Additionally, you need to add "content-available":1
to your push notification payload, otherwise the app won't be woken if it's in the background (see documentation hereupdated):
此外,您需要添加"content-available":1
到您的推送通知有效负载中,否则应用程序在后台不会被唤醒(请参阅此处更新的文档):
For a push notification to trigger a download operation, the notification's payload must include the content-available key with its value set to 1. When that key is present, the system wakes the app in the background (or launches it into the background) and calls the app delegate's application:didReceiveRemoteNotification:fetchCompletionHandler: method. Your implementation of that method should download the relevant content and integrate it into your app
对于触发下载操作的推送通知,通知的有效负载必须包含 content-available 键,其值设置为 1。当该键存在时,系统会在后台唤醒应用程序(或将其启动到后台)和调用应用程序委托的 application:didReceiveRemoteNotification:fetchCompletionHandler: 方法。您对该方法的实现应下载相关内容并将其集成到您的应用程序中
So payload should at least look like this:
所以有效载荷至少应该是这样的:
{
aps = {
"content-available" : 1,
sound : ""
};
}
回答by Mahadev Mandale
- Register for push notification in app delegate.
- Add background mode in app capabilities.
- Add "content-available"="1" while sending the push notification(if you are using firebase replace "content-available"="1" by "content_available"="true" while sending the push notification from server side).
- 在应用程序委托中注册推送通知。
- 在应用程序功能中添加后台模式。
- 在发送推送通知时添加“content-available”=“1”(如果您正在使用 firebase,则在从服务器端发送推送通知时将“content-available”=“1”替换为“content_available”=“true”)。
回答by ZaEeM ZaFaR
I had the same problem. Notification banner appeared, but -application:didReceiveRemoteNotification:fetchCompletionHandler: method was not called. The solution for me that worked was to add implementation of - application:didReceiveRemoteNotification: method and forward call to -application:didReceiveRemoteNotification:fetchCompletionHandler::
我有同样的问题。出现通知横幅,但未调用 -application:didReceiveRemoteNotification:fetchCompletionHandler: 方法。对我来说有效的解决方案是添加 - application:didReceiveRemoteNotification: 方法的实现并将调用转发到 -application:didReceiveRemoteNotification:fetchCompletionHandler::
func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) {
self.application(application, didReceiveRemoteNotification: userInfo) { (UIBackgroundFetchResult) in
}
}
回答by AndyW58
I am creating an iOS project that will use Firebase Cloud Messaging (FCM) to deliver custom data elements, sent via Firebase/APNS notifications, from a company server to the iOS device.
我正在创建一个 iOS 项目,该项目将使用 Firebase 云消息传递 (FCM) 来提供自定义数据元素,通过 Firebase/APNS 通知发送,从公司服务器到 iOS 设备。
The first thing I had to understand is that unlike Android, there is no similar type of 'Service' that will be able to capture and save information I'm sending, regardless if the app is in the foreground (active), background (still in memory) or not active (not in memory). Therefore, I have to use Notification messages NOT Data messages like I had designed for Android.
我必须了解的第一件事是,与 Android 不同,没有类似类型的“服务”能够捕获和保存我发送的信息,无论应用程序是否处于前台(活动)、后台(仍然在内存中)或不活动(不在内存中)。因此,我必须像我为 Android 设计的那样使用通知消息而不是数据消息。
After much reading to understand both Apple APNS and the Firebase interface between the iOS app and APNS server, looking at countless posts on stackoverflow and other web resources, I finally figured out how to get this to work for my requirements.
经过大量阅读以了解 iOS 应用程序和 APNS 服务器之间的 Apple APNS 和 Firebase 接口,查看了关于 stackoverflow 和其他网络资源的无数帖子,我终于找到了如何让它满足我的要求。
When a Firebase Cloud Messaging (FCM) Notification message is sent from the server (or Firebase Console as the FCM defaults to Notification NOT Data messages), it is delivered via APNS and presented as a notification on the iOS device. When the user taps on the notification banner, iOS does the following: if the app is not running/loaded iOS launches the app, if the app is loaded/running but in the background iOS brings the app to the foreground OR if the app is in the foreground (all three cases), the message content is then delivered via func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) {}.
当 Firebase Cloud Messaging (FCM) 通知消息从服务器(或 Firebase 控制台,因为 FCM 默认为 Notification NOT Data 消息)发送时,它会通过 APNS 传送并在 iOS 设备上作为通知显示。当用户点击通知横幅时,iOS 会执行以下操作:如果应用程序未运行/加载 iOS 启动应用程序,如果应用程序已加载/正在运行但在后台 iOS 将应用程序带到前台或如果应用程序在前台(所有三种情况),然后通过 func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) {} 传递消息内容。
One thing for sure, you Must Enable Background Modes and check Remote Notification, you DO NOT have to include {"content-available" : 1} in the payload.
可以肯定的是,您必须启用后台模式并检查远程通知,您不必在有效负载中包含 {"content-available" : 1}。
1) Go through the APNS and Firebase setup, pretty straight forward, generate and register certificates and such.
1)通过APNS和Firebase设置,非常简单,生成和注册证书等。
2) In appDelegate, didFinishLaunchingWithOptions, add:
2) 在 appDelegate, didFinishLaunchingWithOptions 中,添加:
Messaging.messaging().delegate = self as? MessagingDelegate
if #available(iOS 10.0, *) {
UNUserNotificationCenter.current().delegate = self
let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
UNUserNotificationCenter.current().requestAuthorization(
options: authOptions,
completionHandler: {_, _ in })
}
else {
let settings: UIUserNotificationSettings =
UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
application.registerUserNotificationSettings(settings)
}
application.registerForRemoteNotifications()
3) Then add these call back functions to appDelegate:
3)然后将这些回调函数添加到appDelegate:
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) {
// Print message ID.
if let messageID = userInfo["gcm.message_id"] {
print("\n*** application - didReceiveRemoteNotification - fetchCompletionHandler - Message ID: \(messageID)")
}
// Print full message.
print("\n*** application - didReceiveRemoteNotification - full message - fetchCompletionHandler, userInfo: \(userInfo)")
myNotificationService?.processMessage(title: userInfo["Title"] as! String
, text: userInfo["Text"] as! String, completion: { (success) in
if success {
completionHandler(.newData)
}
else {
completionHandler(.noData)
}
})
}
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
completionHandler([.alert, .badge, .sound])
}
Very Helpful:
很有帮助:
https://firebase.googleblog.com/2017/01/debugging-firebase-cloud-messaging-on.html
https://firebase.googleblog.com/2017/01/debugging-firebase-cloud-messaging-on.html