HarmonyOS NEXT-公共事件与通知功能实现

195 阅读8分钟

公共事件与通知功能实现

帝心:全网首发HarmonyOS4.0教程(哔哩哔哩)创作者。致力于推广鸿蒙教程开发。

  1. 个人网站-鸿蒙学院
  2. 语雀笔记-编程视界
  3. 微信公众号:不多讲故事

developer.huawei.com/consumer/cn…


打开 APP 时,推送一个通知

使用Noification Kit的主要业务流程如下:

  1. 请求通知授权。
  2. 应用发布通知到通知服务。
  3. 将通知展示到通知中心。

通知工具类

本工具类具备如下基础功能

    1. 启动APP即发送通知
    2. 添加通知类型
    3. 请求授权并发布普通文本类型通知

待扩展功能:

    1. 发布多行文本类型通知
    2. 发布进度条通知
    3. 为通知添加行为意图
// 发布通知的工具类
import { common } from '@kit.AbilityKit'
import { notificationManager } from '@kit.NotificationKit'
import { BusinessError } from '@kit.BasicServicesKit'

class NotificationUtils {
  // 添加通知类型 https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V5/js-apis-notificationmanager-V5#slottype
  addNotificationType() {
    // 添加通知类型 : addslot回调
    //  社交通信类通知 : SlotType.SOCIAL_COMMUNICATION
    // 内容咨询类通知 : SlotType.CONTENT_INFORMATION
    // 服务提醒 : SlotType.SERVICE_INFORMATION
    notificationManager.addSlot(notificationManager.SlotType.SERVICE_INFORMATION, (err: BusinessError): void => {
      if (err) {
        console.log(`dxin => 添加通知失败 ${err.code}, message is ${err.message}`);
      } else {
        console.log(`dxin => 添加通知成功`);
      }
    });
  }

  publishNotification() {
    // 添加通知类型  可以调用也可以不调用
    // this.addNotificationType()

    let context = getContext(this) as common.UIAbilityContext

    // 1. 请求通知授权  同步 响应值为 boolean 类型
    let authorizationFlag = notificationManager.isNotificationEnabledSync()

    if (authorizationFlag) {
      // 2.能进来就不是第一次
      console.log('dxin =>  用户曾经在弹窗授权过')
      // 再次发送通知 就是以后打开app页发通知。 如果只有首次打开发送通知。可注释下面这行
      this.publishNotificationAction()    // 真正发通知的动作
    } else {
      //   3.第一次启动app 未授权 拉起弹窗 让用户授权
      // 可通过requestEnableNotification的错误码判断用户是否授权。若返回的错误码为1600004,即为拒绝授权。
      // 应用请求通知使能模态弹窗。使用Promise异步回调。  无返回结果
      notificationManager.requestEnableNotification(context)
        .then(() => {
          console.log('dxin => 用户已经授权ed')
          this.publishNotificationAction()
        })
        .catch((err: BusinessError) => {
          if (1600004 == err.code) {
            console.log('dxin => "用户拒绝授权')
          }else {
            console.log('dxin => 授权失败,原因未知。')
          }
        })
    }
  }

  //  发布通知的动作。真正发通知的效果。
   publishNotificationAction(){
    // 准备通知的内容
    let notificationRequest: notificationManager.NotificationRequest = {
      id: 1,
      content: {
        notificationContentType: notificationManager.ContentType.NOTIFICATION_CONTENT_BASIC_TEXT, // 普通文本类型通知
        normal: {
          title: '通知标题',
          text: '通知文本',
          additionalText: 'test_additionalText:通知附加文本',
        }
      }
    };
    // 发布通知
    notificationManager.publish(notificationRequest, (err: BusinessError) => {
      if (err) {
        console.log('dxin => 发布通知时出错了', err.message)
        return
      } else {
        console.log('dxin => 发布通知succeed')
      }
    });
  }
}
export default new NotificationUtils()
import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit';
import { window } from '@kit.ArkUI';
import notificationUtils from '../common/NotificationUtils';

export default class EntryAbility extends UIAbility {

  onWindowStageCreate(windowStage: window.WindowStage): void {
    windowStage.loadContent('pages/Index', (err) => {
      if (err.code) {
        return;
      }
      // 成功加载页面 发送通知
      notificationUtils.publishNotification()
    })
  }

