ITPub博客

首页 > 架构设计 > 操作系统 > 【FAQ】HarmonyOS SDK 闭源开放能力 — Notification Kit

【FAQ】HarmonyOS SDK 闭源开放能力 — Notification Kit

原创 操作系统 作者:HarmonyOS SDK 时间:2025-11-18 16:09:12 0 删除 编辑

1.问题描述:

获取应用是否开启了允许通知权限后,如何引导跳转开启权限通知的设置页面?

解决方案:

  1. 通过isNotificationEnabled方法查询通知是否授权,参考isNotificationEnabled用法。

2.若申请通知权限被拒绝后,后续调用requestEnableNotification()方法不再弹窗,同时会返回错误,错误码是1600004。具体参考请求通知授权。

3.如果想二次授权,可以调用openNotificationSettings申请授权,拉起通知管理弹窗或者引导用户跳转应用设置页面开启权限。

完整代码示例如下:

import { notificationManager } from '@kit.NotificationKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { common } from '@kit.AbilityKit';
import { Want } from '@kit.AbilityKit';
@Entry
@Component
struct NotificationPage {
  aboutToAppear(): void {
    let context = this.getUIContext().getHostContext() as common.UIAbilityContext;
    notificationManager.isNotificationEnabled().then((data: boolean) => {
      console.info("isNotificationEnabled success, data: " + data);
      if (!data) {
        let requestEnableNotificationCallback = (err: BusinessError): void => {
          if (err) {
            console.error(`requestEnableNotification failed, code is ${err.code}, message is ${err.message}`);
          } else {
            console.info(`requestEnableNotification success`);
          }
        };
        notificationManager.requestEnableNotification(context, requestEnableNotificationCallback);
      }
    }).catch((err: BusinessError) => {
      console.error(`isNotificationEnabled fail, code is ${err.code}, message is ${err.message}`);
    });
  }
  // 发布基本类型通知
  publishBasicNotification() {
    let notificationRequest: notificationManager.NotificationRequest = {
      id: 1,
      notificationSlotType: notificationManager.SlotType.SOCIAL_COMMUNICATION,
      content: {
        notificationContentType: notificationManager.ContentType.NOTIFICATION_CONTENT_BASIC_TEXT, // 普通文本类型通知
        normal: {
          title: '基本型消息通知',
          text: '通知内容XXXXXXX',
          additionalText: 'TextXXXXXXX',
        }
      }
    };
    notificationManager.publish(notificationRequest, (err: BusinessError) => {
      if (err) {
        console.error(`Failed to publish notification. Code is ${err.code}, message is ${err.message}`);
        return;
      }
      console.info('Succeeded in publishing notification.');
    });
    notificationManager.setBadgeNumber(1)
  }
  build() {
    Column() {
      Button('基本通知')
        .onClick(() => {
          this.publishBasicNotification()
        })
      Button('二次授权')
        .margin({ top: 20 })
        .onClick(() => {
          let context = this.getUIContext().getHostContext() as common.UIAbilityContext;
          notificationManager.openNotificationSettings(context).then(() => {
            console.info(`openNotificationSettings success`);
          }).catch((err: BusinessError) => {
            console.error(`openNotificationSettings failed, code is ${err.code}, message is ${err.message}`);
          });
        })
      Button('点击进入应用设置页面')
        .margin({ top: 20 })
        .onClick(() => {
          let context = this.getUIContext().getHostContext() as common.UIAbilityContext;
          let want: Want = {
            bundleName: 'com.huawei.hmos.settings',
            abilityName: 'com.huawei.hmos.settings.MainAbility',
            uri: 'application_info_entry',
            parameters: {
              pushParams: "com.example.myapplication" // 配置应用包名
            }
          };
          context.startAbility(want).then(() => {
          }).catch((err: BusinessError) => {
            console.error(`Code is ${err.code}, message is ${err.message}`)
          });
        })
    }
    .alignItems(HorizontalAlign.Center)
    .width('100%')
    .height('100%')
  }
}

