HarmonyOS NotificationManager 模块完全指南 —— 从入门到精通

适用版本:HarmonyOS 6.1.0 Release (API 23+) 及以上
关键词:NotificationManager、通知授权、权限管理、HarmonyOS开发


📋 效果


1. 模块概述

1.1 什么是 NotificationManager?

@ohos.notificationManager(NotificationManager 模块)是 HarmonyOS Notification Kit 的核心模块,负责管理应用的通知权限与通知发布能力。它提供了从权限检查、授权弹窗拉起到系统设置跳转的完整 API 链,是应用接入通知能力的第一步。

1.2 导入方式

import { notificationManager } from '@kit.NotificationKit';
import { common } from '@kit.AbilityKit';
import { BusinessError } from '@kit.BasicServicesKit';

⚠️ 注意BusinessError 必须从 @kit.BasicServicesKit 导入,不可遗漏。错误处理中需要使用 err as BusinessError 进行类型断言以获取 codemessage 属性。

1.3 核心能力一览

能力分类 接口 说明
状态查询 isNotificationEnabled() 异步查询通知是否已授权
状态查询 isNotificationEnabledSync() 同步查询通知是否已授权
一次授权 requestEnableNotification() 拉起系统授权对话框
二次授权 openNotificationSettings() 跳转系统通知设置页面
通知发布 publish() 发布一条本地通知
通知取消 cancel() / cancelAll() 取消指定或全部通知
角标管理 setBadgeNumber() 设置桌面角标数字

2. 核心 API 详解

2.1 通知状态查询

通知授权状态查询是权限管理的起点。HarmonyOS 提供了同步和异步两种方式:

同步查询(推荐)
// 同步方式 - 性能更优,无需 await
const enabled: boolean = notificationManager.isNotificationEnabledSync();
if (enabled) {
    console.info('通知权限已开启');
} else {
    console.info('通知权限未开启');
}

优势:同步调用无需 async/await,执行效率更高,适合在 aboutToAppear() 等生命周期中快速判断。

异步查询
// 异步方式 - Promise 风格
notificationManager.isNotificationEnabled()
    .then((enabled: boolean) => {
        if (enabled) {
            console.info('通知权限已开启');
        } else {
            console.info('通知权限未开启');
        }
    })
    .catch((err: BusinessError) => {
        console.error(`查询失败: ${err.code}, ${err.message}`);
    });
接口对比
特性 isNotificationEnabledSync() isNotificationEnabled()
调用方式 同步 异步(Promise)
返回值 boolean Promise<boolean>
API 版本 12+ 9+
适用场景 快速状态判断 需要链式调用时

2.2 请求通知授权(一次授权)

requestEnableNotification() 是调用系统授权弹窗的核心接口。该接口仅在首次调用时弹出系统对话框,用户做出选择后,后续再次调用将不会弹窗。

async function requestPermission(context: common.UIAbilityContext): Promise<void> {
    try {
        await notificationManager.requestEnableNotification(context);
        console.info('用户已授权通知权限');
    } catch (err) {
        const bizErr = err as BusinessError;
        if (bizErr.code === 1600004) {
            // 错误码 1600004 = 用户明确拒绝了授权
            console.warn('用户拒绝了通知授权');
        } else {
            console.error(`请求授权失败: ${bizErr.code}, ${bizErr.message}`);
        }
    }
}

关键理解

  • 该方法返回 Promise,成功表示用户点击了"允许"
  • 抛出异常且错误码为 1600004 表示用户点击了"拒绝"
  • 用户拒绝后,该方法将永远不再弹窗,必须通过 openNotificationSettings() 引导用户手动开启
调用时序图
用户 系统弹窗 NotificationManager 应用 用户 系统弹窗 NotificationManager 应用 alt [用户点击允许] [用户点击拒绝] requestEnableNotification(context) 弹出授权对话框 显示"允许"/"拒绝"选项 点击允许 授权成功 Promise resolve 点击拒绝 授权拒绝 Promise reject (code: 1600004)

2.3 打开通知设置页面(二次授权)

当用户在一次授权中拒绝了通知权限后,应用应通过 openNotificationSettings() 引导用户前往系统设置页面手动开启。

