写点什么

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

作者:HarmonyOS SDK
  • 2025-11-18
    贵州
  • 本文字数:7413 字

    阅读完需:约 24 分钟

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>

用户头像

HarmonyOS SDK

关注

HarmonyOS SDK 2022-06-16 加入

HarmonyOS SDK通过将HarmonyOS系统级能力对外开放,支撑开发者高效打造更纯净、更智能、更精致、更易用的鸿蒙应用,和开发者共同成长。

评论

发布
暂无评论
【FAQ】HarmonyOS SDK 闭源开放能力 — Notification Kit_HarmonyOS NEXT_HarmonyOS SDK_InfoQ写作社区