Как начать работу с Push-уведомлениями на Android
() translation by (you can also view the original English article)
Введение
Получение пользователей для установки вашего приложения - это только половина битвы. Получение их для регулярного использования - это другая половина. Вполне возможно, что ваши пользователи полностью забывают о вашем приложении после использования его только один или два раза. Что со всеми другими новыми приложениями, конкурирующими за их внимание.
Используя push-уведомления, вы можете время от времени напоминать пользователям о своем приложении, повышая вероятность того, что ваше приложение останется на их устройствах.
Google Cloud Messaging, GCM для краткости - это бесплатный сервис, который вы можете использовать для отправки push-уведомлений вашим пользователям. В этом уроке вы узнаете, как использовать его для создания приложения для Android, которое может получать push-уведомления, и простой Python скрипт на стороне сервера, который может их генерировать и отправлять.
Зачем использовать Google Cloud Messaging?
Для большинства клиент-серверных сообщений клиент инициирует запросы на получение данных с сервера. Другими словами, клиент извлекает данные с сервера. В случае push-уведомлений, однако, это сервер, инициирующий передачу данных.
Обычно это достигается за счет поддержания постоянного TCP/IP-соединения - соединения, которое остается постоянно открытым между сервером и клиентом. Это может показаться замечательным, но если у вас популярное приложение, поддержка тысяч постоянных соединений между вашим сервером и устройствами ваших пользователей может быть очень дорогостоящим.
Google Cloud Messaging - это служба, которая решает эту проблему, выступая в качестве посредника между вашим сервером и устройством вашего пользователя. С помощью GCM Google’s Cloud Connection Server, часто называемый CCS, управляет постоянными подключениями для вас. Он также обеспечивает надежную доставку ваших push-уведомлений.
Предпосылки
Чтобы следовать за мной, вам нужно:
- Последняя версия Android Studio
- Python 2.7.6 или выше
- Устройство под управлением Android 4.4 или выше с установленными сервисами Google Play
1. Настройка проекта Android Studio
Запустите Android Studio и создайте новый проект с пустой Activity
. Если вы использовали значения по умолчанию, проект должен включать класс Java в MainActivity.java.
Шаг 1: добавьте зависимости
В этом проекте мы будем использовать Google Services gradle plugin для настройки GCM. Включите его в проект, добавив следующую строку в раздел dependencies
в build.gradle проекта:
1 |
classpath 'com.google.gms:google-services:1.5.0' |
Затем примените плагин в модуле app
build.gradle:
1 |
apply plugin: 'com.google.gms.google-services' |
Чтобы иметь возможность использовать API GCM, добавьте com.google.android.gms: play-services
Как compile
зависимость в том же файле:
1 |
compile "com.google.android.gms:play-services:8.3.0" |
Если вы нажмете кнопку «Синхронизировать сейчас», вы увидите следующую ошибку:



Чтобы исправить ошибку, нажмите ссылку «Установить репозиторий и синхронизировать проект».
Шаг 2: обновите манифест
Внутри файла AndroidManifest.xml проекта создайте и используйте специальное разрешение C2D_MESSAGE на основе имени пакета вашего проекта. Убедитесь, что для параметра ProtectionLevel
установлено разрешение в значение signature.
1 |
<permission
|
2 |
android:name="com.github.hathibelagal.pn.permission.C2D_MESSAGE" |
3 |
android:protectionLevel="signature" /> |
4 |
<uses-permission
|
5 |
android:name="com.github.hathibelagal.pn.permission.C2D_MESSAGE" /> |
Уведомления поступают в виде трансляций. Для обработки этих трансляций нашему приложению требуется BroadcastReceiver
. Однако нам не нужно создавать его вручную. Вместо этого мы можем использовать класс GcmReceiver
как BroadcastReceiver
.
У BroadcastReceiver
должен быть intent-filter
, который отвечает на действие com.google.android.c2dm.intent.RECEIVE
, а имя его category
должно соответствовать имени пакета вашего проекта. Добавьте в манифест следующий код:
1 |
<receiver
|
2 |
android:name="com.google.android.gms.gcm.GcmReceiver" |
3 |
android:exported="true" |
4 |
android:permission="com.google.android.c2dm.permission.SEND" > |
5 |
<intent-filter>
|
6 |
<action android:name="com.google.android.c2dm.intent.RECEIVE" /> |
7 |
<category android:name="com.github.hathibelagal.pn" /> |
8 |
</intent-filter>
|
9 |
</receiver>
|
2. Получите ключ API сервера и идентификатор отправителя
При общении с сервером облачных соединений нам необходимо идентифицировать себя с помощью ключа API на стороне сервера и идентификатора отправителя на стороне клиента. Чтобы получить ключ API и идентификатор отправителя, создайте новый проект в консоли разработчика.



