iOS 推送通知:如何在应用程序处于后台时检测用户是否点击了通知?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/32061897/
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
iOS push notification: how to detect if the user tapped on notification when the app is in background?
提问by Bao Lei
There are a lot of stackoverflow threads regarding this topic, but I still didn't find a good solution.
有很多关于这个主题的 stackoverflow 线程,但我仍然没有找到一个好的解决方案。
If the app is not in the background, I can check launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey]
in application:didFinishLaunchingWithOptions:
call to see if it's opened from a notification.
如果应用程序是不是在后台,我可以检查launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey]
在application:didFinishLaunchingWithOptions:
通话,看它是否是从一个通知打开。
If the app is in the background, all the posts suggest to use application:didReceiveRemoteNotification:
and check the application state. But as I experimented (and also as the name of this API suggests), this method gets called when the notification is received, instead of tapped.
如果应用程序在后台,所有帖子都建议使用application:didReceiveRemoteNotification:
并检查应用程序状态。但正如我所试验的(也正如这个 API 的名称所暗示的那样),这个方法在收到通知时被调用,而不是被点击。
So the problem is, if the app is launched and then backgrounded, and you know a notification is received from application:didReceiveNotification
(application:didFinishLaunchWithOptions:
won't trigger at this point), how do you know if user resumed the app from by tapping the notification or just tapping the app icon? Because if the user tapped the notification, the expectation is to open the page mentioned in that notification. Otherwise it shouldn't.
所以问题是,如果应用程序启动然后后台运行,并且您知道从application:didReceiveNotification
(此时application:didFinishLaunchWithOptions:
不会触发)收到通知,您如何知道用户是通过点击通知还是点击应用程序图标?因为如果用户点击通知,则期望打开该通知中提到的页面。否则不应该。
I could use handleActionWithIdentifier
for custom action notifications, but this only gets triggered when a custom action button is tapped, not when the user taps on the main body of the notification.
我可以handleActionWithIdentifier
用于自定义操作通知,但这只会在点击自定义操作按钮时触发,而不是在用户点击通知主体时触发。
Thanks.
谢谢。
EDIT:
编辑:
after reading one answer below, I thought in this way I can clarify my question:
阅读下面的一个答案后,我想通过这种方式可以澄清我的问题:
How can we differentiate these 2 scenarios:
我们如何区分这两种情况:
(A) 1.app goes to background; 2.notification received; 3. user taps on the notification; 4. app enters foreground
(A) 1.app进入后台;2.收到通知;3. 用户点击通知;4.应用进入前台
(B) 1.app goes to background; 2.notification received; 3. user ignores the notification and taps on the app icon later; 4. app enters foreground
(B) 1.app进入后台;2.收到通知;3. 用户忽略通知,稍后点击应用图标;4.应用进入前台
Since application:didReceiveRemoteNotification:
is triggered in both cases at step 2.
因为application:didReceiveRemoteNotification:
在步骤 2 的两种情况下都被触发。
Or, should application:didReceiveRemoteNotification:
be triggered in step 3 for (A) only, but I somehow configured my app wrong so I'm seeing it at step 2?
或者,应该application:didReceiveRemoteNotification:
仅在 (A) 的步骤 3 中触发,但我不知何故配置了我的应用程序错误,所以我在步骤 2 中看到它?
采纳答案by Bao Lei
OK I finally figured out.
好吧我终于想通了。
In the target settings ? Capabilities tab ? Background Modes, if you check "Remote Notifications", application:didReceiveRemoteNotification:
will get triggered as soon as notification arrives (as long as the app is in the background), and in that case there is no way to tell whether the user will tap on the notification.
在目标设置中?功能选项卡 ? 后台模式,如果你勾选“远程通知”,application:didReceiveRemoteNotification:
会在通知到达时立即触发(只要应用程序在后台),在这种情况下,无法判断用户是否会点击通知。
If you uncheck that box, application:didReceiveRemoteNotification:
will be triggered only when you tap on the notification.
如果您取消选中该框,application:didReceiveRemoteNotification:
则只有在您点击通知时才会触发。
It's a little strange that checking this box will change how one of the app delegate methods behaves. It would be nicer if that box is checked, Apple uses two different delegate methods for notification receive and notification tap. I think most of the developers always want to know if a notification is tapped on or not.
有点奇怪的是,选中此框将更改应用程序委托方法之一的行为方式。如果选中该框会更好,Apple 使用两种不同的委托方法来接收通知和点击通知。我认为大多数开发人员总是想知道是否点击了通知。
Hopefully this will be helpful for anyone else who run into this issue. Apple also didn't document it clearly hereso it took me a while to figure out.
回答by Dennism
I've been looking for the same thing as you and actually found a solution that does not require remote notification to be ticked off.
我一直在寻找与您相同的东西,实际上找到了一个不需要勾选远程通知的解决方案。
To check whether user has tapped, or app is in background or is active, you just have to check the application state in
要检查用户是否已点击,或者应用程序是否在后台或处于活动状态,您只需检查应用程序状态
-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler{
if(application.applicationState == UIApplicationStateActive) {
//app is currently active, can update badges count here
}else if(application.applicationState == UIApplicationStateBackground){
//app is in background, if content-available key of your notification is set to 1, poll to your backend to retrieve data and update your interface here
}else if(application.applicationState == UIApplicationStateInactive){
//app is transitioning from background to foreground (user taps notification), do what you need when user taps here
}
For more info check:
欲了解更多信息,请检查:
UIKit Framework Reference > UIApplication Class Reference > UIApplicationState
回答by Werner Kratochwil
According to iOS / XCode: how to know that app has been launched with a click on notification or on springboard app icon?you have to check for the application state in didReceiveLocalNotification like this:
根据 iOS / XCode:如何通过单击通知或跳板应用程序图标来知道该应用程序已启动?您必须像这样在 didReceiveLocalNotification 中检查应用程序状态:
if ([UIApplication sharedApplication].applicationState == UIApplicationStateInactive)
{
// user has tapped notification
}
else
{
// user opened app from app icon
}
Although it does not make totally sense to me, it seems to work.
虽然它对我来说并不完全有意义,但它似乎有效。
回答by Hamid Shahsavari
If somebody wants it in swift 3.0
如果有人想要 swift 3.0
switch application.applicationState {
case .active:
//app is currently active, can update badges count here
break
case .inactive:
//app is transitioning from background to foreground (user taps notification), do what you need when user taps here
break
case .background:
//app is in background, if content-available key of your notification is set to 1, poll to your backend to retrieve data and update your interface here
break
default:
break
}
for swift 4
快速 4
switch UIApplication.shared.applicationState {
case .active:
//app is currently active, can update badges count here
break
case .inactive:
//app is transitioning from background to foreground (user taps notification), do what you need when user taps here
break
case .background:
//app is in background, if content-available key of your notification is set to 1, poll to your backend to retrieve data and update your interface here
break
default:
break
}
回答by Aleks Osipov
If you have "Background Modes" > "Remote notifications" checked == YES, tap on notification event will arrive in:
如果您已选中“后台模式”>“远程通知”== 是,则点击通知事件将到达:
-(void)userNotificationCenter:(UNUserNotificationCenter *)center **didReceiveNotificationResponse**:(UNNotificationResponse *)response withCompletionHandler:(void(^)())completionHandler.
It helped me. Please enjoy :)
它帮助了我。请享受 :)
回答by pre
I ran into this problem, too — but on iOS 11 with the new UserNotifications
Framework.
我也遇到了这个问题——但在带有新UserNotifications
框架的iOS 11 上。
Here for me it is like this:
对我来说,它是这样的:
- New Launch:
application:didFinishLaunchingWithOptions:
- Received from a terminate state:
application(_:didReceiveRemoteNotification:fetchCompletionHandler:)
- Received in Foreground:
userNotificationCenter(_:willPresent:withCompletionHandler:)
- Received in Background:
userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler:
- 新推出:
application:didFinishLaunchingWithOptions:
- 从终止状态接收:
application(_:didReceiveRemoteNotification:fetchCompletionHandler:)
- 在前台接收:
userNotificationCenter(_:willPresent:withCompletionHandler:)
- 在后台接收:
userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler:
回答by DoruChidean
In my case, background mode OFF did not make any difference. However when the app was suspended and the user tapped the notification, I could handle the case in this callback method:
就我而言,后台模式关闭没有任何区别。但是,当应用程序暂停并且用户点击通知时,我可以在此回调方法中处理这种情况:
func userNotificationCenter(_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: @escaping () -> Void) {
}
回答by Yatin Arora
For iOS 10 and above put this in AppDelegate, to get to know notification is tapped(works even app is closed or open)
对于 iOS 10 及更高版本,将其放在 AppDelegate 中,以了解通知已被点击(即使应用程序关闭或打开也能正常工作)
func userNotificationCenter(_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: @escaping () -> Void) {
print("notification tapped here")
}
回答by Saeid
There are two Funcs to handle received PushNotification inside :
有两个 Funcs 来处理接收到的 PushNotification 内部:
class PushNotificationManager: NSObject, MessagingDelegate, UNUserNotificationCenterDelegate{
}
As I tested the first on trigger as soon as Notification arrived
当我在通知到达时立即测试第一个触发器
@available(iOS 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
completionHandler(UNNotificationPresentationOptions.alert)
//OnReceive Notification
let userInfo = notification.request.content.userInfo
for key in userInfo.keys {
Constants.setPrint("\(key): \(userInfo[key])")
}
completionHandler([])
}
And second one when Tapped on Notification:
当点击通知时的第二个:
@available(iOS 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
//OnTap Notification
let userInfo = response.notification.request.content.userInfo
for key in userInfo.keys {
Constants.setPrint("\(key): \(userInfo[key])")
}
completionHandler()
}
Too I tested it with both Remote Notification(in Background Modes) On/Off state.
我也使用远程通知(在后台模式)开/关状态对其进行了测试。
回答by Hourglasser
SWIFT 5.1
斯威夫特 5.1
UIApplication.State
did not work for me, because once I read fingerprint (modal is shown) in my app, notification is also thrown in upper bar and user must click it.
UIApplication.State
对我不起作用,因为一旦我在我的应用程序中读取指纹(显示模态),通知也会被抛出到上栏中,用户必须点击它。
I've created
我创建了
public static var isNotificationFromApp: Bool = false
public static var isNotificationFromApp: Bool = false
in AppDelegate
and I set it true
in my starting viewController
and then in my notification storyboard
/viewController
I just check that :)
在AppDelegate
,我true
在我的开始viewController
然后在我的通知中设置它storyboard
/viewController
我只是检查:)
Hope it can come in handy
希望能派上用场