openharmony 鸿蒙 notification-subscriber-extension-ability-development-steps

2026-08-25 浏览 (1)

通知订阅扩展能力开发步骤

接口说明

接口名描述
onDestroy(): void通知订阅扩展被销毁时的回调。
onReceiveMessage(notificationInfo: NotificationInfo): void收到通知时的回调。
onCancelMessages(hashCodes: Array<string>): void取消通知时的回调。

前提条件

申请ohos.permission.SUBSCRIBE_NOTIFICATION权限。

开发步骤

开发者在实现NotificationSubscriberExtensionAbility提供方时,需在DevEco Studio工程中新建一个NotificationSubscriberExtensionAbility。具体步骤如下。

  1. 在entry/src/main/ets/创建目录extensionability。

  2. 在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)}`)
        // ...
      }
      // ...
    }
    
  3. 使用蓝牙模块接口与穿戴设备配对(蓝牙处于配对状态)并获取地址,然后通过subscribe/unsubscribe接口订阅或取消订阅通知。

  4. 实现NotificationSubscriberExtensionAbility后,还需要在合适的时机调用openSubscriptionSettings接口,打开通知扩展订阅设置页面,引导用户授予获取本机通知的权限,该页面以半模态弹窗显示。建议在设备管理页面提供一个通知授权的按钮,用户点击按钮则调用openSubscriptionSettings接口。

  5. 在应用的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
    }
    
  6. 在应用的string.json文件中添加

      {
        "name": "NotificationSubscriberExtAbility_desc",
        "value": "description"
      },
      {
        "name": "NotificationSubscriberExtAbility_label",
        "value": "ThirdPartyWearableApp"
      }
    
  7. 示例仅为传统蓝牙连接示例,开发者也可选用低功耗蓝牙连接方式。

  8. 用户收到消息后,假如蓝牙连接是无效的,则建立蓝牙连接。

  9. 假如蓝牙连接已经存在,则直接使用这个连接发送消息。

  10. 如果使用该连接发送消息失败,则重新建立连接,如果连接能建立成功则发送消息。

  11. 需要申请权限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|undefined
      public cancelHashCodes: Array<string>|undefined
    }
    // Spp means Serial Port Profile
    class 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);
        }
      }
    }
    

注意:请勿频繁建立连接,可能会影响功能。

你可能感兴趣的鸿蒙文章

openharmony 鸿蒙 notification-enable

openharmony 鸿蒙 notification-overview

openharmony 鸿蒙 notification-with-wantagent

openharmony 鸿蒙 notification-customized-ringtone

openharmony 鸿蒙 Readme-CN

openharmony 鸿蒙 notification-cancel

openharmony 鸿蒙 notification-update

openharmony 鸿蒙 live-view-notification-sys

openharmony 鸿蒙 notification-slot

openharmony 鸿蒙 progress-bar-notification

  • 所属分类: 后端技术
  • 本文标签: 鸿蒙 软件
  • 版权声明: 本文链接 https://seaxiang.com/blog/QcZdRTdd