鸿蒙应用服务开发【自定义通知角标】

自定义通知角标

介绍

本示例主要展示了设定应用的桌面图标角标的功能,使用@ohos.notificationManager接口,进行桌面角标的设置,通知的发送,获取等。

效果预览

使用说明

  1. 在主界面,可以看到当前应用的所有消息通知;
  2. 点击右下角Tab页签进入通知发送页面,点击对应的通知即可发送相应类型的通知,点击几次发送几条;
  3. 点击左下角Tab页签进入消息列表,可以查看刚才发送的消息,消息右边会显示消息数量,点击相应的消息可进行消息读取,取消相应通知;
  4. 下拉通知栏,可以看到角标数量,对应消息数量。

具体实现

  • 允许发送通知,发送通知的功能接口封装在NotificationUtil,源码参考:[NotificationUtil.ets]

    /*

    • Copyright (c) 2023 Huawei Device Co., Ltd.
    • Licensed under the Apache License, Version 2.0 (the "License");
    • you may not use this file except in compliance with the License.
    • You may obtain a copy of the License at
    • http://www.apache.org/licenses/LICENSE-2.0
    • Unless required by applicable law or agreed to in writing, software
    • distributed under the License is distributed on an "AS IS" BASIS,
    • WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    • See the License for the specific language governing permissions and
    • limitations under the License.
      */

    import { notificationManager } from '@kit.NotificationKit';
    import { logger } from '../util/Logger';
    import { notificationManagement } from '../notification/NotificationManagementUtil';
    import { BusinessError } from '@kit.BasicServicesKit';

    const TAG: string = 'NotificationUtilModel';

    class NotificationUtil {
    /**
    * enable notification
    */
    private id: number = 0

    复制代码
    async enableNotification() {
      try {
        notificationManager.requestEnableNotification(AppStorage.get('context'), (err: BusinessError): void => {
          if (err) {
            logger.error(TAG, `requestEnableNotification failed, code is ${err.code}, message is ${err.message}`);
          } else {
            logger.info(TAG, 'requestEnableNotification success');
          }
        });
        logger.info(TAG, `enableNotification success`);
      } catch (err) {
        logger.info(TAG, `enableNotification err ${JSON.stringify(err)}`);
      }
    }
    
    /**
     *
     * @param notificationRequest
     * @param id, Support specifying notification id when publishing notifications
     */
    async publishNotification(notificationRequest: notificationManager.NotificationRequest, group?: string) {
      notificationRequest.id = this.id;
      this.id++;
      if (group) {
        notificationRequest.groupName = group;
      }
    
      try {
        await notificationManager.publish(notificationRequest);
        logger.info(TAG, `publish notification success`);
        // 通知管理器添加新通知
        await notificationManagement.addNotification(notificationRequest);
      } catch (err) {
        if (err) {
          logger.info(TAG, `publishNotification err ${JSON.stringify(err)}`);
        }
      }
    }
    
    /**
     * cancel notification by id
     */
    async cancelNotificationById(id: number) {
      try {
        await notificationManager.cancel(id);
        logger.info(TAG, `cancel success`);
      } catch (err) {
        if (err) {
          logger.info(TAG, `cancel err ${JSON.stringify(err)}`);
        }
      }
    }
    
    /**
     * cancel all notification
     */
    async cancelAllNotifications() {
      try {
        await notificationManager.cancelAll();
        logger.info(TAG, `cancel all success`);
      } catch (err) {
        if (err) {
          logger.info(TAG, `cancel all err ${JSON.stringify(err)}`);
        }
      }
    }

    }

    export let notificationUtil = new NotificationUtil();

  • 允许发送通知:在进入[Index.ets] 前通过notificationUtil.enableNotification()调用notification.requestEnableNotification()接口向用户请求发送通知;

    /*

    • Copyright (c) 2023 Huawei Device Co., Ltd.
    • Licensed under the Apache License, Version 2.0 (the "License")
    • you may not use this file except in compliance with the License.
    • You may obtain a copy of the License at
    • http://www.apache.org/licenses/LICENSE-2.0
    • Unless required by applicable law or agreed to in writing, software
    • distributed under the License is distributed on an "AS IS" BASIS,
    • WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    • See the License for the specific language governing permissions and
    • limitations under the License.
      */

    import { NotificationList } from '../components/NotificationList';
    import { NoticePublish } from '../components/NotificationPublish';

    export interface TabImage {
    selectedImage: Resource,
    unselectedImage: Resource,
    }

    const MESSAGE_TAB: TabImage = {
    selectedImage: r('app.media.ic_messages_filled'), unselectedImage: r('app.media.ic_messages'),
    }
    const NOTIFICATION_TAB: TabImage = {
    selectedImage: r('app.media.ic_public_send_filled'), unselectedImage: r('app.media.ic_public_send'),
    }

    interface TAB_INDEX_TYPE {
    MESSAGE_TAB: number
    NOTIFICATION_TAB: number
    }

    const TAB_INDEX: TAB_INDEX_TYPE = {
    MESSAGE_TAB: 0,
    NOTIFICATION_TAB: 1
    }

    @Entry
    @Component
    struct Index {
    @State tabsIndex: number = 0

    复制代码
    @Builder TabBarBuilder(index: number, item: TabImage, tabBarName: Resource) {
    
      Column() {
        Image(this.tabsIndex === index ? item.selectedImage : item.unselectedImage)
          .width(24)
          .height(24)
          .margin({ bottom: 10 })
        Text(tabBarName)
          .fontSize(10)
    
      }
      .width('100%')
      .padding({ top: 0, bottom: 0 })
      .alignItems(HorizontalAlign.Center)
      .id(`tabBar${index}`)
    }
    
    build() {
      Column() {
        Tabs({ barPosition: BarPosition.End }) {
          TabContent() {
            Column() {
              if (this.tabsIndex === TAB_INDEX.MESSAGE_TAB) {
                NotificationList()
              }
              Blank()
            }
            .height('100%')
          }
          .tabBar(this.TabBarBuilder(TAB_INDEX.MESSAGE_TAB, MESSAGE_TAB, $r('app.string.messages_list_title')))
    
          TabContent() {
            Column() {
              NoticePublish()
              Blank()
            }
            .height('100%')
          }
          .tabBar(this.TabBarBuilder(TAB_INDEX.NOTIFICATION_TAB, NOTIFICATION_TAB, $r('app.string.notification_publish_title')),)
        }
        .barHeight(74)
        .barWidth('100%')
        .vertical(false)
        .onChange((index: number) => {
          this.tabsIndex = index
        })
    
      }.width('100%').height('100%')
      .backgroundColor($r('app.color.background_light_gray'))
    }

    }

  • 发送通知:通过publishNotification()封装发布通知的接口;

  • 获取应用所有消息通知、取消相关类型通知,角标管理接口封装在NotificationManagementUtil,源码参考:[NotificationManagementUtil.ets]

    /*

    • Copyright (c) 2023 Huawei Device Co., Ltd.
    • Licensed under the Apache License, Version 2.0 (the "License");
    • you may not use this file except in compliance with the License.
    • You may obtain a copy of the License at
    • http://www.apache.org/licenses/LICENSE-2.0
    • Unless required by applicable law or agreed to in writing, software
    • distributed under the License is distributed on an "AS IS" BASIS,
    • WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    • See the License for the specific language governing permissions and
    • limitations under the License.
      */
      import { notificationManager } from '@kit.NotificationKit';
      import { logger } from '../util/Logger';

    const NOTIFICATION_TYPE_SIZE = 5;

    export interface getAllNotificationsResultType {
    groupNotifications: Array<Array<notificationManager.NotificationRequest>>
    countsByType: Array<number>
    }

    // 通知管理
    class NotificationManagementUtil {
    typeNotifications: Array<Array<notificationManager.NotificationRequest>> = new Array(NOTIFICATION_TYPE_SIZE + 1);
    countsByType: Array<number> = new Array(NOTIFICATION_TYPE_SIZE + 1);
    badgeNum: number = 0;

    复制代码
    constructor() {
      this.countsByType.fill(0);
      for (let i = 0; i < NOTIFICATION_TYPE_SIZE + 1; i++) {
        this.typeNotifications[i] = new Array();
      }
      // 获取当前应用所有通知
      notificationManager.getActiveNotifications().then((notifications) => {
        for (let i = 0; i < notifications.length; i++) {
          let typeId = notifications[i].content.notificationContentType;
          this.countsByType[typeId as number] += 1;
          this.typeNotifications[typeId as number].push(notifications[i]);
        }
        logger.info(`getAllActiveNotifications success, data: ${JSON.stringify(notifications)}`)
        // 计算角标数量
        this.countsByType.forEach((num: number) => {
          this.badgeNum += num;
        })
      })
    }
    
    // 取消属于该类型的通知
    cancelNotificationType(typeId: number) {
      this.typeNotifications[typeId].forEach(item => {
        notificationManager.cancel(item.id);
      })
    }
    
    // 设置角标
    async setBadgeNumber(num: number) {
      await notificationManager.setBadgeNumber(num).then(() => {
        this.badgeNum = num;
        logger.info("displayBadge success");
      });
    }
    
    // 获取角标数量
    getBadgeNumber(): number {
      return this.badgeNum;
    }
    
    // 添加一条消息
    async addNotification(notification: notificationManager.NotificationRequest) {
      const typeId: notificationManager.ContentType = notification.content.notificationContentType as notificationManager.ContentType;
      this.typeNotifications[typeId].push(notification);
      this.countsByType[typeId] += 1;
      this.badgeNum += 1;
      await notificationManagement.setBadgeNumber(this.badgeNum);
      logger.info("add Message success");
    }
    
    // 获取当前所有消息及数量
    async getAllNotifications() {
      let result: getAllNotificationsResultType = {
        groupNotifications: this.typeNotifications,
        countsByType: this.countsByType
      }
      return result;
    }

    }

    export let notificationManagement = new NotificationManagementUtil();

  • 获取应用所有消息通知:在constructor()构造函数中调用@ohos.notificationManager中的getActiveNotifications接口获取所有通知及相应类型通知数量,通过封装getAllNotifications()对外提供接口获取当前消息及消息数量。

  • 取消相关类型通知:通过cancelNotificationType()封装取消相关通知类型的接口;

  • 角标管理接口:通过setBadgeNumber()封装设置应用角标数量的接口,通过getBadgeNumber()封装获取当前应用角标数量的接口。

    • 添加一条通知:通过addNotification()封装接口添加一条通知到消息管理器,当发送通知的时候进行调用。
  • NotificationOperations向外提供接口,在页面中调用它们来实现功能,源码参考:[NotificationOperations.ets]

    /*

    • Copyright (c) 2023 Huawei Device Co., Ltd.
    • Licensed under the Apache License, Version 2.0 (the "License")
    • you may not use this file except in compliance with the License.
    • You may obtain a copy of the License at
    • http://www.apache.org/licenses/LICENSE-2.0
    • Unless required by applicable law or agreed to in writing, software
    • distributed under the License is distributed on an "AS IS" BASIS,
    • WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    • See the License for the specific language governing permissions and
    • limitations under the License.
      */

    import { image } from '@kit.ImageKit';
    import { notificationManager } from '@kit.NotificationKit';
    import { logger, notificationUtil, notificationContentUtil, notificationRequestUtil } from '@ohos/notification';

    const TAG: string = 'Sample_Notification';
    const MULTI_LINE_CONTENT: Array<string> = ['line0', 'line1', 'line2', 'line3']; // 多行文本通知的多行文本内容

    interface NOTIFICATION_GROUP_TYPE {
    BASIC: string
    LONG_TEXT: string
    MULTI_LINE: string
    PICTURE: string
    CONVERSATION: string
    }

    const NOTIFICATION_GROUP: NOTIFICATION_GROUP_TYPE = { // 定义不同类型通知的通知组
    BASIC: 'BASIC',
    LONG_TEXT: 'LONG_TEXT',
    MULTI_LINE: 'MULTI_LINE',
    PICTURE: 'PICTURE',
    CONVERSATION: 'CONVERSATION'
    }

    export default class NotificationOperations {
    private context: Context;
    private basicContent: notificationManager.NotificationBasicContent;

    复制代码
    // 在初始化函数初始化基本通知类型的参数
    constructor(context: Context) {
      this.context = context;
      let notificationTitle = '';
      let notificationText = this.context.resourceManager.getStringSync($r('app.string.notification_content'));
      let notificationAdditional = this.context.resourceManager.getStringSync($r('app.string.notification_additional'));
      this.basicContent = {
        title: notificationTitle,
        text: notificationText,
        additionalText: notificationAdditional
      }
    }
    
    // 发布基本类型通知
    publishBasicNotification = () => {
      try {
        logger.info(TAG, 'publishBasicNotification');
        this.basicContent.title = this.context.resourceManager.getStringSync($r('app.string.basic_notification'));
        let notificationContent = notificationContentUtil.initBasicNotificationContent(this.basicContent);
        notificationUtil.publishNotification(notificationRequestUtil.initBasicNotificationRequest(notificationContent as notificationManager.NotificationContent) as notificationManager.NotificationRequest);
      } catch (error) {
        logger.info(TAG, `publishBasicNotification error, error = ${JSON.stringify(error)}`);
      }
    }
    // 发布长文本类型通知
    publishLongTextNotification = () => {
      try {
        logger.info(TAG, 'publishLongTextNotification');
        this.basicContent.title = this.context.resourceManager.getStringSync($r('app.string.long_text_notification'));
        let notificationLongText = this.context.resourceManager.getStringSync($r('app.string.notification_long_text'));
        let notificationBriefText = this.context.resourceManager.getStringSync($r('app.string.notification_brief_text'));
        let notificationExpandedText = this.context.resourceManager.getStringSync($r('app.string.notification_expanded_title'));
        let notificationContent = notificationContentUtil.initNotificationLongTextContent(this.basicContent, notificationLongText, notificationBriefText, notificationExpandedText);
        notificationUtil.publishNotification(notificationRequestUtil.initBasicNotificationRequest(notificationContent as notificationManager.NotificationContent) as notificationManager.NotificationRequest);
      } catch (error) {
        logger.info(TAG, `publishLongTextNotification error, error = ${JSON.stringify(error)}`);
      }
    }
    // 发布多行文本类型通知
    publishMultiLineNotification = () => {
      try {
        logger.info(TAG, 'publishMultiLineNotification');
        this.basicContent.title = this.context.resourceManager.getStringSync($r('app.string.multiline_notification'));
        let notificationBriefText = this.context.resourceManager.getStringSync($r('app.string.notification_brief_text'));
        let notificationLongTitle = this.context.resourceManager.getStringSync($r('app.string.notification_expanded_title'));
        let notificationContent = notificationContentUtil.initNotificationMultiLineContent(this.basicContent, notificationBriefText, notificationLongTitle, MULTI_LINE_CONTENT);
        notificationUtil.publishNotification(notificationRequestUtil.initBasicNotificationRequest(notificationContent as notificationManager.NotificationContent) as notificationManager.NotificationRequest);
      } catch (error) {
        logger.info(TAG, `publishMultiLineNotification error, error = ${JSON.stringify(error)}`);
      }
    }
    // 发布图片类型通知
    publishPictureNotification = async () => {
      try {
        logger.info(TAG, 'publishPictureNotification');
        this.basicContent.title = this.context.resourceManager.getStringSync($r('app.string.picture_notification'));
        let notificationBriefText = this.context.resourceManager.getStringSync($r('app.string.notification_brief_text'));
        let notificationExpandedText = this.context.resourceManager.getStringSync($r('app.string.notification_expanded_title'));
        let imageArray = await this.context.resourceManager.getMediaContent($r('app.media.notification_icon').id);
        let imageResource = image.createImageSource(imageArray.buffer as ArrayBuffer);
        let picture = await imageResource.createPixelMap();
        let notificationContent = notificationContentUtil.initNotificationPictureContent(this.basicContent, notificationBriefText, notificationExpandedText, picture);
        notificationUtil.publishNotification(notificationRequestUtil.initBasicNotificationRequest(notificationContent as notificationManager.NotificationContent) as notificationManager.NotificationRequest);
      } catch (error) {
        logger.info(TAG, `publishPictureNotification error, error = ${JSON.stringify(error)}`);
      }
    }
    // 发布社交类型的通知
    publishConversationNotification = async () => {
      try {
        logger.info(TAG, 'publishConversationNotification');
        this.basicContent.title = this.context.resourceManager.getStringSync($r('app.string.conversation_notification'));
        let notificationContent = notificationContentUtil.initNotificationConversationContent(this.basicContent);
        notificationUtil.publishNotification(notificationRequestUtil.initBasicNotificationRequest(notificationContent as notificationManager.NotificationContent) as notificationManager.NotificationRequest, NOTIFICATION_GROUP.CONVERSATION);
      } catch (error) {
        logger.info(TAG, `publishNotificationWithWantAgent error, error = ${JSON.stringify(error)}`);
      }
    }

    }

  • 发布通知:在[Index.ets]页面中进入发送通知Tab页签,通过点击事件调用NotificationOperations中封装的对应的方法,然后从NotificationContentUtil中获取对应的主体内容content,将 content传递给NotificationRequestUtil得到完整的发布信息,最后调用NotificationUtil.publishNotification()发布内容,并调用NotificationManagementUtil的addNotification()添加一条消息;

    /*

    • Copyright (c) 2023 Huawei Device Co., Ltd.
    • Licensed under the Apache License, Version 2.0 (the "License")
    • you may not use this file except in compliance with the License.
    • You may obtain a copy of the License at
    • http://www.apache.org/licenses/LICENSE-2.0
    • Unless required by applicable law or agreed to in writing, software
    • distributed under the License is distributed on an "AS IS" BASIS,
    • WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    • See the License for the specific language governing permissions and
    • limitations under the License.
      */

    import { NotificationList } from '../components/NotificationList';
    import { NoticePublish } from '../components/NotificationPublish';

    export interface TabImage {
    selectedImage: Resource,
    unselectedImage: Resource,
    }

    const MESSAGE_TAB: TabImage = {
    selectedImage: r('app.media.ic_messages_filled'), unselectedImage: r('app.media.ic_messages'),
    }
    const NOTIFICATION_TAB: TabImage = {
    selectedImage: r('app.media.ic_public_send_filled'), unselectedImage: r('app.media.ic_public_send'),
    }

    interface TAB_INDEX_TYPE {
    MESSAGE_TAB: number
    NOTIFICATION_TAB: number
    }

    const TAB_INDEX: TAB_INDEX_TYPE = {
    MESSAGE_TAB: 0,
    NOTIFICATION_TAB: 1
    }

    @Entry
    @Component
    struct Index {
    @State tabsIndex: number = 0

    复制代码
    @Builder TabBarBuilder(index: number, item: TabImage, tabBarName: Resource) {
    
      Column() {
        Image(this.tabsIndex === index ? item.selectedImage : item.unselectedImage)
          .width(24)
          .height(24)
          .margin({ bottom: 10 })
        Text(tabBarName)
          .fontSize(10)
    
      }
      .width('100%')
      .padding({ top: 0, bottom: 0 })
      .alignItems(HorizontalAlign.Center)
      .id(`tabBar${index}`)
    }
    
    build() {
      Column() {
        Tabs({ barPosition: BarPosition.End }) {
          TabContent() {
            Column() {
              if (this.tabsIndex === TAB_INDEX.MESSAGE_TAB) {
                NotificationList()
              }
              Blank()
            }
            .height('100%')
          }
          .tabBar(this.TabBarBuilder(TAB_INDEX.MESSAGE_TAB, MESSAGE_TAB, $r('app.string.messages_list_title')))
    
          TabContent() {
            Column() {
              NoticePublish()
              Blank()
            }
            .height('100%')
          }
          .tabBar(this.TabBarBuilder(TAB_INDEX.NOTIFICATION_TAB, NOTIFICATION_TAB, $r('app.string.notification_publish_title')),)
        }
        .barHeight(74)
        .barWidth('100%')
        .vertical(false)
        .onChange((index: number) => {
          this.tabsIndex = index
        })
    
      }.width('100%').height('100%')
      .backgroundColor($r('app.color.background_light_gray'))
    }

    }