2.问题描述:

使用notificationManager.openNotificationSettings接口打开的弹窗,如何监听弹窗关闭事件?

解决方案:

在页面打开应用通知设置页。

openNotificationSettings接口拉起的设置页面,页面关闭的时候没有回调方法可以直接使用,但是该接口拉起的页面关闭的时候,会触发其他页面聚焦的回调,在这个页面的根组件上注册的 onfocus事件,在该回调内自定义一些操作,比如调用isNotificationEnabledSync()来查询应用通知的开启状态。具体实现代码如下:

import { notificationManager } from '@kit.NotificationKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { common } from '@kit.AbilityKit';
@Entry
@Component
struct NotificationManagerDemo {
  // 组件聚焦状态
  @State focusState: boolean = true
  build() {
    Column() {
      Button('打开弹窗')
        .onClick(() => {
          let context = this.getUIContext().getHostContext() as common.UIAbilityContext;
          // 拉起应用通知设置页面
          notificationManager.openNotificationSettings(context).then(() => {
            console.info('页面拉起成功')
            // 拉起成功,改变页面聚焦状态
            this.focusState = false
          }).catch((err: BusinessError) => {
            console.info('页面拉起失败')
          });
        })
    }
    .onFocus(() => {
      // 组件聚焦的回调
      if (!this.focusState) {
        // 做一些自己的操作
        console.info('应用通知页面关闭')
        // 查询通知开关是否开启
        let res = notificationManager.isNotificationEnabledSync()
        console.info(`是否开启应用通知:${res}`)
        this.getUIContext().getPromptAction().showToast({ message: `是否开启应用通知:${res}` })
        // 重置组件聚焦状态
        this.focusState = !this.focusState
      }
    })
  }
}

3.问题描述:

notificationManager.openNotificationSettings唤起半模态框,如何监听消失并读取最新通知开启状态?

解决方案:

封装通知管理工具类,全局使用。

  1. 创建通知管理工具类:
// NotificationUtil.ts
import { notificationManager } from '@kit.NotificationKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { common } from '@kit.AbilityKit';
 
/**
 * 通知管理工具类
 */
export class NotificationUtil {
  private static instance: NotificationUtil;
  private context: common.UIAbilityContext | null = null;
  private focusStateCallbacks: Array<(isFocused: boolean) => void> = [];
 
  private constructor() {
  }
 
  /**
   * 获取单例实例
   */
  public static getInstance(): NotificationUtil {
    if (!NotificationUtil.instance) {
      NotificationUtil.instance = new NotificationUtil();
    }
    return NotificationUtil.instance;
  }
 
  /**
   * 初始化工具类(必须在应用启动时调用)
   * @param context UIAbility上下文
   */
  public initialize(context: common.UIAbilityContext): void {
    this.context = context;
  }
 
  /**
   * 打开通知设置页面
   * @returns Promise<boolean> 是否成功打开
   */
  public async openNotificationSettings(): Promise<boolean> {
    if (!this.context) {
      console.error('NotificationUtil 未初始化,请先调用 initialize 方法');
      return false;
    }
 
    try {
      await notificationManager.openNotificationSettings(this.context);
      console.info('通知设置页面拉起成功');
      return true;
    } catch (err) {
      const error = err as BusinessError;
      console.error(`通知设置页面拉起失败: ${error.code} - ${error.message}`);
      return false;
    }
  }
 
  /**
   * 检查通知是否开启(同步)
   * @returns boolean 通知是否开启
   */
  public isNotificationEnabled(): boolean {
    try {
      return notificationManager.isNotificationEnabledSync();
    } catch (err) {
      const error = err as BusinessError;
      console.error(`检查通知状态失败: ${error.code} - ${error.message}`);
      return false;
    }
  }
 
