当前位置: 首页 > news >正文

HarmonyOS NEXT Push接入

接入HarmonyOS NEXT Push 推送功能,相比于 Android 真的是简单太多。不再需要适配接入各个厂家的推送 SDK,真是舒服。

1.开通推送服务与配置Client ID

1.1 创建应用获取Client ID

按照官方文档来就可以了:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/push-config-setting-V5

1.2 配置Client ID

在项目模块级别下的src/main/module.json5(例如entry/src/main/module.json5)中,新增metadata并配置client_id,如下所示:

"module": {"name": "entry","type": "xxx","description": "xxxx","mainElement": "xxxx","deviceTypes": [],"pages": "xxxx","abilities": [],// 配置如下信息"metadata": [ {"name": "client_id",// 配置为步骤1中获取的Client ID"value": "xxxxxx"  }]
}

2.获取 push token 并上传

import { pushService } from '@kit.PushKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { UIAbility, AbilityConstant, Want } from '@kit.AbilityKit';export default class EntryAbility extends UIAbility {async onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): Promise<void> {// 获取Push Tokentry {const pushToken: string = await pushService.getToken();hilog.info(0x0000, 'testTag', 'Succeeded in getting push token: %{public}s', pushToken);} catch (err) {let e: BusinessError = err as BusinessError;hilog.error(0x0000, 'testTag', 'Failed to get push token: %{public}d %{public}s', e.code, e.message);}// 上报Push Token 到服务器uploadPushToken()}
}

3. AAID

上传 push token 时,可以使用 AAID 当作 识别设备的唯一标识,即类是 Android 中的 deviceId 使用。i按照官方文档说明:

AAID(Anonymous Application Identifier):应用匿名标识符,标识运行在移动智能终端设备上的应用实例,只有该应用实例才能访问该标识符,它只存在于应用的安装期,总长度32位。与无法重置的设备级硬件ID相比,AAID具有更好的隐私权属性。

AAID具有以下特性:
匿名化、无隐私风险:AAID和已有的任何标识符都不关联,并且每个应用只能访问自己的AAID。
同一个设备上,同一个开发者的多个应用,AAID取值不同。
同一个设备上,不同开发者的应用,AAID取值不同。
不同设备上,同一个开发者的应用,AAID取值不同。
不同设备上,不同开发者的应用,AAID取值不同。
场景介绍
AAID会在包括但不限于下述场景中发生变化:
应用卸载重装。
应用调用删除AAID接口。
用户恢复出厂设置。
用户清除应用数据。
获取 AAID :

import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit';
import { AAID } from '@kit.PushKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { hilog } from '@kit.PerformanceAnalysisKit';export default class EntryAbility extends UIAbility {// 入参want与launchParam并未使用,为初始化项目时自带参数async onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): Promise<void> {// 获取AAIDtry {const aaid: string = await AAID.getAAID();hilog.info(0x0000, 'testTag', 'Succeeded in getting AAID.');} catch (err) {let e: BusinessError = err as BusinessError;hilog.error(0x0000, 'testTag', 'Failed to get AAID: %{public}d %{public}s', e.code, e.message);}}
}

4. 唤醒应用

后端在推送消息的时候,数据结构:

// Request URL
POST https://push-api.cloud.huawei.com/v3/[projectId]/messages:send// Request Header
Content-Type: application/json
Authorization: Bearer eyJr*****OiIx---****.eyJh*****iJodHR--***.QRod*****4Gp---****
push-type: 0// Request Body
{"payload": {"notification": {"category": "MARKETING","title": "普通通知标题","body": "普通通知内容","clickAction": {"actionType": 0,"data": {"testKey": "testValue"}}}},"target": {"token": ["IQAAAA**********4Tw"]},"pushOptions": {"testMessage": true}
}

我们主要关注 clickAction 这个结构:
actionType:点击消息的动作,在后端push-type: 0 即表示 Aler消息时:
0:打开应用首页
1:打开应用自定义页面

