使用 NativeScript 开发实时应用程序:实现推送通知

wufei123 2024-06-02 阅读:13 评论:0
nativescript 是一个使用 xml、css 和 javascript 构建跨平台本机移动应用程序的框架。在本系列中,我们将尝试使用 nativescript 应用程序可以完成的一些很酷的事情:地理位置和 google 地图集成、s...

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并在 中添加以下服务。这将为应用启用 Firebase 消息传递服务:

<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 项目:

使用 NativeScript 开发实时应用程序:实现推送通知

接下来,系统会询问您是否要安装依赖项。说是。

安装完所有依赖项后,您应该会在目录中看到一个 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:

使用 NativeScript 开发实时应用程序:实现推送通知

从浏览器访问该网址即可查看输出“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"}

触发后,您将看到类似于以下内容的输出:

使用 NativeScript 开发实时应用程序:实现推送通知

如果应用当前未打开,您将在通知区域中看到通知:

使用 NativeScript 开发实时应用程序:实现推送通知

结论

恭喜!您终于完成了健身应用程序。在四个教程的过程中,您已经构建了一个使用 Google 地图、SQLite、Firebase 实时数据库和 Firebase 云消息传递的 NativeScript 应用。现在您已经为构建使用这些技术的 NativeScript 应用程序奠定了良好的基础。

要了解有关 NativeScript 或其他跨平台移动技术的更多信息,请务必查看我们在 Envato Tuts+ 上的其他一些课程和教程!

以上就是使用 NativeScript 开发实时应用程序:实现推送通知的详细内容,更多请关注知识资源分享宝库其它相关文章!

版权声明

本站内容来源于互联网搬运,
仅限用于小范围内传播学习,请在下载后24小时内删除,
如果有侵权内容、不妥之处,请第一时间联系我们删除。敬请谅解!
E-mail:dpw1001@163.com

分享:

扫一扫在手机阅读、分享本文

发表评论
热门文章
  • 华为 Mate 70 性能重回第一梯队 iPhone 16 最后一块遮羞布被掀

    华为 Mate 70 性能重回第一梯队 iPhone 16 最后一块遮羞布被掀
    华为 mate 70 或将首发麒麟新款处理器,并将此前有博主爆料其性能跑分将突破110万,这意味着 mate 70 性能将重新夺回第一梯队。也因此,苹果 iphone 16 唯一能有一战之力的性能,也要被 mate 70 拉近不少了。 据悉,华为 Mate 70 性能会大幅提升,并且销量相比 Mate 60 预计增长40% - 50%,且备货充足。如果 iPhone 16 发售日期与 Mate 70 重合,销量很可能被瞬间抢购。 不过,iPhone 16 还有一个阵地暂时难...
  • 酷凛 ID-COOLING 推出霜界 240/360 一体水冷散热器,239/279 元

    酷凛 ID-COOLING 推出霜界 240/360 一体水冷散热器,239/279 元
    本站 5 月 16 日消息,酷凛 id-cooling 近日推出霜界 240/360 一体式水冷散热器,采用黑色无光低调设计,分别定价 239/279 元。 本站整理霜界 240/360 散热器规格如下: 酷凛宣称这两款水冷散热器搭载“自研新 V7 水泵”,采用三相六极马达和改进的铜底方案,缩短了水流路径,相较上代水泵进一步提升解热能力。 霜界 240/360 散热器的水泵为定速 2800 RPM 设计,噪声 28db (A)。 两款一体式水冷散热器采用 27mm 厚冷排,...
  • 惠普新款战 99 笔记本 5 月 20 日开售:酷睿 Ultra / 锐龙 8040,4999 元起

    惠普新款战 99 笔记本 5 月 20 日开售:酷睿 Ultra / 锐龙 8040,4999 元起
    本站 5 月 14 日消息,继上线官网后,新款惠普战 99 商用笔记本现已上架,搭载酷睿 ultra / 锐龙 8040处理器,最高可选英伟达rtx 3000 ada 独立显卡,售价 4999 元起。 战 99 锐龙版 R7-8845HS / 16GB / 1TB:4999 元 R7-8845HS / 32GB / 1TB:5299 元 R7-8845HS / RTX 4050 / 32GB / 1TB:7299 元 R7 Pro-8845HS / RTX 2000 Ada...
  • python中def什么意思

    python中def什么意思
    python 中,def 关键字用于定义函数,这些函数是代码块,执行特定任务。函数语法为 def (参数列表)。函数可以通过其名字和圆括号调用。函数可以接受参数作为输入,并在函数体中使用参数名访问。函数可以使用 return 语句返回一个值,它将成为函数调用的结果。 Python 中 def 关键字 在 Python 中,def 关键字用于定义函数。函数是代码块,旨在执行特定任务。 语法 def 函数定义的语法如下: def (参数列表): # 函数体 示例 定义...
  • python中int函数的用法

    python中int函数的用法
    int() 函数将值转换为整数,支持多种类型(字符串、字节、浮点数),默认进制为 10。可以指定进制数范围在 2-36。int() 返回 int 类型的转换结果,丢弃小数点。例如,将字符串 "42" 转换为整数为 42,将浮点数 3.14 转换为整数为 3。 Python 中的 int() 函数 int() 函数用于将各种类型的值转换为整数。它接受任何可以解释为整数的值作为输入,包括字符串、字节、浮点数和十六进制表示。 用法 int(object, base=10) 其中...