  /**
   * 检查通知是否开启(异步)
   * @returns Promise<boolean> 通知是否开启
   */
  public async isNotificationEnabledAsync(): Promise<boolean> {
    try {
      return await notificationManager.isNotificationEnabled();
    } catch (err) {
      const error = err as BusinessError;
      console.error(`异步检查通知状态失败: ${error.code} - ${error.message}`);
      return false;
    }
  }
 
  /**
   * 注册页面聚焦状态回调
   * @param callback 回调函数
   */
  public registerFocusCallback(callback: (isFocused: boolean) =&gt; void): void {
    this.focusStateCallbacks.push(callback);
  }
 
  /**
   * 注销页面聚焦状态回调
   * @param callback 回调函数
   */
  public unregisterFocusCallback(callback: (isFocused: boolean) =&gt; void): void {
    const index = this.focusStateCallbacks.indexOf(callback);
    if (index &gt; -1) {
      this.focusStateCallbacks.splice(index, 1);
    }
  }
 
  /**
   * 处理页面聚焦事件(需要在页面onFocus中调用)
   * @param isFocused 是否聚焦
   */
  public handleFocusChange(isFocused: boolean): void {
    this.focusStateCallbacks.forEach(callback =&gt; {
      try {
        callback(isFocused);
      } catch (err) {
        console.error('焦点状态回调执行失败:', err);
      }
    });
  }
 
  /**
   * 完整的打开通知设置并监听返回的流程
   * @param onReturnCallback 返回时的回调函数
   * @returns Promise<boolean> 是否成功执行
   */
  public async openSettingsAndListenReturn(onReturnCallback?: (isEnabled: boolean) =&gt; void): Promise<boolean> {
    if (!this.context) {
      console.error('NotificationUtil 未初始化');
      return false;
    }
 
    const success = await this.openNotificationSettings();
    if (success &amp;&amp; onReturnCallback) {
      // 注册一次性回调
      const tempCallback = (isFocused: boolean) =&gt; {
        if (isFocused) {
          const isEnabled = this.isNotificationEnabled();
          onReturnCallback(isEnabled);
          // 执行后立即注销
          this.unregisterFocusCallback(tempCallback);
        }
      };
 
      this.registerFocusCallback(tempCallback);
    }
 
    return success;
  }
}
 
// 导出默认实例
export default NotificationUtil.getInstance();
  1. 在应用入口初始化工具类:
  onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
    try {
      this.context.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET);
 
      // 初始化通知工具类
      NotificationUtil.initialize(this.context);
 
    } catch (err) {
      hilog.error(DOMAIN, 'testTag', 'Failed to set colorMode. Cause: %{public}s', JSON.stringify(err));
    }
    hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onCreate');
  }
  1. 使用封装后的工具类:
import NotificationUtil from './NotificationUtil';
 
@Entry
@Component
struct NotificationManagerDemo {
  @State focusState: boolean = true
 
  build() {
    Column() {
 
      Button('打开应用通知设置页')
        .onClick(async () =&gt; {
          await NotificationUtil.openSettingsAndListenReturn((isEnabled: boolean) =&gt; {
            console.info('从设置页面返回,通知状态:', isEnabled);
            this.getUIContext().getPromptAction().showToast({
              message: `通知状态: ${isEnabled ? '已开启' : '已关闭'}`
            });
          });
        })
 
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
    .alignItems(HorizontalAlign.Center)
    .onFocus(() =&gt; {
      // 将焦点变化传递给工具类
      NotificationUtil.handleFocusChange(true);
    })
    .onBlur(() =&gt; {
      NotificationUtil.handleFocusChange(false);
    })
  }
}

4.问题描述:

如何直接以弹窗方式打开通知管理页面?

解决方案:

  1. 通过isNotificationEnabled方法查询通知是否授权,参考 isNotificationEnabled用法。

