我在反应原生0.38 iOS中遇到推送通知工作时遇到问题。特别是在操作系统终止应用程序后,似乎存在处理推送通知的问题。
似乎当你的应用处于后台状态时,iOS会在某些时候将其杀死(大概是为了释放其他进程的内存)。从我的实验来看,iOS似乎会非常自由地从背景状态终止应用程序 - 这是一个非常普遍的事情。但是,如果操作系统确实从后台状态终止了您的应用,只要该通知包含重要的content-available=1
标记,并且您已允许远程,推送通知到达时它也会恢复它适用于您应用的后台模式的通知。
从RN0.38开始,如果您收到具有content-available=1
标志的推送通知,则必须调用finish
方法,该方法又调用 fetchCompletionHandler 。如果您不调用 completionHandler ,操作系统将惩罚您的应用程序以获取资源,并将减慢(或停止)通知传递 - 它确实(再次非常自由)。我相信你有大约30秒的挂钟时间来调用 fetchCompletionHandler ,之后操作系统会把你放到它的顽皮列表上,你的应用程序将停止正常工作。
所以,从终止状态我可以看到推送通知到达,我可以看到操作系统启动我的应用程序。在我的AppDelegate
我有这个:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
UILocalNotification *remoteNotif = [launchOptions objectForKey: UIApplicationLaunchOptionsRemoteNotificationKey];
if (remoteNotif) {
NSLog(@"push notification when app is not open");
}
...
我看到消息"当app未打开时推送通知"在日志中。都好。当应用程序位于前台时以及它在后台时它可以正常工作,但在终止时则不然。
接下来要做的是-application:didReceiveRemoteNotification:fetchCompletionHandler
被称为:
-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)notification fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
NSLog(@"push-notification with content body => %@", notification);
if(application.applicationState == UIApplicationStateInactive) {
NSLog(@"push-notification app:Inactive");
} else if (application.applicationState == UIApplicationStateBackground) {
NSLog(@"push-notification app:Background");
} else {
NSLog(@"push-notification app:Active");
}
[RCTPushNotificationManager didReceiveRemoteNotification:notification fetchCompletionHandler:completionHandler];
}
在日志中,正如预期的那样,我看到"推送通知应用:背景" 。但是,立即在日志中的这一行之后我看到以下警告:
Nov 28 10:53:17 Tests-iPhone myapp[1139] <Notice>: push-notification app:Background
Nov 28 10:53:17 Tests-iPhone myapp(UIKit)[1139] <Notice>: Warning: Application delegate received call to -application:didReceiveRemoteNotification:fetchCompletionHandler: but the completion handler was never called.
从这看起来它就好像应用程序没有任何时间来处理传入的推送通知。没有调用 completionHandler 的警告立即发生,我的JS代码没有机会运行。当应用程序在前台或后台运行时,我看不到此消息。
我想我的问题是 - 你如何得到一个本机应用程序来优雅地处理在操作系统终止应用程序后到达的iOS推送通知?
从apple docs我收集到的一个方法就是在通知到达后立即启动后台任务。我没有在RN代码库中看到启动后台任务的任何地方,而我现在实际上想知道当应用程序在后台没有启动时推送通知如何工作后台任务。
作为一项实验,我尝试了以下操作,这是一个肮脏的黑客,但我的应用程序在这种情况下开始表现得更好:
-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)notification fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
NSLog(@"push-notification with content body => %@", notification);
if(application.applicationState == UIApplicationStateInactive) {
NSLog(@"push-notification app:Inactive");
} else if (application.applicationState == UIApplicationStateBackground) {
NSLog(@"push-notification app:Background");
} else {
NSLog(@"push-notification app:Active");
}
[RCTPushNotificationManager didReceiveRemoteNotification:notification fetchCompletionHandler:completionHandler];
//start hack
self.pnBgTask = [application beginBackgroundTaskWithName:@"MyPNTask" expirationHandler:^{
[application endBackgroundTask:self.pnBgTask];
self.pnBgTask = UIBackgroundTaskInvalid;
}];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[NSThread sleepForTimeInterval:25.0f];//dodgy hack to give it a chance to complete the 'real' bg-task
[application endBackgroundTask:self.pnBgTask];
self.pnBgTask = UIBackgroundTaskInvalid;
});
//end hack
}
通过此更改,我的应用程序在从xCode运行时效果会更好,但我还没有在真正部署的应用程序中尝试过。
感谢任何想法。
顺便说一句,为了测试这个,你需要让iOS终止你的应用程序(据我所知,这几乎是不可能的),或者 - 或者简单地在Xcode或{{ 3}}使用&#34;等待可执行文件启动&#34;,然后发送推送通知,应用程序将从终止状态开始。