Начните с нажатия кнопки «Выбрать платформу». Затем нажмите кнопку «Включить службы для моего приложения Android App». Когда вы это сделаете, вас попросят указать ваше имя и имя пакета Android для вашего приложения. Убедитесь, что указанное вами имя пакета Android соответствует имени пакета, которое вы ввели при создании проекта Android Studio.



Затем нажмите кнопку «Выбрать и настроить службы» внизу. Теперь вы можете выбрать сервисы Google, которые хотите добавить в приложение.



На данный момент нажмите кнопку «Облачные сообщения», а затем нажмите «Включить облачные сообщения Google». Через несколько секунд вам будет предоставлен ключ API сервера и идентификатор отправителя. Запишите ключ API сервера и нажмите «Закрыть».



Плагин Google Services, который мы добавили ранее, требует правильной работы файла конфигурации. Создайте файл, нажав кнопку «Создать конфигурационные файлы».
После того, как файл был сгенерирован, загрузите его и поместите в каталог app проекта Android Studio.
3. Регистрация клиента
GCM идентифицирует устройства Android с помощью токенов регистрации. Поэтому наше приложение должно иметь возможность регистрироваться на каждом Android-устройстве, на котором оно установлено.
Шаг 1. Создание службы регистрации
Регистрация должна выполняться в фоновом потоке, потому что процесс может занять некоторое время в зависимости от сетевого подключения. Поскольку регистрация не требует каких-либо входных данных от пользователя, IntentService
идеально подходит для этой задачи.
Создайте новый класс Java под названием RegistrationService.java, сделайте его подклассом IntentService
и переопределите его метод onHandleIntent
.
1 |
public class RegistrationService extends IntentService { |
2 |
public RegistrationService() { |
3 |
super("RegistrationService"); |
4 |
}
|
5 |
|
6 |
@Override
|
7 |
protected void onHandleIntent(Intent intent) { |
8 |
|
9 |
}
|
10 |
}
|
Внутри метода onHandleIntent
мы можем использовать API идентификатора экземпляра для создания или получения регистрационного токена. Во-первых, создайте экземпляр класса InstanceID
, используя его метод getInstance
.
1 |
InstanceID myID = InstanceID.getInstance(this); |
Теперь мы можем использовать метод getToken
объекта InstanceID
для получения регистрационного токена в виде String
. GetToken
ожидает идентификатор отправителя как один из его аргументов. Поскольку мы добавили файл google-services.json в наш проект, мы можем передать идентификатор отправителя методу, используя R.string.gcm_defaultSenderID
.
1 |
String registrationToken = myID.getToken( |
2 |
getString(R.string.gcm_defaultSenderId), |
3 |
GoogleCloudMessaging.INSTANCE_ID_SCOPE, |
4 |
null
|
5 |
);
|
Если вы хотите видеть содержимое токена регистрации для целей отладки, вы можете зарегистрировать его как отладочное сообщение, используя метод Log.d
.
1 |
Log.d("Registration Token", registrationToken); |
На этом этапе вы можете отправить токен регистрации на свой веб-сервер и сохранить его в базе данных. Однако вам не нужно это делать, если вы не планируете обращаться к своим пользователям по отдельности. Если вы планируете отправлять одно и то же сообщение каждому пользователю, вы должны следовать принципу публикации подписки.
Теперь я покажу вам, как подписаться на topic
под названием my_little_topic. Требуется всего две строки кода. Сначала создайте новый экземпляр класса GcmPubSub
, используя его метод getInstance
. Затем вызовите его метод subscribe
и передайте ему токен регистрации вместе с названием темы.
1 |
GcmPubSub subscription = GcmPubSub.getInstance(this); |
2 |
subscription.subscribe(registrationToken, "/topics/my_little_topic", null); |
Теперь наше приложение может получать каждое push-уведомление, опубликованное в my_little_topic.
Наконец, определите службу в AndroidManifest.xml.
1 |
<service android:name=".RegistrationService" |
2 |
android:exported="false" /> |
Служба регистрации завершена.
Шаг 2. Создание службы InstanceIDListenerService
Токены регистрации периодически обновляются. Следовательно, каждое приложение для Android, использующее GCM, должно иметь InstanceIDListenerService
, который может обрабатывать эти обновления. Поэтому создайте новый файл Java под названием TokenRefreshListenerService.java и сделайте его подклассом InstanceIDListenerService
. Внутри метода onTokenRefresh
этого класса все, что нам нужно сделать, это просто начать процесс регистрации снова, запустив службу регистрации с использованием метода Intent
и startService
.
Добавьте следующий код в TokenRefreshListenerService.java:
1 |
public class TokenRefreshListenerService extends InstanceIDListenerService { |
2 |
@Override
|
3 |
public void onTokenRefresh() { |
4 |
Intent i = new Intent(this, RegistrationService.class); |
5 |
startService(i); |
6 |
}
|
7 |
}
|
Эта служба должна иметь возможность реагировать на действие com.google.android.gms.iid.InstanceID
. Поэтому, определяя службу в AndroidManifest.xml, добавьте соответствующий intent-filter
.
1 |
<service
|
2 |
android:name=".TokenRefreshListenerService" |
3 |
android:exported="false"> |
4 |
<intent-filter>
|
5 |
<action android:name="com.google.android.gms.iid.InstanceID" /> |
6 |
</intent-filter>
|
7 |
</service>
|
Шаг 3: Запуск службы регистрации
Чтобы процесс регистрации начался сразу после запуска приложения, мы должны запустить класс RegistrationService
внутри метода onCreate
уMainActivity
. Для этого создайте для него Intent
и используйте метод startService
.
1 |
Intent i = new Intent(this, RegistrationService.class); |
2 |
startService(i); |
4. Отображение Push-уведомлений
GCM автоматически отображает push-уведомления в лоток уведомлений, как только они будут получены. Однако он делает это только в том случае, если связанное приложение содержит GCMListenerService
.
Создайте новый класс Java с именем NotificationsListenerService и сделайте его подклассом GCMListenerService
. Если вы не хотите обрабатывать вставленные данные самостоятельно, вам не нужно писать код внутри этого класса. Мы можем оставить этот класс пустым.
1 |
public class NotificationsListenerService extends GcmListenerService { |
2 |
|
3 |
}
|
Определяя службу в AndroidManifest.xml, убедитесь, что вы добавили intent-filter
, который позволяет ему отвечать на com.google.android.c2dm.intent.RECEIVE
.
1 |
<service
|
2 |
android:name=".NotificationsListenerService" |
3 |
android:exported="false" > |
4 |
<intent-filter>
|
5 |
<action android:name="com.google.android.c2dm.intent.RECEIVE" /> |
6 |
</intent-filter>
|
7 |
</service>
|
5. Добавление значков Push Notification
У каждого push-уведомления должен быть связанный с ним значок. Если у вас нет такой возможности, вы можете получить ее в Material Design Icons Library.