  2. 若申请通知权限被拒绝后,后续调用requestEnableNotification()方法不再弹窗,同时会返回错误,错误码是1600004。具体参考 请求通知授权。

如果想二次授权,可以调用 openNotificationSettings申请授权,拉起通知管理弹窗。或者引导用户跳转应用设置页面开启权限,跳转设置页面方法如下:

let context = getContext(this) as common.UIAbilityContext;
let want: Want = {
  bundleName: 'com.huawei.hmos.settings',
  abilityName: 'com.huawei.hmos.settings.MainAbility',
  uri: 'application_info_entry',
  parameters: {
    pushParams: "bundleName" // 配置应用包名
  }
};
context.startAbility(want).then(() =&gt; {
}).catch((err: BusinessError) =&gt; {
  console.error(`Code is ${err.code}, message is ${err.message}`)
});

5.问题描述:

notificationManager.requestEnableNotification err.code:1600013,原因是什么?

解决方案:

【背景知识】

应用需要获取用户授权才能发送通知。在通知发布前调用requestEnableNotification()方法,弹窗让用户选择是否允许发送通知,后续再次调用requestEnableNotification()方法时,则不再弹窗。可参考文档 请求通知权限。

【问题定位】


  1. 权限请求时机问题,需要在UI加载后再申请。

  2. 是否绑定UiAbilityContext,context是否正常初始化。

  3. 以前有异常弹出的场景,产生了脏数据。

  4. 检查相关参数HashMap使用是否正确。

【分析结论】


  1. 1600013,若窗口未加载完成就请求了通知,导致渲染异常,再次请求就会报这个错,尽量在窗口创建并渲染后再调用。

  2. 建议在entryAbility中调用,或是在对应的页面中调用,不建议在授权时切换页面。

【修改建议】

针对报错code:1600013,可以采用以下两种方案:


  1. 执行重启手机、删除应用的操作,清理脏数据后再次安装应用尝试。申请通知权限代码改为在ui加载后再申请。代码示例:
windowStage.loadContent('pages/Index', (err) =&gt; {
     if (err.code) {
       hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');
       return;
     }
 
     notificationManager.requestEnableNotification().then(() =&gt; {
       hilog.info(0x0000, '’testTag', 'requestEnableNotification success');
     })
       .catch((error: BusinessError) =&gt; {
         hilog.error(0x0000, 'testTag', 'requestEnableNotification error : %{public}s', JSON.stringify(error))
       })
     hilog.info(0x0000, 'testTag', 'Succeeded in loading the content.');
   });


  1. 绑定UiAbilityContext使用 模态弹窗方式,初始化context。代码示例:
let context = getContext(this) as common.UIAbilityContext;
notificationManager.isNotificationEnabled().then((data: boolean) =&gt; {
  hilog.info(DOMAIN_NUMBER, TAG, "isNotificationEnabled success, data: " + JSON.stringify(data));
  if(!data){
    notificationManager.requestEnableNotification(context).then(() =&gt; {
      hilog.info(DOMAIN_NUMBER, TAG, `[ANS] requestEnableNotification success`);
    }).catch((err : BusinessError) =&gt; {
      if(1600004 == err.code){
        hilog.error(DOMAIN_NUMBER, TAG, `[ANS] requestEnableNotification refused, code is ${err.code}, message is ${err.message}`);
      } else {
        hilog.error(DOMAIN_NUMBER, TAG, `[ANS] requestEnableNotification failed, code is ${err.code}, message is ${err.message}`);
      }
    });
  }
}).catch((err : BusinessError) =&gt; {
  hilog.error(DOMAIN_NUMBER, TAG, `isNotificationEnabled fail: ${JSON.stringify(err)}`);
});
  • 不在授权时切换页面,建议在window.loadContent回调中请求权限。

</boolean></boolean></boolean></boolean></boolean></boolean>


来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/70003787/viewspace-3102188/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
HarmonyOS SDK技术团队。分享最新的技术干货,带来最全的能力应用场景,更新热门开发者圈子活动。与开发者一起,同成长,共精彩。

注册时间:2021-07-15

  • 博文量
    627
  • 访问量
    729534