  // ...
}
import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit';
import { window } from '@kit.ArkUI';
import notificationUtils from '../common/NotificationUtils';

export default class EntryAbility extends UIAbility {

  onWindowStageCreate(windowStage: window.WindowStage): void {
    windowStage.loadContent('pages/Index', (err) => {
      if (err.code) {
        return;
      }
      // 成功加载页面 发送通知
      notificationUtils.publishNotification()
    })
  }

  // ...
}

在通知页面发送多种通知

1. 优化工具类

设计思路

  1. 调用相同的函数发送不同种类通知
  2. 通知内容由参数控制
// 发布通知的工具类
import { common } from '@kit.AbilityKit'
import { notificationManager } from '@kit.NotificationKit'
import { BusinessError } from '@kit.BasicServicesKit'

class NotificationUtils {
  // 添加通知类型 https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V5/js-apis-notificationmanager-V5#slottype
  addNotificationType() {
    // 添加通知类型 : addslot回调
    //  社交通信类通知 : SlotType.SOCIAL_COMMUNICATION
    // 内容咨询类通知 : SlotType.CONTENT_INFORMATION
    // 服务提醒 : SlotType.SERVICE_INFORMATION
    notificationManager.addSlot(notificationManager.SlotType.SERVICE_INFORMATION, (err: BusinessError): void => {
      if (err) {
        console.log(`dxin => 添加通知失败 ${err.code}, message is ${err.message}`);
      } else {
        console.log(`dxin => 添加通知成功`);
      }
    });
  }

  publishNotification(notificationRequest:notificationManager.NotificationRequest) {
    // 添加通知类型  可以调用也可以不调用
    // this.addNotificationType()

    let context = getContext(this) as common.UIAbilityContext

    // 1. 请求通知授权  同步 响应值为 boolean 类型
    let authorizationFlag = notificationManager.isNotificationEnabledSync()

    if (authorizationFlag) {
      // 2.能进来就不是第一次
      console.log('dxin =>  用户曾经在弹窗授权过')
      // 再次发送通知 就是以后打开app页发通知。 如果只有首次打开发送通知。可注释下面这行
      this.publishNotificationAction(notificationRequest)    // 真正发通知的动作
    } else {
      //   3.第一次启动app 未授权 拉起弹窗 让用户授权
      // 可通过requestEnableNotification的错误码判断用户是否授权。若返回的错误码为1600004,即为拒绝授权。
      // 应用请求通知使能模态弹窗。使用Promise异步回调。  无返回结果
      notificationManager.requestEnableNotification(context)
        .then(() => {
          console.log('dxin => 用户已经授权ed')
          this.publishNotificationAction(notificationRequest)
        })
        .catch((err: BusinessError) => {
          if (1600004 == err.code) {
            console.log('dxin => "用户拒绝授权')
          }else {
            console.log('dxin => 授权失败,原因未知。')
          }
        })
    }
  }

  //  发布通知的动作。真正发通知的效果。
   publishNotificationAction(notificationRequest:notificationManager.NotificationRequest){

    // 发布通知
    notificationManager.publish(notificationRequest, (err: BusinessError) => {
      if (err) {
        console.log('dxin => 发布通知时出错了', err.message)
        return
      } else {
        console.log('dxin => 发布通知succeed')
      }
    });
  }
}

export default new NotificationUtils()

2. 发送不同种类的通知

