HarmonyOS鸿蒙Next中点击通知消息进入应用内页是依靠什么判断进入哪个页面的?

HarmonyOS鸿蒙Next中点击通知消息进入应用内页是依靠什么判断进入哪个页面的? 如题,在项目模块级别下的src/main/module.json5 中设置skills时,是哪个配置决定进入哪个页面的?

5 回复

可以参考点击消息进入应用内页中:

  1. 在skills标签中新增一个独立的skill对象,配置actions参数,取值可自定义,示例如下:
{
  "name": "TestAbility",
  // Ability入口页
  "srcEntry": "./ets/abilities/TestAbility.ets",
  "exported": false,
  "startWindowIcon": "$media:startIcon",
  "startWindowBackground": "$color:start_window_background",
  "skills": [
    // 保持现有skill对象不变
    {
      "actions": [
        "com.app.action"
      ]
    },
    // 新增一个独立的skill对象,配置actions参数
    {
      "actions": [
        "com.test.action"
      ]
    }
  ]
}
  1. 在发送消息时clickAction中设置actionType字段为1,表示点击消息后进入应用内页,并在Request Body请求体中配置与步骤1对应的action值,示例如下:
// Request Body
{
  "payload": {
    "notification": {
      "category": "MARKETING",
      "title": "普通通知标题",
      "body": "普通通知内容",
      "clickAction": {
        "actionType": 1,
        "action": "com.test.action",
        "data": {"testKey": "testValue"}
      }
    }
  },
  "target": {
    "token": ["MAMzLg**********lPW"]
  },
  "pushOptions": {
    "testMessage": true
  }
}

说明:Request Body的action与skills的新增actions值要保持一致,以保证点击推送消息后启动对应Ability入口页,入口页配置为步骤1中的srcEntry。

  1. 在入口页设置跳转的具体页面,示例如下:
// TestAbility.ets
export default class TestAbility extends UIAbility {
  private localStorage = new LocalStorage();

  onCreate(want: Want): void {
    Logger.info('TestAbility onCreate');
    this.localStorage.setOrCreate('want', want);
  }

  onNewWant(want: Want): void {
    Logger.info('TestAbility onNewWant');
    this.localStorage.setOrCreate('want', want);
  }

  onDestroy(): void {
    Logger.info('TestAbility onDestroy');
  }

  onWindowStageCreate(windowStage: window.WindowStage): void {
    // 加载指定页面
    windowStage.loadContent('pages/TargetPage', this.localStorage);
  }
}

更多关于HarmonyOS鸿蒙Next中点击通知消息进入应用内页是依靠什么判断进入哪个页面的?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


【背景知识】 当发布通知时,如果期望用户可以通过点击通知栏拉起目标应用组件或发布公共事件,可以通过Ability Kit申请WantAgent封装至通知消息中。