当然还有其他类型,如下:
请添加图片描述
但是一般我们只关注 push-type: 0 的情况即可。
详情请参见ClickAction。

4.1 通知权限申请

判断是否获得通知权限:

notificationManager.isNotificationEnabled()

如果没有,则请求通知栏权限:

private requestNotificationPermission = () => {notificationManager.isNotificationEnabled().then((data: boolean) => {console.info("isNotificationEnabled success, data: " + JSON.stringify(data));if(!data){notificationManager.requestEnableNotification().then(() => {console.info(`[ANS] requestEnableNotification success`);}).catch((err : BusinessError) => {if(1600004 == err.code){console.info(`[ANS] requestEnableNotification refused`);} else {console.error(`[ANS] requestEnableNotification failed, code is ${err.code}, message is ${err.message}`);}});}}).catch((err : BusinessError) => {console.error(`isNotificationEnabled fail: ${JSON.stringify(err)}`);});}

4.2 跳转到应用

后端推送消息配置 “actionType”: 0,点击通知栏消息后,即可拉起应用

4.2 跳转到指定页面

后端推送消息配置 “actionType”: 1。
这个时候就有两种指定页面的方式:
方式1: 指定 action
方式2:指定 uri

4.2.1 Action 跳转到指定页面

需要在module.json5 中配置 abilibies:

