Статьи

Кодирование приложения реального времени с помощью NativeScript: push-уведомления

NativeScript — это платформа для создания кроссплатформенных собственных мобильных приложений с использованием XML, CSS и JavaScript. В этой серии мы попробуем некоторые интересные вещи, которые вы можете сделать с помощью приложения NativeScript: геолокация и интеграция с Google Maps, база данных SQLite, интеграция с Firebase и push-уведомления. Попутно мы создаем фитнес-приложение с возможностями реального времени, которое будет использовать каждую из этих функций.

Из этого руководства вы узнаете, как легко добавлять push-уведомления в приложение NativeScript с помощью службы Firebase Cloud Messaging Service.

Продолжая предыдущий урок, вы добавите push-уведомления в приложение. Уведомление будет инициировано, когда пользователь побьет свою текущую запись или когда один из его друзей отойдет от них на первое место.

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

1
tns create fitApp —appid «com.yourname.fitApp»

После этого вам также необходимо установить плагины геолокации, Google Maps, SQLite и Firebase:

1
2
3
4
tns plugin add nativescript-geolocation
tns plugin add nativescript-google-maps-sdk
tns plugin add nativescript-sqlite
tns plugin add nativescript-plugin-firebase

После установки вам необходимо настроить плагин Google Maps. Вы можете прочитать подробные инструкции о том, как это сделать, прочитав раздел « Установка плагина Google Maps» в предыдущем руководстве .

Далее установите библиотеку fecha для форматирования дат:

1
npm install —save fecha

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

  • Запуск проекта
  • Настройка приложения Firebase
  • Настройка приложения Facebook
  • Установка плагина Firebase
  • Настройка интеграции с Facebook

Поскольку мы уже настроили плагин Firebase в предыдущем посте, для настройки push-уведомлений необходимо выполнить лишь небольшую работу.

Во-первых, вам нужно перенастроить плагин, зайдя в каталог node_modules / nativescript-plugin-firebase и запустив npm run config . На этот раз выберите как аутентификацию Facebook, так и обмен сообщениями.

Как только это будет сделано, откройте файл firebase.nativescript.json в корневом каталоге вашего проекта и убедитесь, что для messaging установлено значение true :

01
02
03
04
05
06
07
08
09
10
11
12
{
    «using_ios»: false,
    «using_android»: true,
    «remote_config»: false,
    «messaging»: true,
    «crash_reporting»: false,
    «storage»: false,
    «facebook_auth»: true,
    «google_auth»: false,
    «admob»: false,
    «invites»: false
}

Затем откройте app / App_Resources / Android / AndroidManifest.xml и добавьте следующие сервисы в <application> . Это включает службу обмена сообщениями Firebase для приложения:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
<application …>
 
<service android:name=»org.nativescript.plugins.firebase.MyFirebaseInstanceIDService»>
    <intent-filter>
        <action android:name=»com.google.firebase.INSTANCE_ID_EVENT»/>
    </intent-filter>
</service>
<service android:name=»org.nativescript.plugins.firebase.MyFirebaseMessagingService»>
    <intent-filter>
        <action android:name=»com.google.firebase.MESSAGING_EVENT»/>
    </intent-filter>
</service>
 
</application>

Вы можете запустить проект, выполнив tns run android . Но так как это приложение будет основано на функциональности геолокации, я рекомендую использовать эмулятор GPS для быстрой настройки и изменения вашего местоположения. О том, как это сделать, вы можете прочитать в разделе « Запуск приложения» в предыдущем руководстве .

Если вы получили какие-либо ошибки сборки, вы можете удалить платформу и перезапустить приложение:

1
2
tns platform remove android
tns run android

Вы будете использовать Firebase Cloud Functions для создания сервера, который будет отправлять push-уведомления. Эта функция Firebase используется для запуска внутреннего кода всякий раз, когда в используемых вами функциях Firebase происходит определенное событие, например, если в базе данных реального времени сохраняются новые данные или когда через пользователя добавляется новый пользователь. Сервис аутентификации Firebase. Для этого приложения вы будете использовать HTTP-триггеры для отправки push-уведомлений, когда мобильное приложение отправляет запрос определенной конечной точке.

