Статьи

Push-уведомления в ионных приложениях с Google Cloud Messaging

Обновлено 13 января для отражения комментариев и изменений с помощью платформы облачных сообщений Google

В этом руководстве мы рассмотрим, как реализовать push-уведомления в приложении для Android с помощью Google Cloud Messaging Platform. Мы будем использовать Ionic Framework и Cordova для создания приложения. Серверный компонент будет реализован с использованием Node . Вы можете получить весь код проекта, который мы будем строить из Github .

Создайте проект консоли Google

Первый шаг — создать новый проект в консоли разработчика Google . Вам понадобится аккаунт, если у вас его нет.

новый проект

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

ключ API

Далее вас спросят, какой ключ вы хотите создать. Выберите ключ сервера, так как ключ будет в основном использоваться на сервере. Пока не добавляйте IP-адрес, пропустите шаг, ничего не добавляя, и нажмите кнопку « Создать» . Обратите внимание на полученный ключ API.

ключ API сервера

Находясь в меню API и меню авторизации , нажмите на ссылку API и выполните поиск Cloud Messaging для Android . Это необходимый API, нажмите и включите его.

включить гсм

Настройка

Создайте новое ионное приложение, которое использует пустой шаблон.

ionic start ionic-gcm blank 

Перейдите в каталог проекта и установите Push-плагин для Phonegap Builds . Это используется приложением для регистрации устройства и получения push-уведомлений, отправленных сервером.

 cordova plugin add https://github.com/phonegap-build/PushPlugin.git 

На момент написания звука не работает, когда уведомление получено. По умолчанию используется вибрация, даже если вы настроили телефон на использование звуков. Если вы хотите воспроизвести звук, вы должны изменить файл GCMIntentService.java . Вы можете найти его по следующему пути plugins / com.phonegap.plugins.PushPlugin / src / android / com / plugin / gcm

Откройте файл и добавьте следующее в строки 12 и 13.

 import android.content.res.Resources; import android.net.Uri; 

И от линий 125 до 131.

 String soundName = extras.getString("sound"); if (soundName != null) { Resources r = getResources(); int resourceId = r.getIdentifier(soundName, "raw", context.getPackageName()); Uri soundUri = Uri.parse("android.resource://" + context.getPackageName() + "/" + resourceId); mBuilder.setSound(soundUri); } 

Удалить строку 105:

 .setDefaults(defaults) 

Вы можете посмотреть этот запрос на получение ссылки.

Если вы уже добавили платформу Android, вам, возможно, потребуется обновить соответствующий файл на платформах / android / src / com / plugin / gcm / GCMIntentService.java с теми же изменениями.

Помимо Push Plugin, нам нужно установить плагин Cordova Whitelist .

 cordova plugin add cordova-plugin-whitelist 

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

 <access origin="*"/> 

Строим проект

Теперь мы можем начать строить проект.

Служба запросов

Создайте папку служб в каталоге www / js и создайте файл RequestsService.js . Это будет служба, которая передает маркер устройства на сервер. Маркер устройства необходим для отправки push-уведомлений на определенное устройство. Добавьте следующее в файл.

 (function(){ angular.module('starter') .service('RequestsService', ['$http', '$q', '$ionicLoading', RequestsService]); function RequestsService($http, $q, $ionicLoading){ var base_url = 'http://{YOUR SERVER}'; function register(device_token){ var deferred = $q.defer(); $ionicLoading.show(); $http.post(base_url + '/register', {'device_token': device_token}) .success(function(response){ $ionicLoading.hide(); deferred.resolve(response); }) .error(function(data){ deferred.reject(); }); return deferred.promise; }; return { register: register }; } })(); 

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

 (function(){ })(); 

Далее мы создаем новый угловой сервис для модуля стартера . Этот модуль был создан в файле js / app.js и назывался стартером , поэтому он упоминается здесь. Сервис зависит от $http , $q и $ionicLoading , это сервисы, предоставляемые Angular и Ionic.

 angular.module('starter') .service('RequestsService', ['$http', '$q', '$ionicLoading', RequestsService]); function RequestsService($http, $q, $ionicLoading){ ... } 