async function openSettings(context: common.UIAbilityContext): Promise<void> {
    try {
        await notificationManager.openNotificationSettings(context);
        console.info('已跳转至系统通知设置页面');
    } catch (err) {
        const bizErr = err as BusinessError;
        console.error(`打开设置失败: ${bizErr.code}, ${bizErr.message}`);
    }
}

注意

  • 该接口拉起的是半模态通知管理页面,而非完全跳转到系统设置应用
  • 页面关闭时,不会直接回调结果,需通过 onVisibilityChange()onPageShow() 重新检查状态
  • 该接口在用户拒绝授权后调用才有实际意义

3. 完整授权流程

3.1 推荐流程图

已授权

未授权

用户允许

用户拒绝

返回应用

应用启动

isNotificationEnabledSync?

正常使用通知功能

requestEnableNotification
一次授权弹窗

openNotificationSettings
引导去设置

用户在系统设置中开启

3.2 三步走策略

步骤 操作 API 说明
Step 1 检查状态 isNotificationEnabledSync() 判断是否需要授权
Step 2 一次授权 requestEnableNotification() 系统弹窗请求,仅首次生效
Step 3 二次授权 openNotificationSettings() 引导用户去设置页面手动开启

4. 实战代码示例

4.1 完整授权管理工具类

以下是一个可以直接在项目中使用的通知授权管理工具类,封装了三种授权场景的处理逻辑:

import { notificationManager } from '@kit.NotificationKit';
import { common } from '@kit.AbilityKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { hilog } from '@kit.PerformanceAnalysisKit';

const TAG: string = 'NotificationUtil';
const DOMAIN: number = 0x0000;

export class NotificationUtil {

  /**
   * 同步检查通知权限是否已启用
   * @returns true=已启用, false=未启用
   */
  static isNotificationEnabled(): boolean {
    try {
      return notificationManager.isNotificationEnabledSync();
    } catch (err) {
      hilog.error(DOMAIN, TAG, `检查通知状态异常`);
      return false;
    }
  }

  /**
   * 请求通知授权 —— 一次授权
   * 首次调用弹出系统授权对话框
   * @param context UIAbilityContext
   * @returns true=授权成功, false=用户拒绝
   */
  static async requestPermission(context: common.UIAbilityContext): Promise<boolean> {
    try {
      await notificationManager.requestEnableNotification(context);
      hilog.info(DOMAIN, TAG, '通知授权成功');
      return true;
    } catch (err) {
      const bizErr = err as BusinessError;
      if (bizErr.code === 1600004) {
        hilog.warn(DOMAIN, TAG, '用户拒绝通知授权');
      } else {
        hilog.error(DOMAIN, TAG, `请求授权失败: ${bizErr.code}`);
      }
      return false;
    }
  }

  /**
   * 打开系统通知设置 —— 二次授权
   * @param context UIAbilityContext
   */
  static async openSettings(context: common.UIAbilityContext): Promise<void> {
    try {
      await notificationManager.openNotificationSettings(context);
      hilog.info(DOMAIN, TAG, '已打开通知设置页面');
    } catch (err) {
      const bizErr = err as BusinessError;
      hilog.error(DOMAIN, TAG, `打开设置失败: ${bizErr.code}`);
    }
  }

  /**
   * 智能授权流程:自动判断并执行完整的通知授权
   * @param context UIAbilityContext
   */
  static async smartAuthorize(context: common.UIAbilityContext): Promise<boolean> {
    // Step 1: 检查是否已授权
    if (this.isNotificationEnabled()) {
      hilog.info(DOMAIN, TAG, '通知已授权,无需处理');
      return true;
    }

    // Step 2: 一次授权
    const granted = await this.requestPermission(context);
    if (granted) {
      return true;
    }

    // Step 3: 二次授权
    hilog.info(DOMAIN, TAG, '一次授权被拒,引导用户去设置');
    await this.openSettings(context);
    return false;
  }
}

4.2 在页面中使用

import { NotificationUtil } from '../utils/NotificationUtil';
import { common } from '@kit.AbilityKit';

@Entry
@ComponentV2
struct MyPage {
  private context: common.UIAbilityContext =
    this.getUIContext().getHostContext() as common.UIAbilityContext;

  async aboutToAppear(): Promise<void> {
    // 智能授权:自动处理全部流程
    const authorized = await NotificationUtil.smartAuthorize(this.context);
    if (authorized) {
      console.info('通知权限已就绪');
    }
  }