Чтобы использовать облачные функции Firebase, сначала необходимо установить пакет firebase-tools глобально:

1
npm install -g firebase-tools

Затем создайте новую папку, в которой будет размещен код сервера. Это должно быть вне папки вашего приложения. Внутри этой папки установите пакет firebase-functions :

1
npm install firebase-functions@latest —save

После установки войдите в Firebase, запустив firebase login . Это открывает новую вкладку браузера, которая позволяет вам войти в систему с вашей учетной записью Google. Пройдите весь процесс и согласитесь на все запрашиваемые разрешения.

После входа в систему вы можете инициализировать функции Firebase для конкретного проекта Firebase:

1
firebase init functions

Это спросит вас, хотите ли вы создать проект по умолчанию или нет. Выберите проект Firebase, который вы создали в предыдущем уроке:

настроить функции firebase

Далее вас спросят, хотите ли вы установить зависимости. Скажи да.

После того, как все зависимости установлены, вы должны увидеть файл firebase.json и папку функций внутри каталога. Файл, над которым вы будете работать, это файл functions / index.js . Откройте этот файл, и вы увидите следующее:

1
2
3
4
5
6
7
8
const functions = require(‘firebase-functions’);
 
// // Create and Deploy Your First Cloud Functions
// // https://firebase.google.com/docs/functions/write-firebase-functions
//
// exports.helloWorld = functions.https.onRequest((request, response) => {
// response.send(«Hello from Firebase!»);
// });

Раскомментируйте функцию helloWorld , и вы увидите триггеры HTTP в действии.

1
2
3
exports.helloWorld = functions.https.onRequest((request, response) => {
    response.send(«Hello from Firebase!»);
});

Запустите следующее для развертывания функции в облаке:

1
firebase deploy —only functions

После завершения развертывания он должен показать вам URL, на котором была развернута функция:

развернуть функции firebase

Получите доступ к этому URL из вашего браузера, чтобы увидеть вывод «Hello from Firebase!»

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

Откройте файл functions / index.js и очистите его содержимое.

Импортируйте пакеты Firebase, которые вам понадобятся:

1
2
3
const functions = require(‘firebase-functions’);
const admin = require(‘firebase-admin’);
admin.initializeApp(functions.config().firebase);

Создайте функцию init_push . Обратите внимание, что триггер HTTP вызывается для любого метода запроса, поэтому вам нужно отфильтровать метод запроса, который вы хотите обработать. В этом случае мы хотим обрабатывать только POST запросы. Мы ожидаем, что приложение отправит id , steps и friend_ids в качестве данных запроса.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
exports.init_push = functions.https.onRequest((request, response) => {
     
    if(request.method == ‘POST’){
 
        var id = request.body.id;
        var steps = parseInt(request.body.steps);
        var friend_ids = request.body.friend_ids.split(‘,’);
 
        friend_ids.push(id);
 
        // next: add code for getting the user and friends data
    }
 
});

Затем запросите базу данных Firebase, чтобы проверить, существует ли идентификатор пользователя. Это служит способом защиты конечной точки, поэтому не каждый может запускать push-уведомления. (Конечно, реальное приложение должно иметь гораздо лучшую внутреннюю безопасность, чтобы пользователи не могли подделывать свои собственные данные или данные кого-то другого.)

Если пользователь существует, запросите базу данных еще раз, чтобы она вернула всех пользователей. Обратите внимание, что Firebase в настоящее время не предоставляет способ возврата записей на основе массива идентификаторов, поэтому нам придется самостоятельно отфильтровать соответствующие данные:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
admin.database().ref(‘/users’)
    .orderByChild(‘id’)
    .limitToFirst(1)
    .equalTo(id)
    .once(‘value’).then(snapshot => {
     
    var user_data = snapshot.val();
 
    if(user_data){
        // get all users from the database
        admin.database().ref(‘/users’)
            .once(‘value’).then(snapshot => {
            // next: add code for getting the current user’s data and their friends data
        });
    }
});

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

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
var friends_data = [];
var current_user_data = null;
var notification_data = {};
var has_notification = false;
 
