Обеспечиваем надежную работу Google Cloud Messaging

в 12:48, , рубрики: android, android development, gcm, google cloud messaging, mobile development, push notifications, pushbullet, Разработка под android, метки: , , , , ,

Целью статьи является ознакомление с наиболее распостраненными подводными камнями в работе с сервисом нотификаций от Google.
Источником послужила очень полезная, на мой взгляд, статья Keeping Google Cloud Messaging For Android Working Reliably от разработчиков Pushbullet — удобного приложения для синхронизации нотификаций между Android устройствами и браузером Chrome

Надеюсь все из вас уже ознакомлены со статьями по Google Cloud Messaging:

Урок №1: Будьте готовы часто получать SERVICE_NOT_AVAILABLE

Этот момент совершенно игнорируется в официальной документации Implementing GCM Client. Таким образом, это одна из важнейших деталей, которые необходимо знать при регистрации GCM.

Вызов gcm.register(SENDER_ID); очень часто приводит к ошибке с исключением IOException «SERVICE_NOT_AVAILABLE».

Есть вероятность, что она никогда не произойдет на ваших тестовых устройствах и можно оказаться не готовым к ней. Это может привести к очень негативному эффекту, так как надежность вашего приложения может серьёзно пострадать, в тот момент когда ваше приложение уже опубликовано, а так случается очень часто.

Как быть? Это довольно просто. Это сообщение означает что GCM не смог зарегистрироваться и вам надо попробовать еще раз. Документация на этот случай рекомендует экспонциально выждать время и повторить попытку, это отличный совет.

Урок №2: Будьте готовы к повторяющимся ошибкам вызова register, даже если рабочий registration ID создан

Этот совет довольно странный и может оказаться не актуальным, но так как нет способа подтвердить что ошибка в GCM была исправлена, то предусмотрим и это.

Ошибка заключается в следующем:
Совершенно не важно сколько раз вы вызывали gcm.register(SENDER_ID); он постоянно падает с ошибкой на некоторых устройствах. Даже если рабочий registration ID был успешно создан, но так и не был возвращен в результате функции.
Что бы получить этот registration ID, зарегистрируйте свой GCM BroadcastReceiver на следующее событие:

<action android:name="com.google.android.c2dm.intent.REGISTRATION" />

Вы получите возможность получить рабочий registration ID:

final String registrationId = intent.getStringExtra("registration_id");

В случае, если эта переменная не null и не пуста, вы получите работающий registration ID. Далее, можете его сохранить и передать на ваш сервер как вы обычно делаете.

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

Урок №3: Убедитесь что вы регистрируете свое устройсво заново всякий раз, когда обновляете своё приложение

Этот совет взят из официальной документации, но его очень легко пропустить, так что не забывайте о нем.

Маловерятно что пользователь откроет ваше приложение сразу после обновления из маркета, поэтому очень важно произвести регистрацию приложения заново автоматически. Очень важно сохранить работоспособность сервиса сообщений сразу после обновления.

Лучший способ активировать автоматический процесс регистрации, это объявить в AndroidManifest класс BroadcastReceiver, который будет слушать событие PACKAGE_REPLACED:

<receiver android:name=".UpdateReceiver">
    <intent-filter>
        <action android:name="android.intent.action.PACKAGE_REPLACED" />
        <data android:path="<YOUR_PACKAGE_NAME_HERE>"
              android:scheme="package" />
    </intent-filter>
</receiver>

В тот момент, когда метод onReceive будет вызван, вы можете инициировать регистрацию GCM. Далее заменяеете текущий registration ID на новый и отправляете его на свой сервер.

Надеюсь вы помните, что вызывать

gcm = GoogleCloudMessaging.getInstance(activity); 
regid = gcm.register(SENDER_ID);

непосредственно в onReceive BroadcastReceiver-а не стоит, так как этот метод будет вызван в главном потоке приложения (MAIN_THREAD), и не должен работать на прямую с сетью.
Для этих целей рекомендуется использовать AsyncTask, либо специально созданный фоновый сервис, либо Thread на худой конец.

Урок №4: Убедитесь что вы регистрируете свое устройсво заново в случае обновления версии Android на устройстве

Это нигде не документировано (насколько я знаю), но известно, что registration ID зависит от Android ID устройства.
Который может измениться если меняется прошивка устройства или пользователь делает сброс к заводским установкам (factory reset). Таким образом надо зарегистрировать устройство заново если произошла одна из этих ситуаций.

Так же как и в случае с обновлением приложения, пользователь вряд ли сразу же запустит ваше приложение, которое могло бы инициировать процесс регистрации GCM при запуске. Вы должны позаботится об автоматической перерегистрации устройства для того что бы обеспечить работу службы сообщений без ожидания запуска приложения пользователем.
Какой лучший способ сделать это? Существует единственный способ сделать это, хоть этот способ и не идеальный. Вам нужно регистрировать ваше приложение всякий раз, когда телефон перезагружается. Для этого надо дать приложению в AndroidManifest новое разрешение:

<uses-permission
    android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

И настроить BroadcastReceiver на приём события BOOT_COMPLETED:

<receiver android:name=".BootReceiver">
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED" />
    </intent-filter>
</receiver>

Теперь, каждый раз при вызове onReceive этого слушателя вы сможете снова зарегистрировать ваше устройство в GCM.

Возможно, более эффективным было бы вызывать регистрацию устройства только в случае, если Android ID действительно изменился. Важно то, что с помощью этой, казалось бы, не обязательной работы бы будем уверены что устройсво зарегистрировано даже когда это возможно было не нужно, мы ведь не можем быть на 100% уверены Android ID обязательно изменится.

На этом все. Печально, что для того что бы обеспечить бесперебойную работу GCM, пришлось идти на подобные «танцы с бубном» и еще более жалко что большинство этих моментов совершенно не документированы самим Google.

Ошибки и опечатки в личку

Автор: djvu

Источник

Поделиться

* - обязательные к заполнению поля