Правильная последовательность, чтобы получить регистрационный токен для push-уведомления GCM на iOS? Неужели GCM ненадежна?

Привет, я следил за учебником по использованию GCM на iOS. Он работает с перерывами (что означает, что все сертификаты, разрешения и все в порядке). Однако в последнее время я неоднократно получаю два сообщения об ошибках:

GCM | GCM registration is not ready with auth credentials.

Кроме того, повторное подключение к GCM не выполняется:

Error Domain=com.google.gcm Code=501 "(null)"

Это относится, в частности, к устройству, не получающему идентификатор регистрации GCM. Кто-нибудь еще сталкивается с этими проблемами чаще в последнее время? Или это потому, что я вызываю GCM API в неправильной последовательности (особенно методы connectWithHandler:, startWithConfig: и tokenWithAuthorizedEntity)? Я подозреваю, что причина в том, что последний, поскольку я получаю идентификатор GCM после некоторой задержки.

Я не всегда получаю идентификатор GCM. Когда я не получаю один, я обычно должен запускать приложение один или два раза через Xcode. (Или путем принудительного закрытия приложения). Очевидно, что это не то, что мои пользователи должны делать.

Это последовательность вызовов API GCM:

  • Устройство получает токен APNS
  • Затем я звоню tokenWithAuthorizedEntity:, используя токен APNS
  • ^ Это обычно приводит к одной из двух упомянутых выше ошибок.
  • Всякий раз, когда я на самом деле нужен токен GCM, я принудительно обновляю токен GCM вызывая tokenWithAuthorizedEntity снова.

Кроме того, у меня есть вызов connectWithHandler:, написанный внутри моего метода applicationDidBecomeActive:.

Несколько вопросов:

  • Требуется ли вызов connectWithHandler: в applicationDidBecomeActive:, если меня интересует только получение push-сообщений GCM, а не отправка их вверх по течению?
  • Если ответ на (1) - да, в обработчике завершения этого метода, если возникает ошибка, и у меня нет маркера GCM в этой точке, я должен попытаться снова получить токен? (т.е. вызов tokenWithAuthorizedEntity?)
  • Когда следует вызывать startWithConfig? Перед тем, как получить токен GCM или после?

EDIT: Ограниченное тестирование показало, что работает следующее:

  • Сначала введите идентификатор GGLInstance (т.е. вызов getIDWithHandler:)
  • Если вышеуказанный идентификатор GGLInstance был получен без какой-либо ошибки, попросите маркер GCM (т.е. вызов tokenWithAuthorizedEntity:)
  • Выполнение этого обычно дает следующую ошибку, но, по крайней мере, за короткое время (~ 3-10 секунд), токен получен:

Невозможно найти маркер в кеше. Error Domain = com.google.iid Код = -25300 "(Нуль)"

Ответы

Ответ 1

Является ли вызов connectWithHandler: in applicationDidBecomeActive:      необходимо, если меня интересуют только сообщения GCM push и      не отправлять их вверх по течению?

Да, connectWithHandler необходимо, несмотря на то, что его основной целью является соединение с конечной точкой GCM.

Если ответ на (1) да, в обработчике завершения этого метода, если возникает ошибка, и у меня нет токена GCM в этот момент, если Я пытаюсь снова получить токен? (то есть вызов tokenWithAuthorizedEntity?)

Итак, как это работает, вы проверяете ошибки во время запроса самого токена и повторите попытку с экспоненциальным отклонением, если запрос завершился с ошибкой. Подробнее здесь. Также читайте примечание здесь. Теперь, если вы все еще хотите повторно вызвать GGLInstanceIDTokenHandler в любой момент, вы также должны реализовать deleteTokenWithAuthorizedEntity перед тем, как получить новый токен.

Когда следует вызывать startWithConfig? Перед тем, как получить токен GCM или после?

В AppDelegate.m вы должны вызвать экземпляр GGLInstanceID shared с использованием метода startWithConfig. По существу в классе GGLINstanceID.h он должен сначала получить идентификатор экземпляра; затем авторизуйте проект как Уполномоченное лицо, а затем получите токен регистрации через службу iid. См. Подробную реализацию для GGLINstanceID.h class здесь.

Надеюсь, что это поможет в помощи!

EDIT

Отвечает ли этот вопрос на ваш вопрос? Суть его заключается в том, чтобы идентификатор Bundle для вашей цели был таким же, как BUNDLE_ID в файле info.plist.

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

Ответ 2

Попробуйте переместить блок connectWithHandler в метод didFinishLaunchingWithOptions после того, как вы получите блок gcmConfig. (для официального примера, после [END start_gcm_service])