推送通知有效负载未保存在某些设备上

Posted

技术标签:

【中文标题】推送通知有效负载未保存在某些设备上【英文标题】:Push Notification Payload not saved on some device 【发布时间】:2015-07-13 11:20:18 【问题描述】:

我在在某些设备上处理通知负载时遇到了问题。我正在通过 Parse Cloud 功能向我的用户发送推送通知。

我正在使用以下方法来捕获通知并存储其有效负载,以便用户可以在专用视图中查看所有收到的通知。在我的个人设备上,我总是收到通知并正确保存,在我朋友的设备上,虽然通知到达,但如果应用程序在后台,则不会保存有效负载,而如果应用程序在前台,有效负载会被保存。

这可能是设备本身的问题吗?或者可能与电话提供商有关(我有 h3g,他有 Vodafone)?

-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
// Parse push handler will show a UIAlertView
[PFPush handlePush:userInfo];

if (application.applicationState == UIApplicationStateInactive) 

    // tha app is inactive, transitioning to or from the background        
    completionHandler(UIBackgroundFetchResultNoData);

 else if (application.applicationState == UIApplicationStateBackground) 

    // tha app is running in background
    // add the notification to the notificationsArrayRecord
    NSDate *now = [[NSDate alloc]init];
    NSDictionary *aps = userInfo[@"aps"];
    NSString *alertMessage = aps[@"alert"];
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];

    NSMutableArray *notificationsArrayRecord = [[defaults arrayForKey:@"notificationsArrayRecord"] mutableCopy];
    [notificationsArrayRecord addObject:@[now,alertMessage]];
    [defaults setValue: notificationsArrayRecord forKey:@"notificationsArrayRecord"];

    // update the notifications counter
    NSInteger pushCount = [[NSUserDefaults standardUserDefaults] integerForKey: @"pushCount"];
    pushCount ++;
    [defaults setInteger: pushCount forKey:@"pushCount"];
    [defaults synchronize];

    completionHandler(UIBackgroundFetchResultNewData);
 else         
    // the app is running in foreground

    // add the notification to the notificationsArrayRecord
    NSDate *now = [[NSDate alloc]init];
    NSDictionary *aps = userInfo[@"aps"];
    NSString *alertMessage = aps[@"alert"];
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];

    NSMutableArray *notificationsArrayRecord = [[defaults arrayForKey:@"notificationsArrayRecord"] mutableCopy];
    [notificationsArrayRecord addObject:@[now,alertMessage]];
    [defaults setValue: notificationsArrayRecord forKey:@"notificationsArrayRecord"];

    // update the notifications counter
    NSInteger pushCount = [[NSUserDefaults standardUserDefaults] integerForKey: @"pushCount"];
    pushCount ++;
    [defaults setInteger: pushCount forKey:@"pushCount"];
    [defaults synchronize];

    completionHandler(UIBackgroundFetchResultNewData);

    // refresh the menu buttons and the notification counter
    [[NSNotificationCenter defaultCenter] postNotificationName:@"appDidReceiveNotificationWhileActive" object:nil];
   
  

【问题讨论】:

你怎么知道通知到达了?它们是显示在通知中心还是您确定调用了didReceiveRemoteNotification?如果应用被用户强制退出,应用不会被唤醒,didReceiveRemoteNotification 也不会被调用。也许他正在强制退出应用程序? 我用我手上的两部手机做了很多测试。通知永远不会出现,一旦我打开应用程序就无法保存。有时甚至在我的手机上,所以我不再认为这可能是手机问题..这是我的代码的问题,但我不知道它有什么问题。 【参考方案1】:

我想问题是你如何处理应用程序状态UIApplicationStateInactive。在这种情况下,您没有存储信息。您还应该在这种情况下存储它,因为当您收到通知时,应用程序显然可能处于这种状态。这也解释了为什么有时会失败。 另请参阅this question,它表明应用程序有时处于状态UIApplicationStateInactive,当设备收到通知时。

您应该重构代码以在所有情况下存储数据:

