推送通知有效负载未保存在某些设备上
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 分钟,再次发送推送和有效负载未保存。配置没问题,我又检查了一遍,没问题。以上是关于推送通知有效负载未保存在某些设备上的主要内容,如果未能解决你的问题,请参考以下文章