【解决方案】

  1. 代码中申请通知权限:

    enableNotifications() {
      let requestEnableNotificationCallback = (err: BusinessError): void => {
        if (err) {
          hilog.error(0x0000, 'testTag',
            `[ANS] requestEnableNotification failed, code is ${err.code}, message is ${err.message}`);
        } else {
          hilog.info(0x0000, 'testTag', `[ANS] requestEnableNotification success`);
        }
      };
      notificationManager.requestEnableNotification(this.context, requestEnableNotificationCallback);
    }
    
  2. 创建WantAgentInfo信息并填写需要拉起的应用bundleName和abilityName(应用只能设置自己应用的bundleName和abilityName),然后构造NotificationRequest对象并发布通知:

    Button('点击发送通知消息').onClick(() => {
      let wantAgentObj: WantAgent;
      let wantAgentInfo: wantAgent.WantAgentInfo = {
        wants: [
          {
            deviceId: '',
            bundleName: 'com.example.ir_wantagent',
            abilityName: 'EntryAbility',
            action: '',
            entities: [],
            uri: '',
            parameters: {
              targetPage: 'Index2' // 添加目标页面参数
            }
          }
        ],
        actionType: wantAgent.OperationType.START_ABILITY,
        requestCode: 0,
        wantAgentFlags: [wantAgent.WantAgentFlags.CONSTANT_FLAG]
      };
      wantAgent.getWantAgent(wantAgentInfo, (err: BusinessError, data: WantAgent) => {
        if (err) {
          hilog.error(DOMAIN_NUMBER, TAG, `Failed to get want agent. Code is ${err.code}, message is ${err.message}`);
          return;
        }
        hilog.info(DOMAIN_NUMBER, TAG, 'Succeeded in getting want agent.');
        wantAgentObj = data;
        // 构造NotificationRequest对象
        let notificationRequest: notificationManager.NotificationRequest = {
          content: {
            notificationContentType: notificationManager.ContentType.NOTIFICATION_CONTENT_BASIC_TEXT,
            normal: {
              title: 'Test_Title',
              text: 'Test_Text',
              additionalText: 'Test_AdditionalText',
            },
          },
          id: 6,
          label: 'TEST',
          // wantAgentObj使用前需要保证已被赋值(即步骤3执行完成)
          wantAgent: wantAgentObj,
        }
        notificationManager.publish(notificationRequest, (err: BusinessError) => {
          if (err) {
            hilog.error(DOMAIN_NUMBER, TAG,
              `Failed to publish notification. Code is ${err.code}, message is ${err.message}`);
            return;
          }
          hilog.info(DOMAIN_NUMBER, TAG, 'Succeeded in publishing notification.');
          try{
            this.getUIContext().getPromptAction().showToast({ message: '消息已发送' })
          } catch (error) {
            console.error(`error:${error.message}`)
          }
        });
      });
    })
    
  3. 在EntryAbility.ets文件中添加方法实现目标UIAbility热启动目标UIAbility冷启动用来获取点击消息通知后的WantAgentInfo信息并实现跳转指定页面。

    1. 热启动代码,在应用已启动的情况下实现点击消息通知后会从应用当前所在页面跳转到指定页面:
      // 热启动
      onNewWant(want: Want, launchParam: AbilityConstant.LaunchParam): void {
        // 通过want.parameters获取参数
        const targetPage = want.parameters?.targetPage;
        console.info(`onNewWant Received parameter: ${targetPage}`)
        // 根据参数执行逻辑(例如跳转页面)
        if (targetPage === 'Index2') {
          // 跳转到Index2页面
          this.uiContext?.getRouter().pushUrl({
            url: 'pages/Index2'
          }).catch((error: BusinessError) => {
            console.error(`error:${error.message}`)
          });
        }
      }
      
    2. 冷启动代码,实现点击消息通知会启动应用并直接跳转指定页面:
      // 冷启动
      onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
        try {
          this.context.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET);
        } catch (error) {
          console.error(`error:${error.message}`)
        }
        hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate');
        this.funcAbilityWant = want;
      }
      onWindowStageCreate(windowStage: window.WindowStage): void {
        let url = 'pages/Index';
        if (this.funcAbilityWant?.parameters?.targetPage === 'Index2') {
          url = 'pages/Index2';
        }
        console.info(`url:${url}`)
        windowStage.loadContent(url, (err) => {
          if (err.code) {
            hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');
            return;
          }
          try {
            this.uiContext = windowStage.getMainWindowSync().getUIContext();
          } catch (error) {
            console.error(`error:${error.message}`)
          }
          hilog.info(0x0000, 'testTag', 'Succeeded in loading the content.');
        });
      }
      
  4. 新增Index2页面的步骤:右键工程中的Pages文件夹,然后选择New,接着点击Page最后点击New Page,输入Index2即可创建Page页面文件Index2.ets。

  5. 模拟点击消息跳转页面步骤:

    • 冷启动:发送消息后,在多任务页面终止应用,再点击消息实现跳转应用指定页面Index2。
    • 热启动:发送消息后,将应用返回后台,再点击消息实现跳转应用指定页面Index2。