-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
    // Parse push handler will show a UIAlertView
    [PFPush handlePush:userInfo];

    // add the notification to the notificationsArrayRecord     
    NSDate *now = [[NSDate alloc]init];
    NSDictionary *aps = userInfo[@"aps"];
    NSString *alertMessage = aps[@"alert"];
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];

    NSMutableArray *notificationsArrayRecord = [[defaults arrayForKey:@"notificationsArrayRecord"] mutableCopy];
    [notificationsArrayRecord addObject:@[now,alertMessage]];
    [defaults setValue: notificationsArrayRecord forKey:@"notificationsArrayRecord"];

    // update the notifications counter
    NSInteger pushCount = [[NSUserDefaults standardUserDefaults] integerForKey: @"pushCount"];
    pushCount ++;
    [defaults setInteger: pushCount forKey:@"pushCount"];
    [defaults synchronize];

    if (application.applicationState == UIApplicationStateInactive) 
        // the app is inactive, transitioning to or from the background        
        completionHandler(UIBackgroundFetchResultNoData);
     else if (application.applicationState == UIApplicationStateBackground) 
        // the app is running in background
        completionHandler(UIBackgroundFetchResultNewData);
     else         
        // the app is running in foreground
        completionHandler(UIBackgroundFetchResultNewData);

        // refresh the menu buttons and the notification counter
        [[NSNotificationCenter defaultCenter] postNotificationName:@"appDidReceiveNotificationWhileActive" object:nil];
    

更新: 我不确定在applicationState 中调用completionHandler(UIBackgroundFetchResultNoData)(不知道这有什么用处),但也许您需要调用completionHandler(UIBackgroundFetchResultNewData),同样在这种情况下,以获取存储的数据。

还要确保您正确配置了所有内容以在后台接收通知,[查看此]答案(https://***.com/a/31450953/594074)。

【讨论】:

您的回答对我来说看起来很有希望,我会立即尝试并在获得批准后接受它,我可以正确尝试。在此感谢您。 好的,我尝试了您的更正,问题仍然存在。一段时间后,有效负载被保存,然后 5 分钟后它没有被保存。在两部手机上再次尝试。该问题仅在应用程序处于后台状态时出现,因为当它处于前台时,它总是成功保存有效负载。此外,如果我点击 ios 通知徽章,一切都会正确保存(在这种情况下,您的代码有效负载会被保存两次,但这将是一个小问题)... ...老实说,我正在放弃这件事..因为我担心这不是一个可靠的系统。我不知道这是否取决于我正在使用的同步方法或我正在使用 NSUserDefaults 保存有效负载的事实,事实是有时应用程序会进入不调用 didReceiveRemoteNotification 方法的状态一些原因..你的回答对我仍然有用。谢谢。 阅读我的回答中的更新:我不确定在applicationState 中调用completionHandler(UIBackgroundFetchResultNoData)(不知道这有什么好处),但也许你需要改为调用completionHandler(UIBackgroundFetchResultNewData)在这种情况下,获取存储的数据。还要确保您正确配置了所有内容以在后台接收通知,[查看此]答案(***.com/a/31450953/594074)。 不,我也试过UIBackgroundFetchResultNewData 。我什至删除了所有条件,只保留了 save 和 completitionHadler,以确保始终调用代码。结果相同。事实上我只是做了一个测试,有效载荷没有得到保存。有效负载保存了一段时间,然后我将手机置于睡眠模式约 20 分钟,再次发送推送和有效负载未保存。配置没问题,我又检查了一遍,没问题。

以上是关于推送通知有效负载未保存在某些设备上的主要内容,如果未能解决你的问题,请参考以下文章

某些设备在 android 中未收到推送通知

某些设备未收到 Apple 推送通知

ios:此有效负载格式中的推送通知徽章计数未增加

Android 推送通知横幅未在某些设备中显示

推送通知未在 android 上显示

当应用程序处于未运行或后台状态时,如何处理推送通知有效负载而不点击它