let notificationBasicContent: notificationManager.NotificationRequest = {
  id: 1,
  content: {
    notificationContentType: notificationManager.ContentType.NOTIFICATION_CONTENT_BASIC_TEXT, // 普通文本类型通知
    normal: {
      title: '普通通知标题',
      text: '通知内容(不可为空字符串,大小不超过200字节,超出部分会被截断)',
      additionalText: '通知附加内容,是对通知内容的补充',
      // lockscreenPicture: image.PixelMap类型。通知在锁屏界面显示的图片。当前仅支持实况窗类型通知。
    }
  }
};
notificationUtils.publishNotification(notificationBasicContent)
let notificationLongTextContent: notificationManager.NotificationRequest = {
  id: 2,
  content: {
    notificationContentType: notificationManager.ContentType.NOTIFICATION_CONTENT_LONG_TEXT, // 普通文本类型通知
    longText: {
      title: '长文本-通知标题',
      text: '长文本-通知内容',
      additionalText: "通知附加内容,是对通知内容的补充",
      longText: "通知的长文本(不可为空字符串,大小不超过1024字节,超出部分会被截断)",
      briefText: "通知概要内容,是对通知内容的总结(不可为空字符串,大小不超过200字节,超出部分会被截断)。",
      expandedTitle: "通知展开时的标题(不可为空字符串,大小不超过200字节,超出部分会被截断)。"
    }
  }
};
notificationUtils.publishNotification(notificationLongTextContent)
let multipleLinesNft: notificationManager.NotificationRequest = {
  id: 3,
  content: {
    notificationContentType: notificationManager.ContentType.NOTIFICATION_CONTENT_MULTILINE, // 多行文本类型通知
    multiLine: {
      title: '多行通知-标题',
      text: '多行通知-文本',
      briefText: '通知概要内容,是对通知的总结。关键是什么情况下显示呢',
      longTitle: '通知展开时的标题(不可为空字符串,大小不超过200字节,超出部分会被截断)',
      lines: ['多行通知第1行文本内容', '多行通知第2行文本内容:测试长度超出省略的效果', 'line_03', 'line_04'],
    }
  }
};
notificationUtils.publishNotification(multipleLinesNft)
let notificationProgress: notificationManager.NotificationRequest = {
  id: 4,
  content: {
    notificationContentType: notificationManager.ContentType.NOTIFICATION_CONTENT_BASIC_TEXT,
    normal: {
      title: "进度条-通知标题",
      text: "进度条-通知内容",
      additionalText: "通知附加内容,是对通知内容的补充"
    }
  },
  // 构造进度条模板 name字段当前需要固定配置为downloadTemplate
  template: {
    name: 'downloadTemplate',
    data: { title: "进度条通知data", fileName: "文件名比如歌曲", progressValue: 50 }
  }
}
//     3 发布进度条通知
notificationUtils.publishNotification(notificationProgress)
let notificationBasicContent: notificationManager.NotificationRequest = {
  id: 1,
  badgeNumber:100,
  content: {
    notificationContentType: notificationManager.ContentType.NOTIFICATION_CONTENT_BASIC_TEXT, // 普通文本类型通知
    normal: {
      title: '角标通知标题',
      text: '角标是在logo上显示',
      additionalText: '...',
    }
  }
};
notificationUtils.publishNotification(notificationBasicContent)

3. 案例代码

import notificationUtils from '../common/NotificationUtils';
import { notificationManager } from '@kit.NotificationKit';

@Entry
@Component
struct PublishNotification {
  @State message: string = '准备发送通知'