"abilities": [{"name": "MainAbility","launchType": "singleton","srcEntry": "./ets/abilities/MainAbility.ets","description": "$string:MainAbility_desc","icon": "$media:icon","label": "$string:MainAbility_label","exported": true,"startWindowIcon": "$media:icon","startWindowBackground": "$color:startWindowBackgroundColor","skills": [{"entities": ["entity.system.home"],"actions": ["action.system.home",],}, {"actions": ["https://www.huawei.com/test"]}]},

我配置的 action 是:

{"actions": ["https://www.huawei.com/test"]}

细心的你可能会发现这个ability 上面还有一个配置:

{"entities": ["entity.system.home"],"actions": ["action.system.home",],}

千万别动,这个是指定启动的 Ability 的配置,如果你指定的 Abiblity 不是启动页的 Ability ,则没有这个问题。
在这里插入图片描述

4.2.2 uri 跳转到指定页面

"abilities": [{"name": "MainAbility","launchType": "singleton","srcEntry": "./ets/abilities/MainAbility.ets","description": "$string:MainAbility_desc","icon": "$media:icon","label": "$string:MainAbility_label","exported": true,"startWindowIcon": "$media:icon","startWindowBackground": "$color:startWindowBackgroundColor","skills": [{"actions": ["",],"uris": [{"scheme": "https","host": "www.huawei.com","path": "test"},]}]},

记住 actions 里的内容必须是 “” 空的,不然会去适配 action。
在这里插入图片描述

4.3 参数解析

拉起应用后,肯定少不了参数的解析和传递。

{"payload": {"notification": {"category": "MARKETING","title": "普通通知标题","body": "普通通知内容","clickAction": {"actionType": 0,"data": {"testKey": "testValue"}}}},"target": {"token": ["IQAAAA**********4Tw"]},"pushOptions": {"testMessage": true}
}

这里的 “data”: {“testKey”: “testValue”} 就是我们需要解析的参数。
解析参数在两个地方需要处理,

情况1:应用未启动,走 UIAbility 的 onCreate(want: Want)
情况1:应用启动了,在前台或后台,走 UIAbility 的 onNewWant(want: Want)

而这两个方法都有一个参数 want: Want 。我们的参数也就在这个参数里面了。

4.3.1 onNewWant

onNewWant() 就比较简单了,直接解析参数后,掉用 router 到指定页面即可:

onNewWant(want: Want): void {if (want?.uri != null && want.uri.length > 0) {router.pushUrl({url: want.parameters?.['page'] as string,params: want.parameters})}// 获取消息中传递的data数据hilog.info(0x0000, 'testTag', 'onNewWant --> Succeeded in getting message data: %{public}s', JSON.stringify(want.parameters));}

可以看到,我这里把需要跳转到页面的 page 路径传递过来了,这样就方便多了。

4.3.2 onCreate()

onCreate 处理起来就会比较麻烦,因为涉及到参数的传递。
在 onCreate 解析参数

localStorage = new LocalStorage();async onCreate(want: Want): Promise<void> {// 获取消息中传递的data数据if (want?.uri != null && want.uri.length > 0) {let routePage = want.parameters?.['page'] as string;let routePageParam = want.parameters as Record<string, object>this.localStorage.clear()this.localStorage.setOrCreate('page', routePage)this.localStorage.setOrCreate('params', routePageParam)hilog.info(0x0000, 'testTag', 'onCreate --> page: ', ', page: ' + this.routePage);}

因为是应用未启动,所以会走 onWindowStageCeate(),假设我们的启动页是 ‘pages/MainPage

onWindowStageCreate(windowStage: window.WindowStage): void {windowStage.loadContent('pages/MainPage', this.localStorage);}

在 loadContent 方法中,把我们的 localStorage 传递过去,剩下的参数其他页面自己去解析了。

4.4 启动页解析 LocalStorage 参数

关于LocalStorage的知识点可以看这里

let storage = LocalStorage.getShared()
@Entry(storage)
@Component
struct MainPage {@State notificationState: string = ''private clickBackTimeRecord: number = 0;@LocalStorageProp('page') page: string = ''@LocalStorageProp('params') params: Record<string, object> = {}
}

差不多就这么多,如果指定唤起的 UIAbility 不是 main Ability 的话,稍微有点不一样,不过也是大同小异了。

5. Notification 测试

有时候我们不方便用华为后台推送测试的话,可以自己发送通知到通知栏,也是一样的,甚至更方便。因为华为推送后台,如果是指定启动应用内页面的话,action 和 uri 都是无法发送参数的。但是你硬是要用 uri 拼接参数传递过来,然后自己再解析 uri 中的参数,也不是不行,就是太麻烦了。
那么自己发送通知到通知栏就方便多了,还可以传递 data 参数。上代码:

private publishNotification() {// 通过WantAgentInfo的operationType设置动作类型let wantAgentInfo: wantAgent.WantAgentInfo = {wants: [{deviceId: '',bundleName: 'com.huawei.demo',abilityName: 'MainAbility',action: '', // "https://www.huawei.com/test",entities: [],uri: "https://www.huawei.com/test", parameters: {page: 'pages/ClickActionInnerPage',id: '123456'}}],operationType: wantAgent.OperationType.START_ABILITY,requestCode: 0,wantAgentFlags:[wantAgent.WantAgentFlags.CONSTANT_FLAG]};// 创建WantAgentwantAgent.getWantAgent(wantAgentInfo, (err: BusinessError, data: WantAgent) => {if (err) {console.error(`Failed to get want agent. Code is ${err.code}, message is ${err.message}`);return;}console.info('Succeeded in getting want agent.');let notificationRequest: notificationManager.NotificationRequest = {id: 1,content: {notificationContentType: notificationManager.ContentType.NOTIFICATION_CONTENT_BASIC_TEXT, // 普通文本类型通知normal: {title: '我是标题党',text: 'HarmonyOS 论坛中有研发人员求助,反馈通知没有没有声音,因此在真机上验证了一下,果不其然,没有通知的提示音',additionalText:'通知的附加内容',}},notificationSlotType: notificationManager.SlotType.SOCIAL_COMMUNICATION,wantAgent: data,};notificationManager.publish(notificationRequest, (err: BusinessError) => {if (err) {console.error(`Failed to publish notification. Code is ${err.code}, message is ${err.message}`);return;}console.info('Succeeded in publishing notification.');});});}

同样,跟之前说的一样, 如果使用 uri 指定跳转页面的话,action 要是空, bundleName 和 abilityName 必须要填对,也就是我们的包名和指定需要启动的 UIAbility 。也就是上面我说过的,不一定是要 MainUIAbility作为启动的Ability 的,是可以指定的哦。

希望对你有帮助。

相关文章:

HarmonyOS NEXT Push接入

接入HarmonyOS NEXT Push 推送功能&#xff0c;相比于 Android 真的是简单太多。不再需要适配接入各个厂家的推送 SDK&#xff0c;真是舒服。 1.开通推送服务与配置Client ID 1.1 创建应用获取Client ID 按照官方文档来就可以了&#xff1a;https://developer.huawei.com/co…...

如何快速入门Element-UI:打造高效美观的前端界面

Element-UI 是一款基于 Vue.js 的开源组件库,提供了丰富的 UI 组件,可以帮助开发者快速构建美观、响应式的前端界面。本文将详细介绍如何快速入门 Element-UI,包括环境搭建、组件使用、样式定制及常见问题解决方法,帮助你高效地使用 Element-UI 进行前端开发。 一、环境搭…...

Langchain的向量存储 - Document示例代码里的疑问

文章目录 前言一、语句分析二、 举例解释三、 完整代码总结 前言 之前的代码里有下面这句话&#xff0c;可能有看不明白的读者。 vectors [embeddings.embed(doc.page_content) for doc in docs]今天一起来看下这句话。 一、语句分析 这句话实际上是一个列表推导式&#x…...

Docker 教程-介绍-2

快速了解docker有什么。 Docker简介 Docker 是一个开源的应用容器引擎&#xff0c;基于Go语言开发&#xff0c;并遵循Apache 2.0协议。它允许开发者将应用及其依赖包打包进一个可移植的容器中&#xff0c;这些容器可以发布到任何支持Docker的Linux或Windows机器上&#xff0c…...

【2024最新华为OD-C/D卷试题汇总】[支持在线评测] 伐木工(200分) - 三语言AC题解(Python/Java/Cpp)

🍭 大家好这里是清隆学长 ,一枚热爱算法的程序员 ✨ 本系列打算持续跟新华为OD-C/D卷的三语言AC题解 💻 ACM银牌🥈| 多次AK大厂笔试 | 编程一对一辅导 👏 感谢大家的订阅➕ 和 喜欢💗 📎在线评测链接 伐木工(200分) 🌍 评测功能需要订阅专栏后私信联系清隆解…...

UltraScale+系列模块化仪器,可以同时用作控制器、算法加速器和高速数字信号处理器

基于 XCZU7EG / XCZU4EG / XCZU2EG • 灵活的模块组合 • 易于嵌入的紧凑型外观结构 • 高性能的 ARM Cortex 处理器 • 成熟的 FPGA 可编程逻辑 &#xff0c;基于 IP 核的软件库 基于 Xilinx Zynq UltraScaleMPSoC 的 FPGA 技术&#xff0c;采用 Xilinx Zynq UltraScale&a…...

Python与其他编程语言(如Java、C++)相比有哪些优势?

一、技术难点 在探讨Python与其他编程语言相比的优势时&#xff0c;技术难点在于如何全面、准确地把握并阐述这些优势。这需要对Python、Java、C等编程语言有深入的理解&#xff0c;包括它们的语法特性、应用领域、性能特点、开发效率等。 首先&#xff0c;Python的语法简洁明…...

Edge浏览器双击关闭标签页,双击关闭浏览器选项卡

设置》外观》自定义浏览器&#xff0c;开启“使用双击关闭浏览器选项卡” 设置里面搜索“双击”&#xff0c;这是最快的方式 鼠标滚轮单击 或者进入“设置”-“辅助功能” 呼吁已久的功能来了&#xff01;Edge浏览器双击关闭标签页功能上线新 国产浏览器大多都有双击关闭标签页…...

C++ 贪心算法——跳跃游戏、划分字母区间

一&#xff1a;跳跃游戏 55. 跳跃游戏 题目描述&#xff1a;给你一个非负整数数组 nums &#xff0c;你最初位于数组的 第一个下标 。数组中的每个元素代表你在该位置可以跳跃的最大长度。判断你是否能够到达最后一个下标&#xff0c;如果可以&#xff0c;返回 true &#xff1…...

汽车数据应用构想(三)

上期说的&#xff0c;用数据去拟合停车信息的应用&#xff0c;那么类似的POI信息相关的场景其实都可以实现。今天讲讲用户使用频率也很高的加油/充电场景。 实际应用中&#xff0c;在加油场景中用户关心的通常还是价格。无论是导航还是各种加油APP/小程序&#xff0c;都已经很…...

体素技术在AI绘画中的革新作用

随着人工智能技术的不断进步&#xff0c;AI绘画已经成为艺术创作和视觉设计领域的一大趋势。在众多推动AI绘画发展的技术中&#xff0c;体素技术以其独特的优势&#xff0c;正在逐渐改变着我们对计算机生成图像的认识。本文旨在探讨体素技术在AI绘画中的应用与影响&#xff0c;…...

Leetcode.866 回文质数

题目链接 Leetcode.866 回文质数 rating : 1938 题目描述 给你一个整数 n n n &#xff0c;返回大于或等于 n n n 的最小 回文质数。 一个整数如果恰好有两个除数&#xff1a; 1 1 1 和它本身&#xff0c;那么它是 质数 。注意&#xff0c; 1 1 1 不是质数。 例如&#xf…...

【论文阅读】Point2RBox (CVPR’2024)

paper:https://arxiv.org/abs/2311.14758 code:https://github.com/yuyi1005/point2rbox-mmrotate...

深度学习的点云分割

深度学习的点云分割 点云分割是计算机视觉中的一个重要任务&#xff0c;特别是在三维数据处理和分析中。点云数据是由大量三维点构成的集合&#xff0c;每个点包含空间坐标&#xff08;x, y, z&#xff09;&#xff0c;有时还包含其他信息如颜色和法向量。点云分割的目标是将点…...

【知识点】c++模板特化

在 C 中&#xff0c;模板特化分为全特化&#xff08;full specialization&#xff09;和偏特化&#xff08;partial specialization&#xff09;。它们允许程序员为特定类型或类型模式提供不同的实现&#xff0c;以覆盖通用模板的默认行为。 模板全特化 模板全特化是指为某个…...

算法家族之一——二分法

目录 算法算法的打印效果如果算法里的整型“i”为1如果算法里的整型“i”为11 算法的流程图算法的实际应用总结 大家好&#xff0c;我叫 这是我58&#xff0c;现在&#xff0c;请看下面的算法。 算法 #define _CRT_SECURE_NO_WARNINGS 1//<--预处理指令 #include <stdi…...

【深度学习】PuLID: Pure and Lightning ID Customization via Contrastive Alignment

论文&#xff1a;https://arxiv.org/abs/2404.16022 代码&#xff1a;https://github.com/ToTheBeginning/PuLID 文章目录 AbstractIntroductionRelated WorkMethods Abstract 我们提出了一种新颖的、无需调整的文本生成图像ID定制方法——Pure and Lightning ID customizatio…...

Elastic 8.14:用于简化分析的 Elasticsearch 查询语言 (ES|QL) 正式发布

作者&#xff1a;来自 Elastic Brian Bergholm 今天&#xff0c;我们很高兴地宣布 Elastic 8.14 正式发布。 什么是新的&#xff1f; 8.14 版本最重要的标题是 ES|QL 的正式发布(GA)&#xff0c;它是从头开始设计和专门构建的&#xff0c;可大大简化数据调查。在新的查询引擎的…...

C语言指针与数组的区别

在C语言中&#xff0c;指针和数组虽然在很多情况下可以互换使用&#xff0c;但它们在概念上和行为上存在一些区别。下面详细解释这些区别&#xff1a; ### 数组 1. **固定大小**&#xff1a;数组在声明时必须指定大小&#xff0c;这个大小在编译时确定&#xff0c;之后不能改…...

springboot3一些听课笔记

文章目录 一、错误处理机制1.1 默认1.2 自定义 二、嵌入式容器 一、错误处理机制 1.1 默认 错误处理的自动配置都在ErrorMvcAutoConfiguration中&#xff0c;两大核心机制&#xff1a; ● 1. SpringBoot 会自适应处理错误&#xff0c;响应页面或JSON数据 ● 2. SpringMVC的错…...

vscode(仍待补充)

写于2025 6.9 主包将加入vscode这个更权威的圈子 vscode的基本使用 侧边栏 vscode还能连接ssh&#xff1f; debug时使用的launch文件 1.task.json {"tasks": [{"type": "cppbuild","label": "C/C: gcc.exe 生成活动文件"…...

C# 类和继承(抽象类)

抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...

Rust 异步编程

Rust 异步编程 引言 Rust 是一种系统编程语言,以其高性能、安全性以及零成本抽象而著称。在多核处理器成为主流的今天,异步编程成为了一种提高应用性能、优化资源利用的有效手段。本文将深入探讨 Rust 异步编程的核心概念、常用库以及最佳实践。 异步编程基础 什么是异步…...

Redis的发布订阅模式与专业的 MQ(如 Kafka, RabbitMQ)相比,优缺点是什么?适用于哪些场景?

Redis 的发布订阅&#xff08;Pub/Sub&#xff09;模式与专业的 MQ&#xff08;Message Queue&#xff09;如 Kafka、RabbitMQ 进行比较&#xff0c;核心的权衡点在于&#xff1a;简单与速度 vs. 可靠与功能。 下面我们详细展开对比。 Redis Pub/Sub 的核心特点 它是一个发后…...

九天毕昇深度学习平台 | 如何安装库?

pip install 库名 -i https://pypi.tuna.tsinghua.edu.cn/simple --user 举个例子&#xff1a; 报错 ModuleNotFoundError: No module named torch 那么我需要安装 torch pip install torch -i https://pypi.tuna.tsinghua.edu.cn/simple --user pip install 库名&#x…...

A2A JS SDK 完整教程:快速入门指南

目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库&#xff…...

AirSim/Cosys-AirSim 游戏开发(四)外部固定位置监控相机

这个博客介绍了如何通过 settings.json 文件添加一个无人机外的 固定位置监控相机&#xff0c;因为在使用过程中发现 Airsim 对外部监控相机的描述模糊&#xff0c;而 Cosys-Airsim 在官方文档中没有提供外部监控相机设置&#xff0c;最后在源码示例中找到了&#xff0c;所以感…...

基于Java+VUE+MariaDB实现(Web)仿小米商城

仿小米商城 环境安装 nodejs maven JDK11 运行 mvn clean install -DskipTestscd adminmvn spring-boot:runcd ../webmvn spring-boot:runcd ../xiaomi-store-admin-vuenpm installnpm run servecd ../xiaomi-store-vuenpm installnpm run serve 注意&#xff1a;运行前…...

【Linux系统】Linux环境变量:系统配置的隐形指挥官

。# Linux系列 文章目录 前言一、环境变量的概念二、常见的环境变量三、环境变量特点及其相关指令3.1 环境变量的全局性3.2、环境变量的生命周期 四、环境变量的组织方式五、C语言对环境变量的操作5.1 设置环境变量&#xff1a;setenv5.2 删除环境变量:unsetenv5.3 遍历所有环境…...

机器学习的数学基础:线性模型

线性模型 线性模型的基本形式为&#xff1a; f ( x ) ω T x b f\left(\boldsymbol{x}\right)\boldsymbol{\omega}^\text{T}\boldsymbol{x}b f(x)ωTxb 回归问题 利用最小二乘法&#xff0c;得到 ω \boldsymbol{\omega} ω和 b b b的参数估计$ \boldsymbol{\hat{\omega}}…...