  build() {
    Column() {
      Text('我的页面')
    }
  }
}

4.3 使用 V2 状态管理集成

// 在 @ObservedV2 类中管理通知授权状态
@ObservedV2
class NotificationState {
  @Trace isAuthorized: boolean = false;
  @Trace isChecking: boolean = true;

  public checkStatus(): void {
    this.isChecking = true;
    this.isAuthorized = notificationManager.isNotificationEnabledSync();
    this.isChecking = false;
  }

  public async requestAuth(context: common.UIAbilityContext): Promise<void> {
    try {
      await notificationManager.requestEnableNotification(context);
      this.isAuthorized = true;
    } catch (err) {
      const bizErr = err as BusinessError;
      if (bizErr.code === 1600004) {
        this.isAuthorized = false;
      }
    }
  }
}

5. 错误码参考

错误码 说明 处理建议
1600001 内部错误 重试或检查系统状态
1600002 参数错误 检查 context 是否有效
1600003 连接通知服务失败 检查系统服务状态
1600004 用户拒绝通知授权 引导用户去设置页面手动开启
1600007 通知数量超过限制 清理不必要的通知
1600015 应用未被授权发布通知 先调用 requestEnableNotification

重点关注 1600004:这是开发中最常遇到的错误码,代表用户在系统弹窗中点击了"拒绝"。此时不应再次调用 requestEnableNotification()(它不会再弹窗),而应调用 openNotificationSettings() 引导用户手动设置。


6. 最佳实践与避坑指南

6.1 ✅ 推荐做法

  1. 使用同步 API 进行状态检查

    // ✅ 推荐:同步检查,性能更好
    const enabled = notificationManager.isNotificationEnabledSync();
    
  2. 先检查再请求,避免无效调用

    // ✅ 推荐
    if (!notificationManager.isNotificationEnabledSync()) {
        await notificationManager.requestEnableNotification(context);
    }
    
  3. 提供二次授权入口,不放弃用户

    // ✅ 推荐:拒绝后引导去设置
    if (err.code === 1600004) {
        await notificationManager.openNotificationSettings(context);
    }
    
  4. 使用 V2 状态管理驱动 UI 更新

    // ✅ 推荐:@ObservedV2 + @Trace 实现细粒度更新
    @ObservedV2
    class AuthState {
        @Trace enabled: boolean = false;
    }
    
  5. 在页面重新可见时重新检查状态

    // ✅ 推荐:从设置页返回后重新检查
    onVisibilityChange(visible: boolean): void {
        if (visible) {
            this.checkNotificationStatus();
        }
    }
    

6.2 ❌ 常见错误

  1. 用户拒绝后反复调用 requestEnableNotification()

    // ❌ 错误:用户拒绝后该方法永不弹窗
    for (let i = 0; i < 3; i++) {
        await notificationManager.requestEnableNotification(context); // 无效
    }
    
  2. 使用异步 API 做快速判断

    // ❌ 不推荐:同步场景下多余的异步开销
    const enabled = await notificationManager.isNotificationEnabled();
    // ✅ 推荐
    const enabled = notificationManager.isNotificationEnabledSync();
    
  3. 忽略错误码 1600004

    // ❌ 错误:未区分用户拒绝和其他错误
    try {
        await notificationManager.requestEnableNotification(context);
    } catch (err) {
        // 所有错误统一处理,不区分用户拒绝
        console.error('授权失败');
    }
    
  4. 忘记在页面恢复时重新检查状态

    // ❌ 错误:从设置返回后未重新检查
    // 用户可能在设置中手动开启了通知,但应用不知道
    

7. 总结

核心要点回顾

要点 说明
三个核心 API isNotificationEnabledSync → 查状态 → requestEnableNotification → 一次授权 → openNotificationSettings → 二次授权
授权仅一次 requestEnableNotification 只在首次调用时弹窗,用户拒绝后不再弹窗
二次授权 用户拒绝后必须通过 openNotificationSettings 引导手动开启
1600004 关键错误码,代表用户明确拒绝
V2 状态管理 推荐使用 @ObservedV2 + @Trace 管理通知授权状态

学习路径建议

  1. 入门:理解三个核心 API 的作用和调用时机
  2. 进阶:封装工具类,实现智能授权流程
  3. 精通:结合 V2 状态管理和生命周期,打造无缝用户体验

📚 参考文档

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