Тихие push-уведомления доставляются только в том случае, если устройство заряжается и / или приложение находится на переднем плане

Я реализовал тихие push-уведомления, но заметил странное поведение. Беззвучные push-уведомления обрабатываются с помощью:

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler

Тихие push-сообщения, похоже, принимаются только в том случае, если устройство заряжается (т. Е. Подключен кабель) и / или если мое приложение находится на переднем плане.

Если я отключаю устройство от зарядного устройства (или Mac), то тихие push-уведомления больше не принимаются, если приложение не на переднем плане.

Обычно я получаю не тихие push-уведомления в обоих случаях.

Если я снова подключу USB-кабель, то получу ожидаемое поведение и получу беззвучные push-уведомления независимо от того, находится ли приложение на переднем или на заднем плане.

Я использую UILocalNotification, поэтому я знаю, что получено.

Тот факт, что все это работает нормально с подключенным устройством, говорит о том, что мои уведомления с молчаливыми нажатиями настроены правильно, и в приложении установлены правильные режимы фона, заданные в plist и т. Д.

Такое поведение повторяется на iPhone 5s, 6 и iPad 2, работающих под управлением IOS 8 или 8.1.

Кто-нибудь еще испытывал это? Это должно быть легко воспроизвести. Почему простое действие по подключению устройства к зарядному устройству должно изменить возможность получения тихих push-уведомлений?

8 ответов

Мы испытали такое же поведение и пытались понять, почему iOS решает доставлять одни уведомления, а другие нет.

То, что мы разработали до сих пор:

  • Сообщения будут получать более надежно в фоновом режиме, когда на Wi-Fi, чем на сотовые данные. Фактически, когда в сотовой сети (3g/4g), если уровень вашего сигнала недостаточно силен, iOS получает push-сообщение, но не разбудит ваше приложение. Мы разместили на форумах Apple об этом здесь: https://devforums.apple.com/message/1069814. Мы также открыли тикет поддержки, и команда поддержки попросила нас подать его в виде отчета об ошибке, что мы сделали пару недель назад и все еще ждем ответа.

  • Когда вы получаете push-сообщение, вам нужно как можно скорее вызвать fetchCompletionHandler. Технически у вас есть 30 секунд для выполнения фоновой обработки, но в iOS есть формула, согласно которой, чем чаще вы отправляете push-сообщения и в зависимости от того, сколько времени вы тратите на обработку этих сообщений, прежде чем вернуть приложение в приостановленное состояние, iOS может уменьшить объем раз ваше приложение просыпается в будущем.

Смотрите здесь, от Apple didReceiveRemoteNotification: fetchCompletionHandler: документация:

Как только вы закончите обработку уведомления, вы должны вызвать блок в параметре обработчика, иначе ваше приложение будет закрыто. Ваше приложение имеет до 30 секунд времени настенных часов для обработки уведомления и вызова указанного блока обработчика завершения. На практике вам следует вызывать блок обработчика, как только вы закончите обработку уведомления. Система отслеживает затраченное время, энергопотребление и стоимость данных для фоновых загрузок вашего приложения. Приложения, которые используют значительную мощность при обработке push-уведомлений, не всегда могут быть разбужены рано для обработки будущих уведомлений.

В нашем тестировании мы отправляли частые тихие push-уведомления в наше приложение (каждые 10 - 30 секунд). И приложение не спит около 3 секунд, прежде чем мы вернем его обратно в режим сна. Со временем мы определенно заметили снижение частоты, с которой наше приложение просыпается до такой степени, что iOS будет запускать приложение только каждые 15 - 30 минут. Так что, похоже, существует какая-то формула затухания / регулирования, но мы не можем найти никакой документации о том, как именно она работает. Мы запросили эту формулу и переменные у Apple в качестве запроса на поддержку, но они ответили: "Запрашиваемая вами информация не является общедоступной" и снова попросили нас подать отчет об ошибке.

Итак, надеюсь, это полезно? Мы все еще пытаемся узнать больше сами, поэтому я нашел этот вопрос:)

С iOS8 фоновая доставка в приложения изменилась. Фоновый толчок теперь будет доставляться в приложение только при определенных обстоятельствах. Apple не указала в явном виде, в чем именно состоят эти обстоятельства, но, исходя из моих обширных экспериментов, все сводится к тому, заряжается телефон или нет. Есть некоторые другие переменные в игре (такие как тип сети, тип устройства, включенный Wi-Fi), но основной основной фактор - это заряжается устройство или нет, когда приходит пуш.

Если телефон заряжается от прямого сетевого источника питания или косвенно через USB-соединение с компьютером, то подавляющее большинство времени будет доставляться в приложение. Но отсоедините телефон от источника питания или USB, и фоновое нажатие почти никогда не будет доставлено в приложение, даже если батарея телефона заряжена на 100%.

