iOS推送通知:当应用程序处于后台时,如何检测用户是否点击了通知?

Bao*_*Lei 108 push-notification apple-push-notifications ios swift

关于这个主题有很多stackoverflow线程,但我仍然没有找到一个好的解决方案.

如果应用程序不在后台,我可以launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey]通过application:didFinishLaunchingWithOptions:电话查看它是否从通知中打开.

如果应用程序在后台,则所有帖子都建议使用application:didReceiveRemoteNotification:并检查应用程序状态.但是当我进行实验时(以及此API的名称建议),此方法在收到通知时被调用,而不是被点击.

所以问题是,如果应用程序启动然后背景化,并且您知道收到通知application:didReceiveNotification(此时application:didFinishLaunchWithOptions:不会触发),您如何知道用户是通过点击通知还是仅通过点击来恢复应用程序应用图标?因为如果用户点击了通知,则期望打开该通知中提到的页面.否则它不应该.

我可以handleActionWithIdentifier用于自定义操作通知,但这仅在轻触自定义操作按钮时触发,而不是在用户点击通知主体时触发.

谢谢.

编辑:

在阅读下面的一个答案之后,我想通过这种方式我可以澄清我的问题:

我们如何区分这两种情况:

(A)1.app转到后台; 2.收到通知; 3.用户点击通知; 4. app进入前台

(B)1.app转到后台; 2.收到通知; 3.用户忽略通知并稍后点击应用程序图标; 4. app进入前台

因为application:didReceiveRemoteNotification:在步骤2中两种情况都被触发.

或者,应application:didReceiveRemoteNotification:仅在步骤3中针对(A)触发,但我以某种方式将我的应用程序配置错误,所以我在第2步看到它?

Bao*_*Lei 93

好的,我终于明白了.

在目标设置➝功能选项卡➝后台模式中,如果选中"远程通知",application:didReceiveRemoteNotification:将在通知到达时立即触发(只要应用程序在后台),在这种情况下无法判断是否用户将点击通知.

如果取消选中该框,application:didReceiveRemoteNotification:则仅在您点按通知时才会触发.

检查此框会改变其中一个应用程序委托方法的行为方式,这有点奇怪.如果选中此框会更好,Apple会使用两种不同的委托方法进行通知接收和通知点击.我认为大多数开发人员总是想知道是否有通知.

希望这对遇到此问题的任何其他人都有帮助.苹果也没有在这里清楚地记录下来,所以我花了一段时间才弄明白.

在此输入图像描述

  • 我完全将背景模式设置为"关闭",但在应用程序处于后台模式时收到通知时仍会收到通知. (6认同)
  • 大!这对我有帮助.遗憾的是,我需要关闭远程通知.我想在推送通知到达时预取数据并检测用户点击.我找不到实现这个目标的方法. (3认同)
  • 我将后台模式设置为“ON”模式并启用远程通知。仍然无法检测到通知事件。 (3认同)

小智 65

我一直在寻找和你一样的东西,并且实际上找到了一个不需要远程通知的解决方案.

要检查用户是否已点击,或应用程序处于后台或处于活动状态,您只需检查应用程序状态

-(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

    }
Run Code Online (Sandbox Code Playgroud)

欲了解更多信息:

UIKit框架参考> UIApplication类参考> UIApplicationState

  • 当应用程序在屏幕上时,由于用户使用通知中心(从顶部滑动)或控制中心(从底部滑动),应用程序将成为UIApplicationStateInactive.显然,没有办法判断APNS是在非活动状态下收到还是用户实际点击了它. (10认同)
  • 这让我感到困惑,为什么Apple不会显示其他事件,或者只是在元数据中添加一个标志来指示用户实际上与通知进行了交互。对于影响用户对应用程序行为期望的关键信息,不得不“推断”用户是否基于有关应用程序状态的环境信息采取了行动。也许唯一要做的就是创建一个自定义操作以使用该信息打开应用程序? (2认同)

Wer*_*wil 19

根据 iOS/XCode:如何通过点击通知或跳板应用程序图标来了解该应用程序已启动? 你必须在didReceiveLocalNotification中检查应用程序状态,如下所示:

if ([UIApplication sharedApplication].applicationState == UIApplicationStateInactive)
{
    // user has tapped notification
}
else
{
    // user opened app from app icon
}
Run Code Online (Sandbox Code Playgroud)

虽然它对我来说没有任何意义,但似乎有效.

  • 我不同意.我在后台功能中检查了"远程通知",它的工作方式与我的答案相同.我也检查了"后台获取".也许这会引起变化? (3认同)

Ham*_*ari 16

如果有人想在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
    }
Run Code Online (Sandbox Code Playgroud)

对于斯威夫特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
}
Run Code Online (Sandbox Code Playgroud)

  • 在didReceiveRemoteNotification上 (2认同)

小智 6

如果您已选中“背景模式”>“远程通知” ==是,则点击通知事件将到达:

-(void)userNotificationCenter:(UNUserNotificationCenter *)center **didReceiveNotificationResponse**:(UNNotificationResponse *)response withCompletionHandler:(void(^)())completionHandler.
Run Code Online (Sandbox Code Playgroud)

它帮助了我。请享受 :)


Sae*_*eid 6

类中有两个 Funcs 来处理接收到的 PushNotification PushNotificationManager

class PushNotificationManager: NSObject, MessagingDelegate, UNUserNotificationCenterDelegate{

}
Run Code Online (Sandbox Code Playgroud)

当我在通知到达时测试了第一个触发器

@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([])
    
}
Run Code Online (Sandbox Code Playgroud)

当点击通知时的第二个:

@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()
}
Run Code Online (Sandbox Code Playgroud)

我还使用远程通知的 ON 和 OFF 状态(在后台模式下)对其进行了测试


pre*_*pre 5

我也遇到了这个问题-但是在带有新UserNotificationsFramework的iOS 11上。

对我来说就像这样:

  • 新品发布: application:didFinishLaunchingWithOptions:
  • 在前台收到: application:didReceiveRemoteNotification:fetchCompletionHandler:
  • 在后台收到: userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler:

  • 这实在是太复杂了‍♂️ (5认同)

Yat*_*ora 5

对于 iOS 10 及更高版本,将其放在 AppDelegate 中,以了解通知已被点击(即使应用程序关闭或打开也能正常工作)

func userNotificationCenter(_ center: UNUserNotificationCenter,
                                didReceive response: UNNotificationResponse,
                                withCompletionHandler completionHandler: @escaping () -> Void) {
print("notification tapped here")
}
Run Code Online (Sandbox Code Playgroud)

  • 这是 iOS 10+ 的正确答案。此处的另一个线程提供了完整的解释:/sf/answers/2924856651/。 (2认同)