var users = snapshot.val();
for(var key in users){
    var user_id = users[key].id;
     
    if(friend_ids.indexOf(user_id) != -1 && id != user_id){ // the current user’s friends
        friends_data.push(users[key]);
    }else if(id == user_id){ // the current user
        current_user_data = users[key];
    }
}
 
// sort in descending order by the number of steps
var sorted_friends_data = friends_data.sort(function(a, b) {
    return b.steps — a.steps;
});
 
// next: add code for constructing the notification payload

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

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
if(steps > sorted_friends_data[0].steps){
    // notify friend who was overtaken
    var diff_steps = steps — sorted_friends_data[0].steps;
    notification_data = {
        payload: {
            title: ‘One of your friends beat your record’,
            body: ‘Too bad, your friend ‘ + current_user_data.user_name + ‘ just overtook you by ‘ + diff_steps + ‘ steps’
        },
        device_token: sorted_friends_data[0].device_token
    };
    has_notification = true;
     
}else if(steps > current_user_data.steps){
    // notify current user
    var diff_steps = steps — current_user_data.steps;
    notification_data = {
        payload: {
            title: ‘You beat your record!’,
            body: ‘Congrats!
        },
        device_token: current_user_data.device_token
    };
    has_notification = true;
}
 
// next: add code for sending push notification

Наконец, отправьте уведомление:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
if(has_notification){
     
    var payload = {
      notification: notification_data.payload
    };
     
    // send push notification
    admin.messaging().sendToDevice(notification_data.device_token, payload).then(function(res) {
         
        response.send(JSON.stringify({‘has_notification’: true}));
    })
    .catch(function(error) {
        response.send(JSON.stringify(error));
    });
 
}else{
    response.send(JSON.stringify({‘has_notification’: false}));
}

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

Первое, что вам нужно сделать для получения push-уведомлений, это обновить функцию firebase.init() чтобы включить прослушиватель для получения токена устройства:

1
2
3
4
5
onPushTokenReceivedCallback: function(token) {
    // temporarily save it to application settings until such time that
    // the user logs in for the first time
    applicationSettings.setString(‘device_token’, token);
},

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

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

1
2
3
4
5
6
7
onMessageReceivedCallback: function(message) {
    dialogs.alert({
        title: message.title,
        message: message.body,
        okButtonText: «ok»
    });
},

Firebase Cloud Messaging требует токен устройства при отправке push-уведомления на определенное устройство. Поскольку мы уже используем Firebase, мы просто сохраним токен устройства вместе с пользовательскими данными. Для этого вам нужно отредактировать код для сохранения данных пользователя, включив в него токен устройства, который мы получили ранее:

01
02
03
04
05
06
07
08
09
10
11
12
if(firebase_result.value == null){
 
    var device_token = applicationSettings.getString(‘device_token’);
 
    var user_data = {
        ‘uid’: fb_result.uid,
        ‘user_name’: fb_result.name,
        ‘profile_photo’: fb_result.profileImageURL,
        ‘device_token’: device_token
    };
 
}

Push-уведомления запускаются, когда происходит одно из двух:

  • когда пользователь побивает свою текущую запись
  • когда один из друзей пользователя побивает свой рекорд и выходит на первое место

Первый прост, поэтому нет необходимости в дополнительной настройке. Но для второго вам нужно немного поработать. Во-первых, вы должны отредактировать код, когда меняется состояние аутентификации. Сразу после извлечения идентификаторов друзей из результатов Facebook вы должны сохранить идентификаторы друзей с помощью настроек приложения.

1
2
3
4
5
6
7
8
9
// extracting the friend IDs from the Facebook result
var friends_ids = r.data.map(function(obj){
    return obj.id;
});
 
// save the friend IDs
applicationSettings.setString(‘friends_ids’, JSON.stringify(friends_ids));
 
friends_ids.push(user[user_key].id);

