HarmonyOS 鸿蒙Next中唤醒后台app方法

HarmonyOS 鸿蒙Next中唤醒后台app方法 【问题描述】:app在后台挂起,当app已配对的蓝牙设备靠近手机在蓝牙连接后,有唤醒app的 办法吗?

【问题现象】:不涉及

【版本信息】:不涉及

【复现代码】:不涉及

【尝试解决方案】:不涉及

4 回复

开发者您好,可以在蓝牙连接后尝试通过发送“消息通知”,然后点击“消息通知”唤醒应用。

【背景知识】 当发布通知时,如果期望用户可以通过点击通知栏拉起目标应用组件或发布公共事件,可以通过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);
}
  1. 创建WantAgentInfo信息并填写需要拉起的应用bundleName和abilityName(应用只能设置自己应用的bundleName和abilityName),然后构造NotificationRequest对象并发布通知:
Button('点击发送通知消息').onClick(() => {
  let wantAgentObj: WantAgent;
  let wantAgentInfo: wantAgent.WantAgentInfo = {
    wants: [
      {
        deviceId: '',
        bundleName: 'com.example.s_20250401090433411329', // 自己项目的包名
        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}`)
      }
    });
  });
})
  1. 在EntryAbility.ets文件中添加方法实现目标UIAbility热启动目标UIAbility冷启动用来获取点击消息通知后的WantAgentInfo信息并实现跳转指定页面。
  • 热启动代码,在应用已启动的情况下实现点击消息通知后会从应用当前所在页面跳转到指定页面:
// 热启动
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}`)
    });
  }
}
  • 冷启动代码,实现点击消息通知会启动应用并直接跳转指定页面:
// 冷启动
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.');
  });
}
  1. 新增Index2页面的步骤:右键工程中的Pages文件夹,然后选择New,接着点击Page最后点击New Page,输入Index2即可创建Page页面文件Index2.ets。

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

    • 冷启动:发送消息后,在多任务页面终止应用,再点击消息实现跳转应用指定页面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.s_20250401090433411329', // 自己项目的包名
              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;

  // 热启动
  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');
  }

  // 冷启动
  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.');
    });
  }


  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');
  }
}

更多关于HarmonyOS 鸿蒙Next中唤醒后台app方法的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


鸿蒙应用不允许自启动,但你可以看看“代理提醒”,让用户手动点进去

在HarmonyOS Next中,唤醒后台应用可通过AbilityManager的startAbility()方法实现,需指定目标应用的bundleName和abilityName。系统根据应用状态自动处理:若应用未启动则创建新实例,已在后台则切换到前台。注意确保目标应用已配置相应权限,避免因权限限制导致唤醒失败。

在HarmonyOS Next中,可以通过蓝牙连接事件触发后台应用的唤醒。建议使用系统提供的后台任务管理机制,结合蓝牙状态监听来实现。当已配对设备连接时,系统可自动恢复应用的部分后台能力。具体可通过注册蓝牙连接状态监听器,在回调中启动应用或恢复服务。注意需在配置文件中声明必要的权限(如蓝牙和设备唤醒权限),并遵循后台任务管理策略,避免频繁唤醒影响系统性能。

回到顶部