通知订阅扩展能力开发步骤
接口说明
| 接口名 | 描述 |
|---|---|
| onDestroy(): void | 通知订阅扩展被销毁时的回调。 |
| onReceiveMessage(notificationInfo: NotificationInfo): void | 收到通知时的回调。 |
| onCancelMessages(hashCodes: Array<string>): void | 取消通知时的回调。 |
前提条件
申请ohos.permission.SUBSCRIBE_NOTIFICATION权限。
开发步骤
开发者在实现NotificationSubscriberExtensionAbility提供方时,需在DevEco Studio工程中新建一个NotificationSubscriberExtensionAbility。具体步骤如下。
-
在entry/src/main/ets/创建目录extensionability。
-
在entry/src/main/ets/extensionability目录下创建NotificationSubscriberExtAbility.ets,其内容如下。
import { hilog } from '@kit.PerformanceAnalysisKit';import { notificationExtensionSubscription, NotificationSubscriberExtensionAbility } from '@kit.NotificationKit';// ...const DOMAIN = 0x0000;// ...export class NotificationSubscriberExtAbility extends NotificationSubscriberExtensionAbility {// ...onDestroy(): void {hilog.info(DOMAIN, 'testTag', 'onDestroy');// ...}// ...onReceiveMessage(notificationInfo: notificationExtensionSubscription.NotificationInfo): void {hilog.info(DOMAIN, 'testTag', `on receive message ${JSON.stringify(notificationInfo)}`)// ...}// ...onCancelMessages(hashCodes: Array<string>): void {hilog.info(DOMAIN, 'testTag', `on cancel message ${JSON.stringify(hashCodes)}`)// ...}// ...} -
使用蓝牙模块接口与穿戴设备配对(蓝牙处于配对状态)并获取地址,然后通过subscribe/unsubscribe接口订阅或取消订阅通知。
-
实现NotificationSubscriberExtensionAbility后,还需要在合适的时机调用openSubscriptionSettings接口,打开通知扩展订阅设置页面,引导用户授予获取本机通知的权限,该页面以半模态弹窗显示。建议在设备管理页面提供一个通知授权的按钮,用户点击按钮则调用openSubscriptionSettings接口。
-
在应用的module.json5文件中配置extensionAbilities。
{"name": "NotificationSubscriberExtAbility","srcEntry": "./ets/extensionability/NotificationSubscriberExtAbility.ets","type": "notificationSubscriber","description": "$string:NotificationSubscriberExtAbility_desc","icon": "$media:layered_image","label": "$string:NotificationSubscriberExtAbility_label","exported": true} -
在应用的string.json文件中添加
{"name": "NotificationSubscriberExtAbility_desc","value": "description"},{"name": "NotificationSubscriberExtAbility_label","value": "ThirdPartyWearableApp"}
传统蓝牙连接示例
-
示例仅为传统蓝牙连接示例,开发者也可选用低功耗蓝牙连接方式。
-
用户收到消息后,假如蓝牙连接是无效的,则建立蓝牙连接。
-
假如蓝牙连接已经存在,则直接使用这个连接发送消息。
-
如果使用该连接发送消息失败,则重新建立连接,如果连接能建立成功则发送消息。
-
需要申请权限ohos.permission.ACCESS_BLUETOOTH。如何配置和申请权限,具体操作请参考声明权限和向用户申请授权。
import { hilog } from '@kit.PerformanceAnalysisKit';import { notificationExtensionSubscription, NotificationSubscriberExtensionAbility } from '@kit.NotificationKit';import { BusinessError } from '@kit.BasicServicesKit';import { socket } from '@kit.ConnectivityKit'import { util } from '@kit.ArkTS';const DOMAIN = 0x0000;class TransferInfo {public type: string = ''public info: notificationExtensionSubscription.NotificationInfo | undefinedpublic cancelHashCodes: Array<string> | undefined}// Spp means Serial Port Profileclass SppClientManager {private clientNumber: number = -1;private peerDevice: string = '';constructor(peerDevice: string) {this.peerDevice = peerDevice}public isConnect(): boolean {return this.clientNumber !== -1;}public async startConnect(): Promise<boolean> {let option: socket.SppOptions = {uuid: '00009999-0000-1000-8000-00805F9B34FB',secure: false,type: socket.SppType.SPP_RFCOMM};socket.sppConnect(this.peerDevice, option, (err: BusinessError, num: number) => {if (err) {hilog.error(DOMAIN, 'testTag', `cpp connect failed, errCode: ${err.code}, errMessage: ${err.message}`);} else {hilog.info(DOMAIN, 'testTag', `spp connect success clientNumber: ${num}`);this.clientNumber = num;}});return true}private sendData(jsonStr: string) {if (!this.isConnect()) {hilog.error(DOMAIN, 'testTag', `server is not connected`);return;}if (!jsonStr) {hilog.error(DOMAIN, 'testTag', 'json is empty');return;}hilog.info(DOMAIN, 'testTag', `prepare sending data to client ${this.clientNumber}`);const textEncoder:util.TextEncoder = new util.TextEncoder();const uint8Array: Uint8Array = textEncoder.encodeInto(jsonStr);const arrayBuffer = uint8Array.buffer;socket.sppWrite(this.clientNumber, arrayBuffer);hilog.info(DOMAIN, 'testTag', `sending success size: ${arrayBuffer.byteLength} bytes, data: ${jsonStr}`);}public sendNotificationData(notificationInfo: notificationExtensionSubscription.NotificationInfo) {let info: TransferInfo = {type: 'publish',info: notificationInfo,cancelHashCodes: undefined};let jsonStr = JSON.stringify(info);this.sendData(jsonStr);}public sendCancelNotificationData(cancelHashCodes: Array<string>) {let info: TransferInfo = {type: 'cancel',cancelHashCodes: cancelHashCodes,info: undefined};let jsonStr = JSON.stringify(info);this.sendData(jsonStr);}public read = (dataBuffer: ArrayBuffer) => {let data = new Uint8Array(dataBuffer);hilog.info(DOMAIN, 'testTag', `client data: ${JSON.stringify(data)}`);};public stopConnect() {hilog.info(DOMAIN, 'testTag', `closeSppClient ${this.clientNumber}`);try {socket.off('sppRead', this.clientNumber, this.read);} catch (err) {hilog.error(DOMAIN, 'testTag', `off sppRead errCode: ${err.code}, errMessage: ${err.message}`);}try {socket.sppCloseClientSocket(this.clientNumber);this.clientNumber = -1;} catch (err) {hilog.error(DOMAIN, 'testTag', `stopConnect errCode: ${err.code}, errMessage: ${err.message}`);}}}// export SppClientManager;export class NotificationSubscriberExtAbility extends NotificationSubscriberExtensionAbility {private sppClientManager: SppClientManager | undefined;onDestroy(): void {hilog.info(DOMAIN, 'testTag', 'onDestroy');this.sppClientManager!.stopConnect();}// Called back when a notification is published.onReceiveMessage(notificationInfo: notificationExtensionSubscription.NotificationInfo): void {hilog.info(DOMAIN, 'testTag', `on receive message ${JSON.stringify(notificationInfo)}`)notificationExtensionSubscription.getSubscribeInfo().then(async (info) => {if (this.sppClientManager == undefined) {this.sppClientManager = new SppClientManager(info[0].addr);}if (this.sppClientManager.isConnect()) {this.sendPublishWithRetry(notificationInfo);} else {try {await this.sppClientManager.startConnect().then(() => {hilog.info(DOMAIN, 'testTag', `startConnect success`);});} catch (err) {hilog.error(DOMAIN, 'testTag', `Failed to start connect: ${JSON.stringify(err)}`);}setTimeout(() => {this.sendPublishWithRetry(notificationInfo);}, 3000)}}).catch((err: BusinessError) => {hilog.error(DOMAIN, 'testTag',`notificationExtensionSubscription failed, errCode ${err.code}, errorMessage ${err.message}`);});}// Sends a publish notification and retries once upon failure.private async sendPublishWithRetry(notificationInfo: notificationExtensionSubscription.NotificationInfo) {try {this.sppClientManager!.sendNotificationData(notificationInfo);} catch (err) {hilog.error(DOMAIN, 'testTag', `send failed, errCode ${err.code}, errorMessage ${err.message}, and retry one times`);try {await this.sppClientManager!.startConnect().then(() => {hilog.info(DOMAIN, 'testTag', `startConnect success`);});} catch (err) {hilog.error(DOMAIN, 'testTag', `Failed to start connect: ${JSON.stringify(err)}`);}setTimeout(() => {this.sppClientManager!.sendNotificationData(notificationInfo);}, 3000);}}// Called back when notifications are cancelled.onCancelMessages(hashCodes: Array<string>): void {hilog.info(DOMAIN, 'testTag', `on cancel message ${JSON.stringify(hashCodes)}`)notificationExtensionSubscription.getSubscribeInfo().then(async (info) => {if (this.sppClientManager == undefined) {this.sppClientManager = new SppClientManager(info[0].addr);}if (this.sppClientManager.isConnect()) {this.sendCancelWithRetry(hashCodes);} else {try {await this.sppClientManager.startConnect().then(() => {hilog.info(DOMAIN, 'testTag', `startConnect success`);});} catch (err) {hilog.error(DOMAIN, 'testTag', `Failed to start connect: ${JSON.stringify(err)}`);}setTimeout(() => {this.sendCancelWithRetry(hashCodes);}, 3000)}}).catch((err: BusinessError) => {hilog.error(DOMAIN, 'testTag', `notificationExtensionSubscription failed, errCode ${err.code}, errorMessage ${err.message}`);});}// Retries a cancel operation if it fails.private async sendCancelWithRetry(hashCodes: string[]) {try {this.sppClientManager!.sendCancelNotificationData(hashCodes);} catch (err) {hilog.error(DOMAIN, 'testTag', `send failed, errCode ${err.code}, errorMessage ${err.message}, and retry one times`);try {await this.sppClientManager!.startConnect().then(() => {hilog.info(DOMAIN, 'testTag', `startConnect success`);});} catch (err) {hilog.error(DOMAIN, 'testTag', `Failed to start connect: ${JSON.stringify(err)}`);}setTimeout(() => {this.sppClientManager!.sendCancelNotificationData(hashCodes);}, 3000);}}}
注意:请勿频繁建立连接,可能会影响功能。