  build() {
    Column({ space: 20 }) {
      Text(this.message).fontSize(20).fontColor('#ffd64a4a')
      Divider()
      Text('发布不同种类通知').fontSize(30).fontWeight(700)
      Button('发布【普通文本】通知').fontSize(22)
        .onClick(() => {
          // 普通通知
          // 准备通知的内容
          let notificationBasicContent: notificationManager.NotificationRequest = {
            id: 1,
            content: {
              notificationContentType: notificationManager.ContentType.NOTIFICATION_CONTENT_BASIC_TEXT, // 普通文本类型通知
              normal: {
                title: '普通通知标题',
                text: '通知内容(不可为空字符串,大小不超过200字节,超出部分会被截断)',
                additionalText: '通知附加内容,是对通知内容的补充',
                // lockscreenPicture: image.PixelMap类型。通知在锁屏界面显示的图片。当前仅支持实况窗类型通知。
              }
            }
          };
          notificationUtils.publishNotification(notificationBasicContent)
          this.message = '发送【普通】通知OK'
        })
      Button('发布【长文本】通知').fontSize(22)
        .onClick(() => {
          // 普通通知
          // 准备通知的内容
          let notificationLongTextContent: notificationManager.NotificationRequest = {
            id: 2,
            content: {
              notificationContentType: notificationManager.ContentType.NOTIFICATION_CONTENT_LONG_TEXT, // 普通文本类型通知
              longText: {
                title: '长文本-通知标题',
                text: '长文本-通知内容',
                additionalText: "通知附加内容,是对通知内容的补充",
                longText: "通知的长文本(不可为空字符串,大小不超过1024字节,超出部分会被截断)",
                briefText: "通知概要内容,是对通知内容的总结(不可为空字符串,大小不超过200字节,超出部分会被截断)。",
                expandedTitle: "通知展开时的标题(不可为空字符串,大小不超过200字节,超出部分会被截断)。"
              }
            }
          };
          notificationUtils.publishNotification(notificationLongTextContent)
          this.message = '发送【长文本】通知OK'
        })
      Button('发布多行文本通知').fontSize(22)
        .onClick(() => {
          // 多行通知
          let multipleLinesNft: notificationManager.NotificationRequest = {
            id: 3,
            content: {
              notificationContentType: notificationManager.ContentType.NOTIFICATION_CONTENT_MULTILINE, // 多行文本类型通知
              multiLine: {
                title: '多行通知-标题',
                text: '多行通知-文本',
                briefText: '通知概要内容,是对通知的总结。关键是什么情况下显示呢',
                longTitle: '通知展开时的标题(不可为空字符串,大小不超过200字节,超出部分会被截断)',
                lines: ['多行通知第1行文本内容', '多行通知第2行文本内容:测试长度超出省略的效果', 'line_03', 'line_04'],
              }
            }
          };
          notificationUtils.publishNotification(multipleLinesNft)
          this.message = '发送【多行】通知OK'
        })
      Button('发布进度条通知').fontSize(22)
        .onClick(() => {
          //  2 准备进度条通知内容
          let notificationProgress: notificationManager.NotificationRequest = {
            id: 4,
            content: {
              notificationContentType: notificationManager.ContentType.NOTIFICATION_CONTENT_BASIC_TEXT,
              normal: {
                title: "进度条-通知标题",
                text: "进度条-通知内容",
                additionalText: "通知附加内容,是对通知内容的补充"
              }
            },
            // 构造进度条模板 name字段当前需要固定配置为downloadTemplate
            template: {
              name: 'downloadTemplate',
              data: { title: "进度条通知data", fileName: "文件名比如歌曲", progressValue: 50 }
            }
          }
          //     3 发布进度条通知
          notificationUtils.publishNotification(notificationProgress)
          this.message ="发布【进度条】通知ok"
          // 1. 需要查询系统是否支持进度条模板 由于系统是默认支持的。所以就注释掉了
          // notificationManager.isSupportTemplate("downloadTemplate")
          //   .then((data: boolean) => {
          //     if (data) {
          //       //如果支持
          //       this.message = '系统支持进度条模板'
          //       //  2 准备进度条通知内容
          //       let notificationProgress: notificationManager.NotificationRequest = {
          //         id: 4,
          //         content: {
          //           notificationContentType: notificationManager.ContentType.NOTIFICATION_CONTENT_BASIC_TEXT,
          //           normal: {
          //             title: "进度条-通知标题",
          //             text: "进度条-通知内容",
          //             additionalText: "通知附加内容,是对通知内容的补充"
          //           }
          //         },
          //         // 构造进度条模板 name字段当前需要固定配置为downloadTemplate
          //         template: {
          //           name: 'downloadTemplate',
          //           data: { title: "进度条通知data", fileName: "文件名比如歌曲", progressValue: 50 }
          //         }
          //       }
          //       //     3 发布进度条通知
          //       notificationUtils.publishNotification(notificationProgress)
          //       this.message ="发布【进度条】通知ok"
          //     } else {
          //       this.message = '系统不支持进度条模板'
          //     }
          //   })
        })

      Button('发布【角标】通知').fontSize(22)
        .onClick(() => {
          // 普通通知
          // 准备通知的内容
          let notificationBasicContent: notificationManager.NotificationRequest = {
            id: 1,
            badgeNumber:100,
            content: {
              notificationContentType: notificationManager.ContentType.NOTIFICATION_CONTENT_BASIC_TEXT, // 普通文本类型通知
              normal: {
                title: '角标通知标题',
                text: '角标是在logo上显示',
                additionalText: '...',
              }
            }
          };
          notificationUtils.publishNotification(notificationBasicContent)
          this.message = '发送【角标】通知OK。返回桌面查看'
        })
      Text('更过种类的通知请参考官方文档扩展学习').fontSize(18)
    }
    .width('100%')
    .height('100%')
    .backgroundColor($r('app.color.theme_color'))
    .justifyContent(FlexAlign.Center)
  }
}