在后台执行didReceiveRemoteNotification

这样的问题已经被问了很多次了,但是我还有一些具体的情况。

当我的应用程序处于活动状态,并且收到PUSH消息时,我可以成功parsing自定义有效负载等。

但是,当我的应用程序在后台,并且PUSH到达时,用户必须点击“View / Open”button才能调用didFinishLaunchingWithOptions ,然后调用didFinishLaunchingWithOptions

我需要让我的应用程序决定是否必须在后台使用UIAlert提示用户,或者根据本地设置禁止推送消息。

任何帮助,将不胜感激,

您的应用需要处理所有可能的推送通知递送状态:

  • 你的应用程序刚刚启动

  • 你的应用程序只是从背景到前景

  • 您的应用程序已经在前台运行

您无法在交货时select使用何种呈现方式来呈现推送通知,这些通知是通知本身编码的(可选警报,徽章号码,声音)。 但是,由于您大概都在控制推送通知的应用程序和有效内容,因此可以在有效内容中指定是否存在已提供给用户的警报视图和消息。 只有在应用程序已经在前台运行的情况下,您知道用户不是通过警报或定期从主屏幕启动您的应用程序。

您可以使用以下代码来判断您的应用程序是否刚刚进入了前台或不在didReceiveRemoteNotification中:

 - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo { if ( application.applicationState == UIApplicationStateActive ) // app was already in the foreground else // app was just brought from background to foreground ... } 

content-available = 1传递给您的有效内容,并且即使在后台也会调用didReceiveRemoteNotification 。 例如

 { "alert" : "", "badge" : "0", "content-available" : "1", "sound" : "" } 

当应用程序处于后台时,为了pipe理接收到的推送通知,你必须做几件事情。

首先,在你的服务器端,你必须设置{“aps”:{“content-available”:1 … / $ body ['aps'] ['content-available'] = 1; 在推送通知有效载荷中。

其次,在你的Xcode项目中,哟不得不使用“远程通知”。 这是通过转到项目的目标 – >function,然后启用function切换,并检查远程通知checkbox。

第三,不是使用didReceiveRemoteNotification,而是必须调用application:didReceiveRemoteNotification:fetchCompletionHandler:,这将允许您在接收通知的时刻在后台执行所需的任务:

 - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler { if(application.applicationState == UIApplicationStateInactive) { NSLog(@"Inactive - the user has tapped in the notification when app was closed or in background"); //do some tasks [self manageRemoteNotification:userInfo]; completionHandler(UIBackgroundFetchResultNewData); } else if (application.applicationState == UIApplicationStateBackground) { NSLog(@"application Background - notification has arrived when app was in background"); NSString* contentAvailable = [NSString stringWithFormat:@"%@", [[userInfo valueForKey:@"aps"] valueForKey:@"content-available"]]; if([contentAvailable isEqualToString:@"1"]) { // do tasks [self manageRemoteNotification:userInfo]; NSLog(@"content-available is equal to 1"); completionHandler(UIBackgroundFetchResultNewData); } } else { NSLog(@"application Active - notication has arrived while app was opened"); //Show an in-app banner //do tasks [self manageRemoteNotification:userInfo]; completionHandler(UIBackgroundFetchResultNewData); } } 

最后,您必须在设置通知设置时将此通知types:UIRemoteNotificationTypeNewsstandContentAvailability添加到通知设置。

除此之外,如果您的应用程序在通知到达时closures,则必须在didFinishLaunchingWithOptions中进行pipe理,并且只需用户点击推送通知即可:方法是:

 if (launchOptions != nil) { NSDictionary *dictionary = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey]; if (dictionary != nil) { NSLog(@"Launched from push notification: %@", dictionary); [self manageRemoteNotification:dictionary]; } } 

launchOptions是!= nil当您通过点击推送通知启动应用程序时,如果通过点击图标来访问它,launchOptions将是== nil。

我希望这会有用。 这里: https : //developer.apple.com/library/ios/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/BackgroundExecution/BackgroundExecution.html这是由苹果解释。

有一件事要记住,当你的推送信息到达用户的iPhone,并点击“取消”,除了图标的徽章号码(他们将由操作系统照顾),你将无法后台应用程序来了解这个推送事件,并采取进一步的行动。

警告字

我认为你的应用逻辑是基于你的推送通知中的自定义数据的行为。 这不是推送通知的目的。 你应该做的didbecomeactive在应用程序中做的事情只是向你的服务器询问你所需要的数据,然后依靠这个数据来代替你的有效负载。

因为文件也说明了最好的做法。 因为Apple无法保证您的推送通知无论如何都是百分之百地被接收到的。

重要提示:通知的传递是“尽力而为”,不保证。 它不打算将数据传递到您的应用程序,只是为了通知用户有新的数据可用。

但是,如果您想要知道某个徽章是否已被更改,而不依赖于用户通过单击徽章来打开应用程序,则可以这样做:

答:您添加一个(正确的)徽章号码到您的服务器发送的推送通知的有效载荷。 例如,可能看起来像这样:

 { "aps" : { "alert" : "You got your emails.", "badge" : 9 } } 

B.你在你的应用中持续追踪这个徽章号码,例如把它存储在NSUserDefaults

然后在applicationDidBecomeActive可以将UIApplicationapplicationIconBadgeNumber属性与之前存储的标记数量进行比较,看它是否已经增加或减less,并基于此进行一些更新。

  - (void)applicationDidBecomeActive:(UIApplication *)application { NSNumber *badgecount = [[NSUserDefaults standardUserDefaults] objectForKey:@"badgecount"]; if (!badgecount) badgecount = @(0); if ([UIApplication sharedApplication].applicationIconBadgeNumber != [badgecount integerValue]) { //store the new badge count badgecount = [NSNumber numberWithInteger:[UIApplication sharedApplication].applicationIconBadgeNumber]; NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; [defaults setObject:badgecount forKey:@"badgecount"]; [defaults synchronize]; // do some stuff here because it's different } } 

从最近的iOS – 我认为8 – 如果你已经启用远程通知作为背景模式,一个窍门是跟踪你是否作为一个标志进入前台。

 @interface AppDelegate () @property (assign, atomic, getter=isEnteringForeground) BOOL enteringForeground; @end - (void) applicationWillEnterForeground: (UIApplication *) application { self.enteringForeground = YES; } - (void) applicationDidBecomeActive: (UIApplication *) application { self.enteringForeground = NO; } - (void) application: (UIApplication *) application didReceiveRemoteNotification: (NSDictionary *) userInfo fetchCompletionHandler: (void (^) (UIBackgroundFetchResult)) completionHandler { const BOOL launchedFromBackground = !(application.applicationState == UIApplicationStateActive); const BOOL enteringForeground = self.enteringForeground; if (launchedFromBackground && enteringForeground) { // The user clicked a push while the app was in the BG } }