以上就是本篇文章所带来的鸿蒙开发中一小部分技术讲解;想要学习完整的鸿蒙全栈技术。可以在结尾找我可全部拿到!

下面是鸿蒙的完整学习路线 ,展示如下:

除此之外,根据这个学习鸿蒙全栈学习路线,也附带一整套完整的学习【文档+视频】,内容包含如下

内容包含了:(ArkTS、ArkUI、Stage模型、多端部署、分布式应用开发、音频、视频、WebGL、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、鸿蒙南向开发、鸿蒙项目实战)等技术知识点。帮助大家在学习鸿蒙路上快速成长!

鸿蒙【北向应用开发+南向系统层开发】文档

鸿蒙【基础+实战项目】视频

鸿蒙面经

为了避免大家在学习过程中产生更多的时间成本,对比我把以上内容全部放在了↓↓↓想要的可以自拿喔!谢谢大家观看!

相关推荐
一只栖枝5 小时前
华为 HCIE 大数据认证中 Linux 命令行的运用及价值
大数据·linux·运维·华为·华为认证·hcie·it
zhanshuo9 小时前
在鸿蒙里优雅地处理网络错误:从 Demo 到实战案例
harmonyos
zhanshuo9 小时前
在鸿蒙中实现深色/浅色模式切换:从原理到可运行 Demo
harmonyos
whysqwhw14 小时前
鸿蒙分布式投屏
harmonyos
whysqwhw15 小时前
鸿蒙AVSession Kit
harmonyos
whysqwhw17 小时前
鸿蒙各种生命周期
harmonyos
whysqwhw18 小时前
鸿蒙音频编码
harmonyos
whysqwhw18 小时前
鸿蒙音频解码
harmonyos
whysqwhw18 小时前
鸿蒙视频解码
harmonyos
whysqwhw18 小时前
鸿蒙视频编码
harmonyos