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

2026-08-25 浏览 (1)

Developing the ExtensionAbility for Notification Subscription

Available APIs

APIDescription
onDestroy(): voidCallback to be invoked when the notification subscription extension is destroyed.
onReceiveMessage(notificationInfo: NotificationInfo): voidCallback to be invoked when a notification is received.
onCancelMessages(hashCodes: Array<string>): voidCallback to be invoked when notifications are canceled.

Prerequisites

You have requested the ohos.permission.SUBSCRIBE_NOTIFICATION permission.

How to Develop

To implement a provider for NotificationSubscriberExtensionAbility, you need to create a NotificationSubscriberExtensionAbility in DevEco Studio project. The procedure is as follows:

  1. Create the entry/src/main/ets/extensionability directory.

  2. Create the NotificationSubscriberExtAbility.ets file in the entry/src/main/ets/extensionability directory. The file content is as follows:

    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. Use the Bluetooth module API to pair with the wearable (with Bluetooth in pairing state) and obtain the device address. Then, subscribe to or unsubscribe from notifications through the subscribe/unsubscribe APIs.

  4. After implementing NotificationSubscriberExtensionAbility, call the openSubscriptionSettings API at an appropriate time to open the notification subscription settings screen and guide the user to grant the permission for obtaining notifications from the device. This screen is displayed as a semi-modal dialog box. It is recommended that you provide a notification authorization button on the device management screen. When the user taps the button, the openSubscriptionSettings API is called.

  5. Configure ExtensionAbilities in the module.json5 file of the application.

    {
      "name": "NotificationSubscriberExtAbility",
      "srcEntry": "./ets/extensionability/NotificationSubscriberExtAbility.ets",
      "type": "notificationSubscriber",
      "description": "$string:NotificationSubscriberExtAbility_desc",
      "icon": "$media:layered_image",
      "label": "$string:NotificationSubscriberExtAbility_label",
      "exported": true
    }
    
  6. Add the following content to the string.json file of the application:

      {
        "name": "NotificationSubscriberExtAbility_desc",
        "value": "description"
      },
      {
        "name": "NotificationSubscriberExtAbility_label",
        "value": "ThirdPartyWearableApp"
      }
    
  7. The following uses classic Bluetooth as an example. You can use BLE for connection as required.

  8. After the user receives a message, the application establishes a Bluetooth connection if the current connection is invalid.

  9. If an active Bluetooth connection already exists, the application directly uses this connection to send the message.

  10. If message transmission fails, the application will re-establish the connection and retry sending the message once the connection is successfully established.

  11. Apply for the ohos.permission.ACCESS_BLUETOOTH permission. For details about how to configure and apply for permissions, see Declaring Permissions and Requesting User Authorization.

    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);
        }
      }
    }
    

Note: Do not frequently establish connections. Otherwise, the functionality may be affected.

你可能感兴趣的鸿蒙文章

openharmony 鸿蒙 notification-enable

openharmony 鸿蒙 notification-overview

openharmony 鸿蒙 notification-with-wantagent

openharmony 鸿蒙 notification-customized-ringtone

openharmony 鸿蒙 notification-cancel

openharmony 鸿蒙 Readme-EN

openharmony 鸿蒙 notification-update

openharmony 鸿蒙 live-view-notification-sys

openharmony 鸿蒙 notification-slot

openharmony 鸿蒙 progress-bar-notification

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