Как только вы загрузите значок, поместите его в папку res вашего проекта. Я буду использовать ic_cloud_white_48dp в качестве значка.
6. Запуск приложения для Android
Теперь наше Android-приложение завершено. После того, как вы скомпилируете его и запустите на Android-устройстве, вы сможете увидеть маркер регистрации в логах logcat.



Нажмите кнопку «Назад» на устройстве, чтобы выйти из приложения. Это необходимо, потому что GCM автоматически отображает push-уведомления только в том случае, если пользователь не использует приложение. Если вы хотите, чтобы уведомления отображались даже в том случае, когда приложение запущено, вам нужно будет создать уведомления самостоятельно в NotificationsListenerService
с помощью класса Notification.Builder
.
7. Отправка Push-уведомлений
В заключительной части этого учебника мы создадим простой Python скрипт, который может генерировать и отправлять push-уведомления всем устройствам Android, на которых установлено наше приложение.
Вы можете запустить этот скрипт с локального компьютера или с удаленного веб-сервера, к которому у вас есть доступ к SSH.
Шаг 1. Создание сценария
Создайте новый файл с именем send.py и откройте его, используя ваш любимый текстовый редактор.
В верхней части файла импортируйте модули urllib2
и urllib
. Мы будем использовать эти модули для отправки данных на Google Cloud Connection Server. Импортируйте модуль json
, потому что отправляемые данные должны быть действительными JSON. Наконец, чтобы получить доступ к аргументам командной строки, импортируйте модуль sys
.
1 |
from urllib2 import * |
2 |
import urllib |
3 |
import json |
4 |
import sys |
Затем создайте переменную, в которой хранится ключ API сервера, который вы записали ранее. Ключ должен быть частью каждого HTTP-запроса, который мы делаем в CCS.
1 |
MY_API_KEY="ABCDEF123456789ABCDE--12A" |
Каждое уведомление должно иметь название и тело. Вместо жесткого кодирования в нашем скрипте давайте примем название и тело как аргументы командной строки, используя массив argv
.
1 |
messageTitle = sys.argv[1] |
2 |
messageBody = sys.argv[2] |
Создайте новый словарь Python для представления данных, которые должны быть отправлены в CCS. Чтобы наше приложение для Android могло получать уведомление, оно должно быть опубликовано в тему my_little_topic. Поэтому добавьте ключ to в словарь, и установите его значение в /themes/my_little_topic.
Чтобы представить содержимое уведомления, добавьте ключ, называемый notification в словарь, и установите его значение для другого словарного объекта, содержащего три ключа:
- body
- title
- icon
Убедитесь, что значение icon
совпадает с именем значка, который можно использовать в вашем проекте Android.
1 |
data={ |
2 |
"to" : "/topics/my_little_topic", |
3 |
"notification" : { |
4 |
"body" : messageBody, |
5 |
"title" : messageTitle, |
6 |
"icon" : "ic_cloud_white_48dp" |
7 |
}
|
8 |
}
|
Преобразуйте словарь в строку JSON, используя функцию dumps
модуля json
:
1 |
dataAsJSON = json.dumps(data) |
Все, что нам нужно сделать, это отправить строку JSON на https://gcm-http.googleapis.com/gcm/send. Для этого создайте новый объект Request
и установите dataAsJSON
в качестве своих данных. Затем установите заголовок Authorization
в MY_API_KEY
и заголовок Content-type
в application/json.
1 |
request = Request( |
2 |
"https://gcm-http.googleapis.com/gcm/send", |
3 |
dataAsJSON, |
4 |
{ "Authorization" : "key="+MY_API_KEY, |
5 |
"Content-type" : "application/json" |
6 |
}
|
7 |
)
|
Наконец, чтобы выполнить запрос и получить ответ, передайте объект запроса функции urlopen
и вызовите его метод read
.
1 |
print urlopen(request).read() |
Теперь скрипт Python завершен и готов к использованию.
Шаг 2. Запуск сценария
На этом этапе мы готовы отправить push-уведомления всем устройствам, на которых установлено наше приложение. Откройте терминал и введите каталог, в котором вы создали send.py.
Передайте имя сценария исполняемому файлу python
вместе со строкой для заголовка уведомления, а другое - для тела уведомления. Вот пример, который вы можете использовать:
1 |
python send.py "My first push notification" "GCM API is wonderful!" |
Если ошибок нет, вы должны получить ответ, который выглядит так:
1 |
{"message_id":12345676892321} |
Если вы проверите свое Android-устройство, вы увидите новое уведомление в лотке уведомлений.



Заключение
Теперь вы знаете, как отправлять push-уведомления своим пользователям. На этом занятии вы узнали, как создать Android-приложение, способное регистрироваться и получать уведомления, публикуемые по определенной теме. Вы также узнали, как создать скрипт Python, который может публиковать уведомления.
Несмотря на то, что push-уведомления могут показаться отличным способом общения с вашими пользователями, я предлагаю вам использовать их экономно и только если у вас есть что-то полезное, потому что слишком много слишком часто - это, пожалуй, самый быстрый способ чтобы ваше приложение оказалось удаленным.
Чтобы узнать больше о облачных сообщениях Google, см. Руководство по облачным сообщениям.