完整代码如下:

  • Index.ets代码:

    import { common, wantAgent, WantAgent } from '@kit.AbilityKit';
    import { BusinessError } from '@kit.BasicServicesKit';
    import { hilog } from '@kit.PerformanceAnalysisKit';
    import { notificationManager } from '@kit.NotificationKit';
    
    const TAG: string = '[PublishOperation]';
    const DOMAIN_NUMBER: number = 0xFF00;
    
    @Entry
    @Component
    struct Index {
      @State message: string = 'Hello World';
      private context = this.getUIContext().getHostContext() as common.UIAbilityContext;
    
      enableNotifications() {
        let requestEnableNotificationCallback = (err: BusinessError): void => {
          if (err) {
            hilog.error(0x0000, 'testTag',
              `[ANS] requestEnableNotification failed, code is ${err.code}, message is ${err.message}`);
          } else {
            hilog.info(0x0000, 'testTag', `[ANS] requestEnableNotification success`);
          }
        };
        notificationManager.requestEnableNotification(this.context, requestEnableNotificationCallback);
      }
    
      aboutToAppear(): void {
        this.enableNotifications()
      }
    
      build() {
        Column({ space: 10 }) {
          Text('页面一')
            .fontSize(40)
            .fontWeight(FontWeight.Bold)
    
          Button('点击发送通知消息').onClick(() => {
            let wantAgentObj: WantAgent;
            let wantAgentInfo: wantAgent.WantAgentInfo = {
              wants: [
                {
                  deviceId: '',
                  bundleName: 'com.example.ir_wantagent', // 自己项目的包名
                  abilityName: 'EntryAbility',
                  action: '',
                  entities: [],
                  uri: '',
                  parameters: {
                    targetPage: 'Index2' // 添加目标页面参数
                  }
                }
              ],
              actionType: wantAgent.OperationType.START_ABILITY,
              requestCode: 0,
              wantAgentFlags: [wantAgent.WantAgentFlags.CONSTANT_FLAG]
            };
            wantAgent.getWantAgent(wantAgentInfo, (err: BusinessError, data: WantAgent) => {
              if (err) {
                hilog.error(DOMAIN_NUMBER, TAG, `Failed to get want agent. Code is ${err.code}, message is ${err.message}`);
                return;
              }
              hilog.info(DOMAIN_NUMBER, TAG, 'Succeeded in getting want agent.');
              wantAgentObj = data;
              // 构造NotificationRequest对象
              let notificationRequest: notificationManager.NotificationRequest = {
                content: {
                  notificationContentType: notificationManager.ContentType.NOTIFICATION_CONTENT_BASIC_TEXT,
                  normal: {
                    title: 'Test_Title',
                    text: 'Test_Text',
                    additionalText: 'Test_AdditionalText',
                  },
                },
                id: 6,
                label: 'TEST',
                wantAgent: wantAgentObj,
              }
              notificationManager.publish(notificationRequest, (err: BusinessError) => {
                if (err) {
                  hilog.error(DOMAIN_NUMBER, TAG,
                    `Failed to publish notification. Code is ${err.code}, message is ${err.message}`);
                  return;
                }
                hilog.info(DOMAIN_NUMBER, TAG, 'Succeeded in publishing notification.');
                try {
                  this.getUIContext().getPromptAction().showToast({ message: '消息已发送' })
                } catch (error) {
                  console.error(`error:${error.message}`)
                }
              });
            });
          })
        }
        .width('100%')
        .height('100%')
        .justifyContent(FlexAlign.Center)
      }
    
      // 页面间转场动画,在热启动场景下点击通知消息跳转到目标页面时,使用该动画可优化跳转体验
      pageTransition() {
        PageTransitionExit({ type: RouteType.Push, duration: 200 })
          .slide(SlideEffect.Left)
      }
    }
    
  • EntryAbility.ets代码:

    import { AbilityConstant, ConfigurationConstant, UIAbility, Want } from '@kit.AbilityKit';
    import { hilog } from '@kit.PerformanceAnalysisKit';
    import { BusinessError } from '@kit.BasicServicesKit';
    import { window } from '@kit.ArkUI';
    
    export default class EntryAbility extends UIAbility {
      funcAbilityWant: Want | undefined = undefined;
      uiContext: UIContext | undefined = undefined;
    
      // 冷启动
      onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
        this.context.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET);
        } catch (error) {
          console.error(`error:${error.message}`)
        }
        hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate');
        this.funcAbilityWant = want;
      }
    
      // 热启动
      onNewWant(want: Want, launchParam: AbilityConstant.LaunchParam): void {
        // 通过want.parameters获取参数
        const targetPage = want.parameters?.targetPage;
        console.info(`onNewWant Received parameter: ${targetPage}`)
        // 根据参数执行逻辑(例如跳转页面)
        if (targetPage === 'Index2') {
          // 跳转到Index2页面
          this.uiContext?.getRouter().pushUrl({
            url: 'pages/Index2'
          }).catch((error: BusinessError) => {
            console.error(`error:${error.message}`)
          });
        }
      }
    
      onDestroy(): void {
        hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy');
      }
    
      onWindowStageCreate(windowStage: window.WindowStage): void {
        let url = 'pages/Index';
        if (this.funcAbilityWant?.parameters?.targetPage === 'Index2') {
          url = 'pages/Index2';
        }
        console.info(`url:${url}`)
        windowStage.loadContent(url, (err) => {
          if (err.code) {
            hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');
            return;
          }
          try {
            this.uiContext = windowStage.getMainWindowSync().getUIContext();
          } catch (error) {
            console.error(`error:${error.message}`)
          }
          hilog.info(0x0000, 'testTag', 'Succeeded in loading the content.');
        });
      }
    
      onWindowStageDestroy(): void {
        // Main window is destroyed, release UI related resources
        hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageDestroy');
      }
    
      onForeground(): void {
        // Ability has brought to foreground
        hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground');
      }
    
      onBackground(): void {
        // Ability has back to background
        hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onBackground');
      }
    }
    

感觉不太行,实际是从通知进入的,不会有封装 want 的步骤,但您给的代码是从应用进入其他页面的,

在HarmonyOS Next中,点击通知消息进入应用内页面的判断机制基于通知消息中预设的意图(Intent)参数。系统解析通知携带的Intent数据,匹配应用内已注册的页面路由路径,直接导航至对应页面。此过程由系统级事件分发机制和应用的页面路由配置协同完成,无需依赖Java或C语言逻辑。

在HarmonyOS Next中,点击通知消息进入应用内页的页面跳转逻辑由module.json5中的skills配置项决定。具体是通过以下关键配置判断目标页面:

  1. entities字段:定义通知消息关联的实体类型(如"entity.system.home"表示主页)
  2. actions字段:指定要执行的操作(如"action.system.start"表示启动动作)
  3. uris字段(可选):通过URI参数携带目标页面路径或参数

示例配置:

"skills": [{
  "entities": ["entity.system.detail"],
  "actions": ["action.system.start"],
  "uris": [{
    "scheme": "app",
    "host": "com.example.app",
    "path": "/detail"
  }]
}]

当通知触发时,系统会根据skills中定义的URI路径(如app://com.example.app/detail)匹配对应的Page Ability,最终跳转到指定页面。URI中的path参数需要与目标页面的路径声明保持一致。

回到顶部