Вы можете очень легко это проверить, просто отправив несколько нажатий, когда телефон заряжается, а когда нет. НО вы должны принять во внимание, что фоновые изменения в сборке разработки и использовании среды "песочницы" НЕ ведут себя так же, как фоновые изменения в производственной сборке и производственной среде, фоновые изменения на самом деле более вероятны для доставки в приложение в процессе разработки. затем они находятся в производстве, поэтому крайне важно, чтобы вы тестировали, используя производственную сборку и производственную среду Apple, чтобы увидеть реальные результаты.

Обратите внимание, что есть два шага принудительной доставки, во-первых, он должен быть доставлен на сам телефон, во-вторых, как только телефон получит его, он должен быть доставлен операционной системой в приложение. В iOS7 такие вещи, как тьюринг по Wi-Fi, увеличивали шансы того, что пуш доберется до телефона. Однако с iOS8, даже несмотря на то, что push-сообщение успешно доставляется на телефон, ОС не передает его в фоновое приложение, если телефон не заряжается. Это означает, что телефон получает уведомление и удерживает его, иногда в течение нескольких часов, прежде чем он сможет переслать его в приложение, если телефон не заряжается.

Я столкнулся с той же проблемой, и причина, по которой я не получаю push-уведомления, когда приложение не заряжается, заключается в том, что когда режим низкого энергопотребления включен из Settings > Battery это отключает background-fetch функция для всех приложений.

Что мешает устройству получать push-уведомления.

Эта ссылка может быть полезной. Документация Apple

Я также заметил то же самое и потратил некоторое время на выяснение. См. /questions/20038722/vozmozhnyi-li-silent-remote-notifications-esli-polzovatel-otklyuchil-funktsiyu-push-uvedomlenij-dlya-prilozheniya/20038731#20038731

Если вы выключили Bg App Refresh, тихий удаленный пуш будет тихо отброшен (ирония).

Тем не менее, я заметил, что если вы подключаетесь к XCode через кабель, каким-то образом настройка Bg App Refresh игнорируется, и все тихие нажатия для вашего приложения работают.

Я очень подозреваю, что это недокументированная функция: зарядка игнорирует настройку Bg App Refresh.

Это не работает, потому что вы включили неправильный фоновый режим в списке. Вам необходимо включить remote-notification тег (приложение загружает контент в ответ на push-уведомления), а не извлекает. Выборка используется для чего-то другого. Вам также может понадобиться использовать ключ доступного содержимого в полезной нагрузке JSON, например:

{
   "aps": {
      "content-available": 1
    },
    "yourdatakey":{data}
}

Я надеюсь, что вы используете APNS, предоставляя приоритет "CONSERVE_POWER" (5)попробуйте изменить это как "IMMEDIATE" (10)

Я уже давно сталкиваюсь с этой проблемой, и я очень благодарен за этот вопрос и @Kevin D., которые делятся своим пониманием. Я начинаю думать, что /questions/3735253/push-uvedomleniya-kotoryie-zapuskayut-fonovoe-obnovlenie-pered-otobrazheniem-push-uvedomlenij-vs-tihij-push/3735268#3735268 и https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/CommunicatingWIthAPS.html (см. priority в одной из таблиц) описывают, почему мое приложение имеет проблемы:

Ошибочно использовать этот приоритет для толчка, который содержит только content-available ключ.

Для отправки уведомлений я использую node-apn, где по умолчанию (который мне тоже нужен) является установка приоритета max (10 [Остерегайтесь, похоже, только 10 а также 5 правильные значения в это время]), но так как я хотел тихое уведомление, у меня нет alert, badge, или же sound задавать.

Я нашел другое решение, которое работает для меня, используя PushKit Framework

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

Когда я отправляю VOIP Push, приложение просыпается независимо от состояния приложения и может выполнять любые операции.

Зарегистрируйтесь для получения VOIP PushNotification в didFinishLaunchingWithOptions

 PKPushRegistry *pushRegistry = [[PKPushRegistry alloc] initWithQueue:dispatch_get_main_queue()];
pushRegistry.delegate = self;
pushRegistry.desiredPushTypes = [NSSet setWithObject:PKPushTypeVoIP];


- (void)pushRegistry:(PKPushRegistry *)registry didUpdatePushCredentials:(PKPushCredentials *)credentials forType:(NSString *)type{
if([credentials.token length] == 0) {
    NSLog(@"voip token NULL");
    return;
}

NSString *originalToken=[NSString stringWithFormat:@"%@",credentials.token];
NSString *token = [originalToken stringByTrimmingCharactersInSet: [NSCharacterSet characterSetWithCharactersInString:@"<>"]];
token = [token stringByReplacingOccurrencesOfString:@" " withString:@""];
NSLog(@"PushCredentials: %@",token);}

тогда вы можете обработать любую фоновую выборку в этой функции, как только вы получите VOIP PushNotification

-(void)pushRegistry:(PKPushRegistry *)registry didReceiveIncomingPushWithPayload:(PKPushPayload *)payload forType:(NSString *)type

ПРИМЕЧАНИЕ: вы должны использовать сертификат, который включает сертификат услуг VoIP

Другие вопросы по тегам