-
-
[原创]同一设备多账号登录,如何避免消息推送“串门”?
-
发表于: 2025-10-17 09:29 937
-
对各应用厂商而言,推送通知消息是App提高用户活跃度和转化率的高性价比营销工具。然而,当一个用户设备登录多个账号时,开发者可能会遇到同一条消息在同一设备的不同账号上重复展示的问题,这不仅降低了消息推送的精准度,还可能对用户造成困扰。
为解决这一问题,HarmonyOS SDK推送服务(Push Kit)推出了通知消息账号校验功能。该功能允许开发者根据终端设备上不同账号的属性来推送消息,确保通知精准地发送给对应设备上的对应账号。例如,在华为手机上,某个应用同时登录了账号A和账号B。当账号A切换至账号B后,原本发送给账号A的通知消息在到达设备后将不会展示,从而避免账号B看到账号A的消息。

错误示例:同一设备账号A切换至账号B后,接收并展示账号A的通知消息
若要实现账号校验功能,其关键便在于profileId。profileId是应用内账号id匿名标识,无论用户是选择华为账号作为应用登录账号,还是选择使用应用账号直接登录账号,该profileId都是应用通过账号映射的唯一匿名标识。所以我们需要为待绑定的账号生成一个非空唯一的profileId,这里不建议使用真实的账号id,推荐使用账号id自行生成对应的匿名标识,能与该账号id建立唯一映射关系即可,生成算法无限制。
那么,当用户选择华为账号作为应用登录账号并登录账号A成功后,开发者可调用Push Kit绑定接口bindAppProfileId()将已生成的账号A的profileId绑定到当前设备的应用token上。Push Token标识了每台设备上的每个应用,是Push Kit实现消息推送的前提条件,应用服务器在发送通知消息时token中若携带该账号A的profileId,则只有当前设备登录的华为账号为账号A时,才会展示通知消息;若不携带profileId,则无论当前设备登录的华为账号是否为账号A,都正常展示通知消息。
下面,我们来看一下实现推送服务账号校验功能的具体开发步骤。
开发步骤
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | 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 { // 入参 want 与 launchParam 并未使用,为初始化项目时自带参数 async onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): Promise<void> { // 获取Push Token try { const pushToken: string = await pushService.getToken(); hilog.info(0x0000, 'testTag', 'Succeeded in getting push token'); } 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并上报到您的服务端 }} |
- 为确保应用可正常收到通知消息,建议应用发送通知前调用requestEnableNotification()方法弹出提醒,告知用户需要允许接收通知消息。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | import { notificationManager } from '@kit.NotificationKit';import { BusinessError } from '@kit.BasicServicesKit';import { hilog } from '@kit.PerformanceAnalysisKit';import { common } from '@kit.AbilityKit';const TAG: string = '[PublishOperation]';const DOMAIN_NUMBER: number = 0xFF00;let context = this.getUIContext().getHostContext() as common.UIAbilityContext;notificationManager.isNotificationEnabled().then((data: boolean) => { hilog.info(DOMAIN_NUMBER, TAG, "isNotificationEnabled success, data: " + JSON.stringify(data)); if(!data){ notificationManager.requestEnableNotification(context).then(() => { hilog.info(DOMAIN_NUMBER, TAG, `[ANS] requestEnableNotification success`); }).catch((err : BusinessError) => { if(1600004 == err.code){ hilog.error(DOMAIN_NUMBER, TAG, `[ANS] requestEnableNotification refused, code is ${err.code}, message is ${err.message}`); } else { hilog.error(DOMAIN_NUMBER, TAG, `[ANS] requestEnableNotification failed, code is ${err.code}, message is ${err.message}`); } }); }}).catch((err : BusinessError) => { hilog.error(DOMAIN_NUMBER, TAG, `isNotificationEnabled fail, code is ${err.code}, message is ${err.message}`);}); |
- 为待绑定的账号生成一个非空唯一的profileId,调用bindAppProfileId()方法,添加当前设备上该用户与应用的关系。
1 2 3 4 5 6 7 8 9 10 11 12 | import { hilog } from '@kit.PerformanceAnalysisKit';import { pushCommon, pushService } from '@kit.PushKit';import { BusinessError } from '@kit.BasicServicesKit';// 定义需要绑定的profileId,建议使用账号id对应的匿名标识const profileId = '1****9';// 绑定应用账号pushService.bindAppProfileId(pushCommon.AppProfileType.PROFILE_TYPE_APPLICATION_ACCOUNT, profileId).then(() => { hilog.info(0x0000, 'testTag', 'Succeeded in binding app profile id');}).catch((err: BusinessError) => { hilog.error(0x0000, 'testTag', 'Failed to bind app profile id: %{public}d %{public}s', err.code, err.message);}); |
建议您将Push Token和生成的profileId上报到应用服务端,便于应用服务端向终端推送消息。
应用服务端调用REST API推送通知消息,通知消息示例如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | // Request URLPOST 8a6K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6H3N6i4y4Z5i4K6u0V1j5i4m8A6i4K6u0W2j5$3I4G2N6h3c8Q4x3X3g2Z5N6h3q4%4k6h3W2Q4x3X3g2U0L8$3#2Q4x3V1k6$33/[projectId]/messages:send// Request HeaderContent-Type: application/jsonAuthorization: Bearer eyJr*****OiIx---****.eyJh*****iJodHR--***.QRod*****4Gp---****push-type: 0// Request Body{ "payload": { "notification": { "category": "MARKETING", "title": "普通通知标题", "body": "普通通知内容", "profileId": "111***222", "clickAction": { "actionType": 0 } } }, "target": { "token": ["IQAAAA**********4Tw"] }} |
消息发送成功后,Push Kit会先校验绑定账号(华为账号或应用账号)时的AppProfileType。
若绑定华为账号,则先校验下发消息中携带的profileId和之前应用绑定的profileId是否一致,再校验当前登录的华为账号和绑定时登录的分布式账号是否一致,若全部满足则展示消息,否则不展示消息。
若绑定应用账号则校验下发消息中携带的profileId和之前应用绑定的profileId是否一致,若满足则展示消息,否则不展示消息。
了解更多详情>>
访问推送服务联盟官网