Внутри функции RequestsService объявите base_url используемый в качестве базового URL-адреса для base_url запросов на сервер. Это должен быть доступный через Интернет URL-адрес, чтобы приложение могло запрашивать его.

 var base_url = 'http://{YOUR SERVER}'; 

Если у вас нет сервера, на котором вы можете запустить серверный компонент, вы можете использовать ‘ngrok’, чтобы выставить любой порт на вашем локальном хосте в Интернет. Загрузите версию для вашей платформы со страницы загрузок проекта, распакуйте ее и запустите. Я покажу вам, как запустить ngrok позже, когда мы перейдем к серверной части.

Возвращаясь к коду. Мы создаем функцию register которая отправит POST запрос на сервер для регистрации устройства с помощью токена устройства из push-плагина.

 function register(device_token){ var deferred = $q.defer(); //run the function asynchronously $ionicLoading.show(); //show the ionic loader animation //make a POST request to the /register path and submit the device_token as data. $http.post(base_url + '/register', {'device_token': device_token}) .success(function(response){ $ionicLoading.hide(); //hide the ionic loader deferred.resolve(response); }) .error(function(data){ deferred.reject(); }); return deferred.promise; //return the result once the POST request returns a response }; 

Наконец, мы используем шаблон модуля выявления, чтобы представить метод register как открытый метод RequestsService .

 return { register: register }; 

Добавьте javascript в index.html сразу после ссылки на файл app.js.

 <script src="js/services/RequestsService.js"></script> 

Откройте каталог plugin / com.phonegap.plugins.PushPlugin / www и скопируйте файл PushNotification.js в папку www / js . Добавьте ссылку на него в файле index.html сразу после ссылки на файл css / style.css .

 <script type="text/javascript" charset="utf-8" src="js/PushNotification.js"></script> 

Регистрация устройства

В файле app.js создайте глобальную переменную для Push Plugin. Добавьте этот код сразу после закрывающей скобки для функции $ionicPlatform.ready .

 pushNotification = window.plugins.pushNotification; 

Чтобы зарегистрировать устройство, вызовите функцию register . Эта функция принимает 3 аргумента. Первый — это функция, выполняемая после получения уведомления, второй — функция, выполняемая в случае возникновения ошибки, и третий — параметры. Параметры — это объект, в котором вы указываете конфигурацию для push-уведомления, которое будет получено. Из приведенного ниже кода вы можете увидеть badge (значок в уведомлении), sound и alert (текст в уведомлении). ecb — это функция обратного вызова события, которая выполняется каждый раз при получении уведомления. Это та же функция, что и в первом аргументе. Наконец, senderId — это идентификатор проекта, который вы создали ранее в консоли Google. Вы можете найти его, нажав на меню Обзор вашего проекта.

Чтобы зарегистрировать устройство, вызовите функцию register . Эта функция принимает 3 аргумента. Первая — это функция, которая будет выполняться после получения уведомления, вторая — это функция, которая будет выполняться в случае возникновения ошибки, а третья — это параметры. Параметры — это объект, в котором вы указываете различные параметры для push-уведомлений, которые будут получены. Из приведенного ниже кода видно, что вы можете включить badge (значок в уведомлении), sound alert или alert (текст в уведомлении). ecb — это функция обратного вызова события, которая выполняется каждый раз при получении уведомления. Это в основном та же функция, что и в первом аргументе. Наконец, senderId — это номер проекта, который вы создали ранее в консоли Google. Вы можете найти его, нажав на меню Обзор вашего проекта.

Добавьте этот код в app.js :

 pushNotification.register( onNotification, errorHandler, { 'badge': 'true', 'sound': 'true', 'alert': 'true', 'ecb': 'onNotification', 'senderID': 'YOUR GOOGLE CONSOLE PROJECT NUMBER', } ); 

Получение уведомлений

Функция onNotification должна быть присоединена к объекту window чтобы плагин мог его найти. Аргумент, переданный этой функции, является фактическим уведомлением. Вы можете проверить, какой тип события произошел, извлекая свойство event .

Это может иметь 3 возможных значения: registered , message и error . registered событие вызывается при регистрации устройства. Событие message при получении push-уведомления, когда приложение находится на переднем плане. И error когда произошла ошибка. Когда registered событие regid , проверьте, больше ли длина regid чем 0.

Если это так, предположите, что верный токен устройства был возвращен. Вызовите функцию register в службе RequestsService и передайте device_token в качестве аргумента. Как только он возвращает ответ, сообщите пользователю, что устройство было зарегистрировано.

Добавьте этот код в app.js :

 window.onNotification = function(e){ switch(e.event){ case 'registered': if(e.regid.length > 0){ var device_token = e.regid; RequestsService.register(device_token).then(function(response){ alert('registered!'); }); } break; case 'message': alert('msg received: ' + e.message); /* { "message": "Hello this is a push notification", "payload": { "message": "Hello this is a push notification", "sound": "notification", "title": "New Message", "from": "813xxxxxxx", "collapse_key": "do_not_collapse", "foreground": true, "event": "message" } } */ break; case 'error': alert('error occured'); break; } }; 

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

Добавьте этот код в app.js :

 window.errorHandler = function(error){ alert('an error occured'); } 

Играть звуки

Если вы хотите воспроизводить звук при получении уведомления, нам нужно добавить mp3-файл в папку platform / android / res / raw . Моя названа уведомлением .mp3 . Запишите имя файла, и мы добавим его на серверную часть позже, когда отправим уведомление. Вы можете скачать некоторые звуки уведомлений здесь .

Сторона сервера

Сервер отвечает за прием токена устройства, отправленного из приложения, а также за отправку push-уведомлений.

Создайте папку сервера внутри корневого каталога проекта, затем создайте файл ionic-gcm.js . Это файл, который будет содержать код для запуска сервера узла. Этот файл имеет три зависимости: express , node-gcm и body-parser . Установите те, кто использует npm.

 npm install express node-gcm body-parser 

Откройте файл ionic-gcm.js и запросите эти зависимости.

 var express = require('express'); var gcm = require('node-gcm'); 

Используйте экспресс.

 var app = express(); 

Создайте сервер, который прослушивает запросы на порт 3000.

 var server = app.listen(3000, function(){ console.log('server is running'); }); 

Настройте сервер для разрешения всех источников запросов. Это позволяет AJAX-запросам приходить с любого IP-адреса.

 app.use(function(req, res, next){ res.header("Access-Control-Allow-Origin", "*"); res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept"); next(); }); 

Создайте глобальную переменную для хранения текущего токена устройства. Это будет обновлено при доступе к маршруту /register . И текущее значение будет использоваться при доступе к маршруту /push .

 var device_token; 

Создайте новый маршрут для пути /register . Это маршрут для регистрации устройства. Вы можете получить доступ к device_token который был передан через свойство body в объекте req .

Обратите внимание, что я не добавил ни одного кода, связанного с сохранением токена устройства в базе данных. Я ожидаю, что у вас есть свой собственный, поэтому я положил его там как TODO. На данный момент он использует глобальную переменную device_token для хранения токена устройства. После того, как вы сохранили device_token , отправьте ok в качестве ответа.

 app.post('/register', function(req, res){ device_token = req.body.device_token; console.log('device token received'); console.log(device_token); /*YOUR TODO: save the device_token into your database*/ res.send('ok'); }); 

Чтобы отправить push-уведомления :

  1. Создайте маршрут для пути /push .
  2. В функции обратного вызова создайте новый массив, в котором будут храниться токены устройства, и переменную, в которой будет храниться количество попыток отправки сообщения.
  3. Создайте новый экземпляр отправителя, вызвав функцию Sender . Это принимает ключ API из консоли Google.
  4. Создайте новое сообщение, вызвав функцию Message в объекте gcm . Этот объект предоставляется пакетом node-gcm .
  5. Добавьте данные для передачи в push-уведомлении, вызвав функцию addData сообщения. Эта функция принимает пару ключ-значение данных для передачи. Необходимые ключи — title и message . title — это заголовок push-уведомления, а message — содержимое. В приведенном ниже примере sound клавиша также передается. Это имя звукового файла, который вы хотите воспроизвести при получении уведомления.
  6. При желании вы можете установить collapseKey для групповых уведомлений. Это позволяет отправлять уведомление № 1 с помощью collapseKey а затем через несколько минут — уведомление № 2 с таким же collapseKey . Что произойдет, так это то, что уведомление № 2 заменит уведомление № 1. То есть, если пользователь все еще не открыл уведомление № 1, когда приходит уведомление № 2.
  7. delayWhileIdle — еще одно необязательное свойство, если для него установлено значение true , уведомление не отправляется немедленно, если устройство не используется. Это означает, что сервер ожидает активации устройств, прежде чем отправит уведомление. Обратите внимание, что если установлен collapseKey , сервер будет отправлять только самые последние отправленные сообщения, содержащие этот collapseKey . Наконец, есть timeToLive который позволяет установить количество секунд, в течение которых сообщение будет храниться на сервере, когда принимающее устройство отключено. Если вы указываете это свойство, вам также нужно указать collapseKey .
  8. Это еще один шаг, который я ожидаю от вас самостоятельно. device_token из базы данных. Чтобы сделать это, вам нужно передать user_id или другой уникальный идентификатор пользователя. Это позволит вам извлечь device_token , используя эти уникальные данные в качестве ключа. В приведенном ниже примере вместо этого используется значение глобальной переменной device_token . Таким образом, каждый раз, когда регистрируется новое устройство, оно будет тем, которое получит уведомление.
  9. Вставьте полученный из базы данных device_tokens массив device_tokens .
  10. Вызовите функцию send в объекте message . Это принимает message device_tokens , retry_times и функцию для вызова после отправки сообщения.
  11. Отправьте ok ответ.
 app.get('/push', function(req, res){ var device_tokens = []; //create array for storing device tokens var retry_times = 4; //the number of times to retry sending the message if it fails var sender = new gcm.Sender('THE API KEY OF YOUR GOOGLE CONSOLE PROJECT'); //create a new sender var message = new gcm.Message(); //create a new message message.addData('title', 'New Message'); message.addData('message', 'Hello this is a push notification'); message.addData('sound', 'notification'); message.collapseKey = 'testing'; //grouping messages message.delayWhileIdle = true; //delay sending while receiving device is offline message.timeToLive = 3; //the number of seconds to keep the message on the server if the device is offline /* YOUR TODO: add code for fetching device_token from the database */ device_tokens.push(device_token); sender.send(message, device_tokens, retry_times, function(result){ console.log(result); console.log('push sent to: ' + device_token); }); res.send('ok'); }); 

Запустите сервер, вызвав его из терминала:

 node ionic-gcm.js 

Если вы хотите использовать ngrok для показа этого сервера в Интернете, откройте новое окно терминала, в котором вы установили ngrok, и выполните следующую команду:

 ngrok http 3000 

Это говорит ngrok об открытии порта 3000 для Интернета и назначении ему общедоступного URL.

Развертывание приложения

Возвращаясь к приложению. Перейдите в корневой каталог приложения и обновите base_url в www / js / services / RequestsService.js, чтобы он соответствовал URL-адресу, предоставленному ngrok.

 var base_url = 'http://{YOUR SERVER}'; 

Добавьте платформу Android:

 cordova platform add android 

Не забудьте добавить mp3-файл в каталог platform / android / res / raw, чтобы звук работал.

Создайте приложение, выполнив следующую команду:

 cordova build android 

После этого перейдите в каталог платформы / android / build / output / apk / и скопируйте файл android-debug.apk на ваше устройство Android. Установите и откройте его. После открытия он должен переслать токен устройства на сервер.

Он должен показать что-то похожее на следующее в окне терминала, где вы выполнили node ionic-gcm.js :

 device token received sjdlf0ojw3ofjowejfowefnosfjlsjfosnf302r3n2on3fon3flsnflsfns0f9un 

Теперь вы можете проверить push-уведомление, открыв следующий локальный URL-адрес в браузере:

 http://localhost:3000/push 

В этот момент ваше устройство должно получить push-уведомление. Вот скриншот.

уведомление

Вывод

Это оно! Из этого руководства вы узнали, как работать с платформой Google Cloud Messaging для Android, чтобы отправлять push-уведомления в приложение Cordova. Если у вас есть какие-либо вопросы, комментарии или проблемы, пожалуйста, дайте мне знать в комментариях ниже.