didReceiveRemoteNotification, когда в фоновом режиме - PullRequest
51 голосов
/ 20 февраля 2011

Подобные вопросы задавались несколько раз, но у меня происходит какая-то конкретная ситуация.

Когда мое приложение активно и я получаю сообщение PUSH, я успешно могу проанализировать пользовательские полезные нагрузки.и все такое.

Однако, когда мое приложение находится в фоновом режиме и прибывает PUSH, пользователь должен нажать на кнопку «Просмотр / Открыть», чтобы вызвать didReceiveRemoteNotification и didFinishLaunchingWithOptions.после этого.

Мне нужно, чтобы мое приложение решило, должны ли они запрашивать пользователя с помощью UIAlert, когда он находится в фоновом режиме, или подавлять push-сообщение, основываясь на некоторых локальных настройках.

Любая помощь будетбыть оцененным,

Ответы [ 6 ]

149 голосов
/ 20 февраля 2011

Ваше приложение должно обрабатывать все возможные состояния доставки push-уведомлений:

  • Ваше приложение было только что запущено

  • Ваше приложение было только что доставленоиз фона на передний план

  • Ваше приложение уже работало на переднем плане

Вы не можете выбрать во время доставки, какой метод презентации используетсяпредставить push-уведомление, которое закодировано в самом уведомлении (необязательное предупреждение, номер значка, звук).Но так как вы, вероятно, контролируете как приложение, так и полезную нагрузку push-уведомления, вы можете указать в полезной нагрузке, было ли представление предупреждения и сообщение, уже представленное пользователю.Только в том случае, если приложение уже запущено на переднем плане, вы знаете, что пользователь не просто запускал ваше приложение через оповещение или регулярно с домашнего экрана.

Вы можете сказать, было ли ваше приложение только что доставлено.на передний план или нет в 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
    ...
}
14 голосов
/ 30 декабря 2014

Передайте content-available = 1 с вашей полезной нагрузкой и вызовете didReceiveRemoteNotification даже в фоновом режиме. например,

{
    "alert" : "",
    "badge" : "0",
    "content-available" : "1",
    "sound" : ""
}
13 голосов
/ 15 января 2016

Чтобы управлять полученным push-уведомлением, когда приложение находится в фоновом режиме, необходимо выполнить несколько действий.

Сначала на стороне сервера необходимо установить {"aps":{"content-available" : 1... / $body['aps']['content-available'] =1; в полезных данных push-уведомлений.

Во-вторых, в вашем проекте XCode вам необходимо использовать "удаленные уведомления".Это делается путем перехода к цели проекта -> возможностям, затем включению переключателя возможностей и проверки флажка удаленных уведомлений.

В-третьих, вместо использования 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);
     }
 }

Наконец, вам нужно добавить этот тип уведомления: UIRemoteNotificationTypeNewsstandContentAvailability в настройки уведомлений, когда выустановите его.

Кроме того, если ваше приложение было закрыто, когда пришло уведомление, вы должны управлять этим в didFinishLaunchingWithOptions, и только если пользователь нажимает на push-уведомление: способ сделать это:

if (launchOptions != nil)
{
    NSDictionary *dictionary = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];

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

launchOptions is! = Nil, когда вы запускаете приложение, нажав на push-уведомление, если вы получите к нему доступ, нажав на значок, launchOptions будет == nil.

Надеюсь это будет полезно. Здесь это объясняет Apple .

8 голосов
/ 20 февраля 2011

Следует помнить одну вещь: когда ваше push-сообщение прибывает на iPhone пользователя и он нажимает кнопку «отмена», за исключением номера значка значка (об этом их позаботится ОС), пути не будетчтобы ваше фоновое приложение узнало об этом событии push и предприняло какие-либо дальнейшие действия.

2 голосов
/ 05 августа 2014

Слово предупреждения

Я думаю, что логика вашего приложения основана на пользовательских данных в вашем push-уведомлении. Это не то, для чего предназначены push-уведомления. В качестве альтернативы вы должны сделать в приложении didbecomeactive просто запросить у вашего сервера данные, которые вам нужны и которые в любом случае отправлялись в качестве полезной нагрузки, и полагаться на них, а не на полезную нагрузку.

Поскольку в документации также указывается , что является наилучшей практикой. Потому что Apple в любом случае не гарантирует, что ваше push-уведомление будет получено в 100% случаев.

Важно: доставка уведомлений - это «лучшее усилие», а не гарантировано. Он не предназначен для доставки данных в ваше приложение, только для уведомить пользователя о наличии новых данных.

Однако, если вы хотите получить некоторое представление о том, был ли изменен, например, значок, не полагаясь на пользователя, открывающего приложение, щелкнув значок, вы можете сделать что-то вроде этого:

A. Вы добавляете (правильный) номер значка в полезную нагрузку push-уведомления, отправляемого вашим сервером. Например, это может выглядеть так:

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

B. Вы постоянно отслеживаете этот номер значка в своем приложении, например, сохраняя его в NSUserDefaults.

Затем в applicationDidBecomeActive можно сравнить свойство applicationIconBadgeNumber UIApplication с вашим ранее сохраненным количеством значков и посмотреть, было ли оно увеличено или уменьшено, и выполнить некоторые обновления на основе этого.

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

    }
0 голосов
/ 07 апреля 2016

Начиная с недавнего 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
    }
}
...