Почему только некоторые устройства получают push-уведомления

Я настроил службу push-уведомлений для отправки уведомлений клиентам на основе RSS-канала. У меня есть служба, которая запускается каждую минуту, чтобы узнать, добавлено ли новое сообщение в фид. Если это так, служба отправит уведомление всем клиентам. Однако некоторые люди жалуются, говоря, что они не получают никаких push-уведомлений. Вот функция, которую я использую для отправки сообщений:

function _sendMessages($tokens, $message) { $payload['aps'] = array('alert' => $message, 'sound' => 'default'); $payload = json_encode($payload); $context = stream_context_create(); stream_context_set_option($context, 'ssl', 'local_cert', $this->certificate); stream_context_set_option($context, 'ssl', 'passphrase', '*********'); $apns = stream_socket_client('ssl://' . $this->server . ':' . $this->port, $error, $errorString,60, STREAM_CLIENT_CONNECT, $context); foreach($tokens as $row) { $apnsMessage = chr(0) . chr(0) . chr(32) . pack('H*', str_replace(' ', '', $row->device_token)) . chr(0) . chr(strlen($payload)) . $payload; $fwrite = fwrite($apns, $apnsMessage); if (!$fwrite) echo 'push error'; else echo 'push success'; } fclose($apns); } 

Я что-то делаю неправильно? Может ли PHP не обрабатывать это через цикл в тысячу раз и передавать потоки через соединение?

Помимо предложений, уже сделанных другими, вот контрольный список вещей, которые следует учитывать, когда толчки не работают.

  1. Если ваш общий пакет push превышает 256 байтов, включая начальный заголовок, токен и полезную нагрузку JSON, APNS просто отбросит его. Если вы не используете «расширенное» обнаружение ошибок, вы никогда не узнаете, пока ваши пользователи не начнут жаловаться. Что вам нужно сделать, это проверить размер закодированного пакета, то есть размер фактических данных, которые вы будете откачивать провод, и если он длиннее 256 байтов, либо отклоните его, либо отрезайте часть текста сообщения и закодируйте он снова, пока он не будет <= 256 байтов.
  2. Если что-то не так с вашей полезной нагрузкой, включая длину, APNS отбросит ее, и APNS также отключит ваше соединение.
  3. Если у вас постоянное соединение, и он простаивает около 20 минут или около того, APNS будет молча отключать соединение. Вы должны быть готовы к этому и снова подключиться.
  4. Если ваш сертификат APNS истек или является неправильным, и вы продолжаете пытаться подключаться со слишком высокой скоростью, APNS закроет ваш IP-адрес в течение неизвестного периода времени, но это намного больше, чем несколько минут, может быть, даже час или более ,
  5. Если iPhone не имеет приема 3G, но имеет Wi-Fi, он попытается использовать его для push-уведомлений. Если вы находитесь в зоне брандмауэра, которая не позволяет исходящие подключения к сети Apple, ваш iPhone не сможет открыть сокет для APNS, а вы – SOL.
  6. Я не уверен, что ваша SQL-база данных обновляется с помощью токенов push каждый раз, когда клиент подключается к APNS. Наличие статической базы данных токенов-токенов является проблемой, потому что токены не остаются неизменными навсегда – это даже говорится в руководстве по программированию APNS. Предполагается, что iPhone будет получать токен при каждом запуске и передавать его на сервер (и я уверен, что вы можете это оптимизировать), iPhone мог бы хранить последний токен настойчиво и отправлять его, только если он изменился). Но некоторые вещи могут привести к изменению токена токена, например, перерегистрации iPhone для push, и я не уверен, что еще. Все, что я знаю, это то, что полагаться на токен, чтобы быть похожим на GUID, задает проблемы. В следующий раз, когда токен изменится, если ваша БД не обновлена, попрощайтесь с этим клиентом.

Надеюсь это поможет.

Я думаю, что здесь есть 3 потенциальные проблемы:

1) Вы слишком часто подключаетесь (возможно, чаще, чем считаете себя), и Apple отказывается / отказывается от соединения, потому что считает, что вы слишком спам. Это было бы очевидно, если честно – ваш флетт потерпит неудачу, потому что поток исчезнет.

APNS в идеале, как соединение, которое должно быть открыто как можно дольше (10 минут – это время бездействия, которое мы используем), а не восстанавливать его каждую минуту. Расходы на переговоры по протоколу SSL связаны с ЦП, но соединение, находящееся в открытом доступе, относительно дешево. Таким образом, я бы держал это соединение открытым между запусками, если это возможно, и автоматически восстанавливать его, если он по какой-либо причине был сброшен.

2) Вы не проверяете ошибки. См. Руководство APNS, но оно может отвечать на одно и то же соединение с ответами об ошибках, и вы просто игнорируете это. Я думаю, что каждый раз в цикле вы должны проверять, есть ли какие-либо данные для чтения, чтения и интерпретации его как пакета ответов об ошибках. По крайней мере, вы должны регистрировать ответы об ошибках.

3) Это длинный выстрел. Возможно ли, что вы действительно удалили этих пользователей, возможно, потому, что вам сообщили об услуге обратной связи? Если пользователь отключен в течение длительного времени, уведомления не будут доставлены службой, и он может сообщить вам удалить эти устройства из вашего списка. Если вы не будете повторно подписывать этих пользователей (или хотя бы подтвердить, что они все еще подписаны), когда приложение запустится, тогда они подумают, что они подписались на уведомления, когда на самом деле вы уже решили забыть о них.

Хм … Я не вижу в этом ничего плохого. Действительно ли клиенты активировали push-уведомления для вашего приложения?