Затем обновите код, когда пользователь прекращает отслеживать свою прогулку. Сразу после кода для создания пользовательских данных для обновления пользователя получите идентификаторы друзей из настроек приложения и включите их в объект, который содержит данные запроса для запуска push-уведомления.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
// construct the user data for updating the user’s distance and steps
var user_key = applicationSettings.getString(‘user_key’);
var user = applicationSettings.getString(‘user’);
var user_data = JSON.parse(user);
user_data[user_key].distance = total_distance;
user_data[user_key].steps = total_steps;
 
// get friend IDs
var friends_ids = JSON.parse(applicationSettings.getString(‘friends_ids’));
 
var request_data = {
    ‘id’: user_data[user_key].id,
    ‘friend_ids’: friends_ids.join(‘,’),
    ‘steps’: total_steps
};

Сделайте запрос к конечной точке Firebase Cloud Functions, которую вы создали ранее. Как только будет получен ответ об успешном выполнении, только тогда данные пользователя будут обновлены в базе данных Firebase.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
http.request({
    url: «https://us-central1-pushapp-ab621.cloudfunctions.net/init_push»,
    method: «POST»,
    headers: { «Content-Type»: «application/json» },
    content: JSON.stringify(request_data)
}).then(function (response) {
    
    var statusCode = response.statusCode;
    if(statusCode == 200){
        // update the user’s data on Firebase
        firebase.update(
            ‘/users’,
            user_data
        );
 
    }
 
}, function (e) {
    console.log(‘Error occurred while initiating push: ‘, e);
});

Вы можете проверить отправку push-уведомлений, предварительно удалив приложение с эмулятора или устройства. Это позволяет нам правильно запустить функцию получения токена устройства. Обязательно добавьте console.log для вывода токена устройства:

1
2
3
4
onPushTokenReceivedCallback: function(token) {
    applicationSettings.setString(‘device_token’, token);
    console.log(‘device token: ‘, device_token);
}

Когда токен устройства будет выведен на консоль NativeScript, скопируйте его, щелкните меню « База данных» на панели инструментов приложения Firebase и добавьте его в качестве токена устройства всем пользователям приложения. Используйте device_token качестве имени свойства.

Чтобы вызвать push-уведомление, вы можете использовать curl, чтобы сделать POST запрос к конечной точке функции Firebase:

1
curl -X POST -H «Content-Type:application/json» YOUR_FIREBASE_FUNCTION_ENDPOINT -d ‘{«id»:»ID OF A FIREBASE USER», «steps»:NUMBER_OF_STEPS, «friend_ids»:»COMMA,SEPARATED,FIREBASE,USER_IDs»}’

Если у вас не установлен curl, вы можете использовать приложение Почтальон для отправки запроса. Используйте следующие параметры для запроса:

  • Способ запроса: POST
  • URL: ваша конечная точка функции Firebase
  • Заголовок Ключ: Content-type
  • Значение заголовков: application/json
  • Тело:
1
{«id»:»ID OF A FIREBASE USER», «steps»:NUMBER_OF_STEPS, «friend_ids»:»COMMA,SEPARATED,FIREBASE,USER_IDs»}

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

push-уведомление получено

Если приложение в данный момент не открыто, вы увидите уведомление в области уведомлений:

push-уведомление вне приложения

Поздравляем! Вы наконец-то завершили приложение для фитнеса. За четыре урока вы создали приложение NativeScript, которое использует карты Google, SQLite, базу данных Firebase Realtime и Firebase Cloud Messaging. Теперь у вас есть довольно хорошая основа для создания приложений NativeScript, использующих эти технологии.

Чтобы узнать больше о NativeScript или других кроссплатформенных мобильных технологиях, обязательно ознакомьтесь с некоторыми другими нашими курсами и руководствами здесь, на Envato Tuts +!

  • NativeScript
    Код мобильного приложения с NativeScript
    Кейван Касаи
  • NativeScript
    Начните с NativeScript и Mobile Angular 2
    Реджинальд Доусон
  • React Native
    Начните с React Native
    Маркус Мюльбергер
  • React Native
    Создайте социальное приложение с React Native
    Маркус Мюльбергер