使用 NativeScript 开发实时应用程序:实现推送通知
nativescript 是一个使用 xml、css 和 javascript 构建跨平台本机移动应用程序的框架。在本系列中,我们将尝试使用 nativescript 应用程序可以完成的一些很酷的事情:地理位置和 google 地图集成、sqlite 数据库、firebase 集成和推送通知。在此过程中,我们正在构建一个具有实时功能的健身应用程序,该应用程序将使用这些功能。
在本教程中,您将了解使用 Firebase 云消息服务向 NativeScript 应用添加推送通知是多么轻松。
您将要创建的内容
继续上一教程,您将向应用添加推送通知。当用户打破当前记录或其中一个朋友取代他们获得第一名时,将会触发通知。
设置项目
如果您已遵循之前的 Firebase 教程,则只需使用同一项目并构建我们将在本教程中添加的功能即可。否则,您可以创建一个新项目并将起始文件复制到项目的应用程序文件夹中。
tns create fitApp --appid "com.yourname.fitApp"
之后,您还需要安装地理位置、Google 地图、SQLite 和 Firebase 插件:
tns plugin add nativescript-geolocation tns plugin add nativescript-google-maps-sdk tns plugin add nativescript-sqlite tns plugin add nativescript-plugin-firebase
安装后,您需要配置 Google 地图插件。您可以阅读之前教程中的安装 Google 地图插件部分,了解有关如何执行此操作的完整说明。
接下来,安装用于格式化日期的 fecha 库:
npm install --save fecha
之后,您还需要配置 Firebase 插件。请务必阅读上一教程中的以下部分,以便您可以运行应用程序:
- 运行项目
- 设置 Firebase 应用
- 设置 Facebook 应用
- 安装 Firebase 插件
- 配置 Facebook 集成
由于我们已经在上一篇文章中设置了 Firebase 插件,因此只需完成少量工作即可设置推送通知。
首先,您必须进入 node_modules/nativescript-plugin-firebase 目录并运行 npm run config 来重新配置插件。这次,选择 Facebook 身份验证和消息传递。
完成后,打开项目根目录中的 firebase.nativescript.json 文件,并确保 messaging 设置为 true:
{ "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 ...> <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 模拟器来快速设置和更改您的位置。您可以在之前的教程中的运行应用部分了解如何执行此操作。
如果遇到任何构建错误,您可以删除平台并重新运行应用程序:
tns platform remove android tns run android
设置 Firebase 云函数
您将使用 Firebase Cloud Functions 创建一个用于发送推送通知的服务器。此 Firebase 功能用于在您正在使用的 Firebase 功能中发生特定事件时运行后端代码 - 例如,如果实时数据库中保存了新数据,或者通过Firebase 身份验证服务。对于此应用,您将使用 HTTP 触发器在移动应用向特定端点发出请求时发送推送通知。
要使用 Firebase Cloud Functions,您首先需要全局安装 firebase-tools 软件包:
npm install -g firebase-tools
接下来,创建一个新文件夹来存放服务器代码。这应该位于您的应用程序文件夹之外。在该文件夹中,安装 firebase-functions 软件包:
npm install firebase-functions@latest --save
安装完成后,通过运行 firebase login 登录 Firebase。这将打开一个新的浏览器选项卡,允许您使用 Google 帐户登录。完成整个过程并同意所请求的所有权限。
登录后,您现在可以初始化特定 Firebase 项目的 Firebase 函数:
firebase init functions
这将询问您是否要设置默认项目。选择您在上一教程中创建的 Firebase 项目:
接下来,系统会询问您是否要安装依赖项。说是。
安装完所有依赖项后,您应该会在目录中看到一个 firebase.json 文件和一个 functions 文件夹。您要处理的文件是 functions/index.js 文件。打开该文件,您将看到以下内容:
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 触发器。
exports.helloWorld = functions.https.onRequest((request, response) => { response.send("Hello from Firebase!"); });
运行以下命令将函数部署到云端:
firebase deploy --only functions
部署完成后,它应该显示已部署该函数的 URL:
从浏览器访问该网址即可查看输出“Hello from Firebase!”
添加服务器代码
现在您已准备好添加用于实现推送通知的代码。首先,您将添加服务器组件的代码,然后添加应用程序的代码。
打开functions/index.js文件并清空其内容。
创建 Firebase 函数
导入您需要的 Firebase 软件包:
const functions = require('firebase-functions'); // for listening to http triggers const admin = require('firebase-admin'); // for accessing the realtime database admin.initializeApp(functions.config().firebase); // initialize the Firebase Admin SDK
创建 init_push 函数。请注意,任何请求方法都会调用 HTTP 触发器,因此您必须筛选要处理的请求方法。在本例中,我们只想处理 POST 请求。我们希望应用提交 id、steps 和 friend_ids 作为请求数据。
exports.init_push = functions.https.onRequest((request, response) => { if(request.method == 'POST'){ var id = request.body.id; // ID of the user who made the request (Firebase Auth ID) var steps = parseInt(request.body.steps); // latest steps, not recorded yet var friend_ids = request.body.friend_ids.split(','); friend_ids.push(id); // also include the ID of the current user // next: add code for getting the user and friends data } });
获取用户和好友数据
接下来,查询 Firebase 数据库以检查用户 ID 是否存在。这是保护端点的一种方式,因此并非任何人都可以触发推送通知。 (当然,真正的应用程序应该具有更好的后端安全性,以便用户无法欺骗自己的数据或其他人的数据。)
如果用户确实存在,则再次查询数据库,以便返回所有用户。请注意,Firebase 目前不提供基于 ID 数组返回记录的方法,因此我们必须自己过滤相关数据:
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。完成此操作后,根据每个用户的步数对数组进行排序。步骤数最多的索引为第一个索引。
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
构造通知负载
现在我们准备好确定谁将接收通知并构建通知负载。谁是第一名?是当前用户还是用户的朋友之一?由于当前用户在打破第一名的总记录时也打破了自己的记录,因此我们只需要检查该记录是否已被打破。
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! You beat your current record by ' + diff_steps + ' steps!' }, device_token: current_user_data.device_token }; has_notification = true; } // next: add code for sending push notification
发送通知
最后发出通知:
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})); // inform the app that a notification was sent }) .catch(function(error) { response.send(JSON.stringify(error)); // send the push notification error to the app }); }else{ response.send(JSON.stringify({'has_notification': false})); // inform the app that a notification was not sent }
更新应用代码
之前,您设置了应用程序,以便它能够接收推送通知。这次,您将添加代码,以便您的应用程序可以处理这些推送通知并将其显示给用户。
接收推送通知
为了接收推送通知,您需要做的第一件事是更新 firebase.init() 函数以包含用于接收设备令牌的侦听器:
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。
接下来,您可以添加接收通知时的侦听器。这将显示一个警告框,其中使用消息的标题和正文作为内容:
onMessageReceivedCallback: function(message) { dialogs.alert({ title: message.title, message: message.body, okButtonText: "ok" }); },
将设备令牌保存到 Firebase
Firebase Cloud Messaging 在向特定设备发送推送通知时需要设备令牌。由于我们已经在使用 Firebase,因此我们只需将设备令牌与用户数据一起保存。为此,您需要编辑用于保存用户数据的代码以包含我们之前获得的设备令牌:
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 }; }
触发推送通知
当发生以下两种情况之一时,将触发推送通知:
- 当用户打破当前记录时
- 当用户的一个朋友打破记录并获得第一名时
第一个很简单,因此实际上不需要额外的设置。但对于第二个,你需要做一些工作。首先,您必须编辑身份验证状态更改时的代码。从 Facebook 结果中提取好友 ID 后,您必须使用应用程序设置保存好友 ID。
// 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);
接下来,更新用户何时停止跟踪其步行的代码。在构建更新用户的用户数据的代码之后,从应用程序设置中获取好友 ID,并将其包含在包含触发推送通知的请求数据的对象中。
// 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 数据库上更新。
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); });
测试推送通知
您可以通过首先从模拟器或设备中卸载应用程序来测试推送通知的发送。这使得我们能够正确触发获取设备令牌的函数。请务必添加 console.log 以输出设备令牌:
onPushTokenReceivedCallback: function(token) { applicationSettings.setString('device_token', token); console.log('device token: ', device_token); // <-- add this }
当设备令牌在 NativeScript 控制台中输出时,将其复制,点击 Firebase 应用信息中心上的数据库菜单,并将其作为设备令牌添加给应用的所有用户。使用 device_token 作为属性名称。
要触发推送通知,您可以使用 curl 向 Firebase 函数端点发出 POST 请求:
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,您可以使用Postman应用发送请求。对请求使用以下设置:
- 请求方法: POST
- 网址:您的 Firebase 函数端点
- 标头键: 内容类型
- 标头值: application/json
- 正文:
{"id":"ID OF A FIREBASE USER", "steps":NUMBER_OF_STEPS, "friend_ids":"COMMA,SEPARATED,FIREBASE,USER_IDs"}
触发后,您将看到类似于以下内容的输出:
如果应用当前未打开,您将在通知区域中看到通知:
结论
恭喜!您终于完成了健身应用程序。在四个教程的过程中,您已经构建了一个使用 Google 地图、SQLite、Firebase 实时数据库和 Firebase 云消息传递的 NativeScript 应用。现在您已经为构建使用这些技术的 NativeScript 应用程序奠定了良好的基础。
要了解有关 NativeScript 或其他跨平台移动技术的更多信息,请务必查看我们在 Envato Tuts+ 上的其他一些课程和教程!
使用 NativeScript 开发实时应用程序:实现推送通知的详细内容,更多请关注红帽云邮其它相关文章!