Делай больше с Google Cloud Messaging

Google Cloud Messaging (GCM) представляет собой бесплатный сервис для отправки сообщений на Android устройства. GCM сообщения могут значительно улучшить пользовательский опыт. Данные вашего приложения могут оставаться актуальными, не тратя заряд аккумулятора для возобновления работы сети и опроса сервера, когда нет никаких обновлений. Кроме того, GCM позволяет присоединять до 1000 получателей одного сообщения, что позволяет легко и быстро связаться с большим количеством пользователей, когда это необходимо, при минимальной нагрузке вашего сервера.

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

Эффективная отправка широковещательных сообщений

Одной из самых полезных функций GCM является поддержка до 1000 получателей одного сообщения. Эта возможность делает более простым отправку важных сообщения для всей базы пользователей. Например, предположим, что у вас было сообщение, которое нужно было отправить 1,000,000 ваших пользователей, и ваш сервер мог справиться с отправкой около 500 сообщений в секунду. Если вы посылаете каждое сообщение только одному получателю, то потребуется 1,000,000/500 = 2,000 секунд, или около получаса. Однако, задав 1,000 получателей для каждого сообщения, общее время, необходимое для отправки сообщений 1,000,000 получателей становится равным (1,000,000/1,000) / 500 = 2 секунды. Это не только полезно, но и важно для своевременного получения данных, таких как предупреждения о стихийных бедствиях или спортивных соревнованиях, где 30-минутный интервал мог бы сделать информацию бесполезной.

Воспользоваться этой функциональностью легко. Если вы используете вспомогательную библиотеку GCM для Java, то просто укажите List коллекцию идентификаторов регистрации для send или sendNoRetry метода, вместо одного идентификатора регистрации.

// This method name is completely fabricated, but you get the idea.
List
       
         regIds = whoShouldISendThisTo(message);

// If you want the SDK to automatically retry a certain number of times, use the
// standard send method.
MulticastResult result = sender.send(message, regIds, 5);

// Otherwise, use sendNoRetry.
MulticastResult result = sender.sendNoRetry(message, regIds);

       

Для реализации поддержки GCM на любом другом языке, отличном от Java, постройте HTTP POST запрос со следующими заголовками:

  • Authorization: key=YOUR_API_KEY
  • Content-type: application/json

Затем поместите требуемые параметры в JSON объект, перечисляя все идентификаторы регистрации под ключом registration_ids. Фрагмент ниже служит примером. Все параметры, кроме registration_ids являются не обязательными, и элементы вложеные в data представляют определенный пользователем контент, а не GCM параметры. Адрес для этого HTTP POST сообщения будет https://android.googleapis.com/gcm/send.

{ "collapse_key": "score_update",
   "time_to_live": 108,
   "delay_while_idle": true,
   "data": {
       "score": "4 x 8",
       "time": "15:16.2342"
   },
   "registration_ids":["4", "8", "15", "16", "23", "42"]
}

Более подробный обзор формата широковещательных сообщений GCM, см. раздел Отправка сообщений руководства по GCM.

Сверните сообщения, которые могут быть заменены

GCM сообщения зачастую просто говорят мобильным приложением, что необходимо связаться с сервером для обновления данных. В GCM, можно (и рекомендуется) для создания сворачиваемых сообщений для ситуации, когда новые сообщения заменяют старые. Давайте рассмотрим на примере спортивных соревнований. Если вы посылаете сообщение всем пользователям с обновленным счетом игры, а затем через 15 минут счет обновляется и вы оправляете новое сообщение, предыдущее сообщение уже не имеет значения. Любым пользователям, которые не получили первое сообщение, нет необходимости отправлять оба и заставлять устройство реагировать (и, возможно, информировать пользователя) дважды, когда важно лишь только одно сообщение.

При определении ключа сворачивания, когда несколько сообщений для одного пользователя помещаются в очередь GCM сервера, только последнее сообщение с данным ключом будет доставлено. В ситуациях, как со спортивными соревнованиями, это избавляет устройство от проделывания ненужной работы и потенциально ненужных уведомлений пользователя. Для ситуаций, связанных с синхронизацией с сервером (например, проверка электронной почты), это может сократить количество синхронизаций устройства. Например, если есть 10 писем ожидающих на сервере, и десять GCM сообщений о "новых письмах" было отправлены на устройство, но необходимо только одно, так как синхронизацию необходимо выполнить только один раз.

Чтобы использовать эту функцию, просто добавьте ключ свертывания для исходящего сообщения. Если вы используете вспомогательную GCM библиотеку, выполните для Message класса вызов collapseKey(String key) метода.

Message message = new Message.Builder(regId)
    .collapseKey("game4_scores") // The key for game 4.
    .ttl(600) // Time in seconds to keep message queued if device offline.
    .delayWhileIdle(true) // Wait for device to become active before sending.
    .addPayload("key1", "value1")
    .addPayload("key2", "value2")
    .build();

Если вы не используете вспомогательную библиотеку, просто добавьте значение в заголовок создаваемого POST запроса, с collapse_key в качестве имени поля и строку, которую вы используете для этого набора обновлений в качестве значения.

Вставьте данные непосредственно в GCM сообщение

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

  • Общий размер данных в пределах 4kb.
  • Все сообщения важные, и должны быть сохранены.
  • Не имеет смысла сворачивать несколько GCM сообщений в единственное сообщение о наличие "новых данных на сервере".

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

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

Однако эта стратегия не подходит для отправки больших объемов данных по нескольким причинам:

  • Ограничения скорости для защиты от вредоносных или плохо запрограммированных приложений от спама отдельных устройств сообщениями.
  • Не гарантируется получение сообщений по порядку.
  • Не гарантируется быстрая доставка сообщений. Даже если устройство получает одно GCM сообщение секунду, размером в 1Kбайт, это 8 килобит в секунду, или скорость домашнего коммутируемого Интернет в начале 1990-х. Это отразится на рейтинге вашего приложение на Google Play.

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

Интеллектуальная обработка GCM сообщений

Ваше приложение должно не просто реагировать на входящие GCM сообщения, а реагировать разумно. Как реагировать зависит от контекста.

Не раздражайте

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

Синхронизация умнее, не труднее

При использовании GCM в качестве индикатора, что устройство должно загрузить данные с сервера, помните, что вы можете отправить 4kb метаданных, которые могут помочь вашему приложению работать разумно. Например, если у вас есть приложение для чтения канала, и ваш пользователь имеет 100 каналов, помогите устройству разумно скачивать новые каналы с сервера! Посмотрите на следующие примеры того, какие метаданные можно отправить вашему приложению в GCM сообщении, и как приложение может на них реагировать:

  • refresh — Ваше приложение просят скачать все каналы, просматриваемые пользователем. Ваше приложение должно либо отправить запросы на 100 различных серверов для получения, либо, если у вас есть агрегатор на вашем сервере, отправьте запрос на получение, упаковку и передачу последних данных от 100 различных каналов, каждый раз, когда хотя бы один обновился.
  • refresh, feedID — Лучше: Ваше приложение знает, что нужно проверить обновление конкретного канала.
  • refresh, feedID, timestamp — Наилучший: Если пользователь уже вручную обновил канал до того, как GCM сообщением было доставлено, приложение может сравнить время последнего обновления и определить, что ничего не нужно делать.