欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 科技 > 名人名企 > 鸿蒙实现后台任务管理

鸿蒙实现后台任务管理

2025/5/25 9:21:05 来源:https://blog.csdn.net/zouyang920/article/details/144339150  浏览:    关键词:鸿蒙实现后台任务管理

目录:

    • 1、后台任务类型
    • 2、应用后台运行
    • 3、后台任务类型实现
      • 3.1、短时任务
      • 3.2、长时任务
      • 3.3、延时任务
      • 3.4、能效资源

1、后台任务类型

OpenHarmony将后台任务分为四种类型,并提供了一个资源申请的扩展功能:

  • 无后台业务 :应用或业务模块退到后台后,无任务需要处理。
  • 短时任务:应用或业务模块退到后台后,如果有紧急不可推迟且短时间能完成的任务,如应用退后台要进行数据压缩,不可中断,则使用短时任务申请延迟进入挂起(Suspend)状态。
  • 长时任务:如果是用户发起的可感知业务需要长时间后台运行,如后台播放音乐、导航、设备连接、VoIP等,则使用长时任务避免进入挂起(Suspend)状态。
  • 延迟任务:延迟任务调度给应用提供一个机制,允许应用根据系统安排,在系统空闲时执行实时性不高的任务。当满足设定条件的时候,任务会被放入待调度队列,当系统空闲时调度该任务。
  • 能效资源 :能效资源包括CPU资源、WORK_SCHEDULER资源、软件资源(COMMON_EVENT,TIMER)、硬件资源(GPS,BLUETOOTH)。如果应用或者进程申请了能效资源,那么根据能效资源的类型会拥有相应的特权,例如申请了CPU资源的可以不被挂起,申请了WORK_SCHEDULER后延时任务可以拥有更长的执行时间。
    在这里插入图片描述

2、应用后台运行

minimize方法提供该能力。若主窗口调用,可以将窗口最小化,并支持在Dock栏中还原。若子窗口调用,可以将窗口隐藏。

参考代码如下:

在EntryAbility.ets的onWindowStageCreate回调中全局保存windowStage:

AppStorage.setOrCreate('context', windowStage);

在页面中获取windowStage并调用方法实现最小化:

import { window } from '@kit.ArkUI'; @Component 
export struct BackgroundExecution { @State message: string = '后台运行'; build() { Column() { Button(this.message) .width('40%') .onClick(() => { let windowStage = AppStorage.get('context') as window.WindowStage; windowStage.getMainWindowSync().minimize(); //当应用进入后台时就可以对接我们后面的流程了,后台任务管理,如短时任务逻辑等        //这里实现后台任务逻辑}) } .height('100%') .width('100%') .justifyContent(FlexAlign.Center) } 
}

3、后台任务类型实现

3.1、短时任务

短时任务适用于小文件下载、缓存、信息发送等实时性高、需要临时占用资源执行的任务。

下面代码模拟在申请短时任务后执行了一个耗时计算任务:

import backgroundTaskManager from '@ohos.resourceschedule.backgroundTaskManager';
import { BusinessError } from '@ohos.base';
import util from '@ohos.util';
import hiTraceMeter from '@ohos.hiTraceMeter';const totalTimes: number = 50000000; // 循环次数
const calculateResult: string = 'Total time costed = %s ms.'; // 文本格式@Entry
@Component
struct Index {@State message: string = 'Click button to calculate.';private requestId: number = 0;// 申请短时任务requestSuspendDelay() {try {let delayInfo = backgroundTaskManager.requestSuspendDelay('compute', () => {console.info('Request suspension delay will time out.');// 任务即将超时,取消短时任务this.cancelSuspendDelay();})this.requestId = delayInfo.requestId;} catch (error) {console.error(`requestSuspendDelay failed. code is ${(error as BusinessError).code} message is ${(error as BusinessError).message}`);}}// 取消短时任务cancelSuspendDelay() {backgroundTaskManager.cancelSuspendDelay(this.requestId);console.info('Request suspension delay cancel.');}// 计算任务computeTask(times: number): number {let start: number = new Date().getTime();let a: number = 1;let b: number = 1;let c: number = 1;for (let i: number = 0; i < times; i++) {a = a * Math.random() + b * Math.random() + c * Math.random();b = a * Math.random() + b * Math.random() + c * Math.random();c = a * Math.random() + b * Math.random() + c * Math.random();}let end: number = new Date().getTime();return end - start;}// 点击回调clickCallback = () => {this.requestSuspendDelay();hiTraceMeter.startTrace('computeTask', 0); // 开启性能打点let timeCost = this.computeTask(totalTimes);this.message = util.format(calculateResult, timeCost.toString());hiTraceMeter.finishTrace('computeTask', 0); // 结束性能打点this.cancelSuspendDelay();}build() {Column() {Row(){Text(this.message)}Row() {Button('开始计算').onClick(this.clickCallback)}.width('100%').justifyContent(FlexAlign.Center)}.width('100%').height('100%').justifyContent(FlexAlign.Center)}
}

3.2、长时任务

下面模拟一个后台定位的场景。应用订阅设备位置变化,每隔一秒获取位置信息,为了保证应用在退到后台后仍然可以使用定位服务,申请了定位类型的长时任务

首先需要在 module.json5 配置文件中为需要使用长时任务的 EntryAbility 声明任务类型。

{"module": {..."abilities": [{"name": "EntryAbility",..."backgroundModes": ["location"]}],}
}

需要使用到的相关权限如下:

  • ohos.permission.INTERNET
  • ohos.permission.LOCATION_IN_BACKGROUND
  • ohos.permission.APPROXIMATELY_LOCATION
  • ohos.permission.LOCATION
  • ohos.permission.KEEP_BACKGROUND_RUNNING

后台定位的实现代码如下:

import wantAgent, { WantAgent } from '@ohos.app.ability.wantAgent';
import common from '@ohos.app.ability.common';
import backgroundTaskManager from '@ohos.resourceschedule.backgroundTaskManager';
import { BusinessError } from '@ohos.base';
import geolocation from '@ohos.geoLocationManager';
import abilityAccessCtrl from '@ohos.abilityAccessCtrl';
import notificationManager from '@ohos.notificationManager';const TAG: string = 'BackgroundLocation';@Entry
@Component
export struct LongTermTaskView {@State latitude: number = 0;@State longitude: number = 0;aboutToAppear() {// 请求发送通知的许可notificationManager.requestEnableNotification().then(() => {console.info(`[EntryAbility] requestEnableNotification success`);// 申请定位相关权限let atManager = abilityAccessCtrl.createAtManager();try {atManager.requestPermissionsFromUser(getContext(this), ['ohos.permission.INTERNET','ohos.permission.LOCATION','ohos.permission.LOCATION_IN_BACKGROUND','ohos.permission.APPROXIMATELY_LOCATION']).then((data) => {console.info(`[EntryAbility], data: ${JSON.stringify(data)}`);}).catch((err: BusinessError) => {console.info(`[EntryAbility], err: ${JSON.stringify(err)}`);})} catch (err) {console.info(`[EntryAbility], catch err->${JSON.stringify(err)}`);}}).catch((err: BusinessError) => {console.error(`[EntryAbility] requestEnableNotification failed, code is ${err.code}, message is ${err.message}`);});}// 位置变化回调locationChange = async (location: geolocation.Location) => {console.info(TAG, `locationChange location =${JSON.stringify(location)}`);this.latitude = location.latitude;this.longitude = location.longitude;}// 获取定位async getLocation() {console.info(TAG, `enter getLocation`);let requestInfo: geolocation.LocationRequest = {priority: geolocation.LocationRequestPriority.FIRST_FIX, // 快速获取位置优先scenario: geolocation.LocationRequestScenario.UNSET, // 未设置场景信息timeInterval: 1, // 上报位置信息的时间间隔distanceInterval: 0, // 上报位置信息的距离间隔maxAccuracy: 100 // 精度信息};console.info(TAG, `on locationChange before`);geolocation.on('locationChange', requestInfo, this.locationChange);console.info(TAG, `on locationChange end`);}// 开始长时任务startContinuousTask() {let context: Context = getContext(this);// 通知参数,指定点击长时任务通知后跳转的应用let wantAgentInfo: wantAgent.WantAgentInfo = {wants: [{bundleName: (context as common.UIAbilityContext).abilityInfo.bundleName,abilityName: (context as common.UIAbilityContext).abilityInfo.name}],operationType: wantAgent.OperationType.START_ABILITY,requestCode: 0,wantAgentFlags: [wantAgent.WantAgentFlags.UPDATE_PRESENT_FLAG]};wantAgent.getWantAgent(wantAgentInfo).then((wantAgentObj: WantAgent) => {backgroundTaskManager.startBackgroundRunning(context,backgroundTaskManager.BackgroundMode.LOCATION, wantAgentObj).then(() => {console.info(`Succeeded in operationing startBackgroundRunning.`);}).catch((err: BusinessError) => {console.error(`Failed to operation startBackgroundRunning. Code is ${err.code}, message is ${err.message}`);});});}// 停止长时任务stopContinuousTask() {backgroundTaskManager.stopBackgroundRunning(getContext()).then(() => {console.info(`Succeeded in operationing stopBackgroundRunning.`);}).catch((err: BusinessError) => {console.error(`Failed to operation stopBackgroundRunning. Code is ${err.code}, message is ${err.message}`);});}build() {Column() {Column() {Text(this.latitude.toString())Text(this.longitude.toString())}.width('100%')Column() {Button('开启定位服务').onClick(() => {this.startContinuousTask();this.getLocation();})Button('关闭定位服务').onClick(async () => {await geolocation.off('locationChange');this.stopContinuousTask();}).margin({ top: 10 })}.width('100%')}.width('100%').height('100%').justifyContent(FlexAlign.Center)}
}

3.3、延时任务

实现延迟任务回调拓展能力:

import WorkSchedulerExtensionAbility from '@ohos.WorkSchedulerExtensionAbility';
import workScheduler from '@ohos.resourceschedule.workScheduler';
export default class MyWorkSchedulerExtensionAbility extends WorkSchedulerExtensionAbility {// 延迟任务开始回调onWorkStart(workInfo: workScheduler.WorkInfo) {console.info(`onWorkStart, workInfo = ${JSON.stringify(workInfo)}`);}// 延迟任务结束回调onWorkStop(workInfo: workScheduler.WorkInfo) {console.info(`onWorkStop, workInfo is ${JSON.stringify(workInfo)}`);}
}
{"module": {"extensionAbilities": [{"name": "MyWorkSchedulerExtensionAbility","srcEntry": "./ets/WorkSchedulerExtension/WorkSchedulerExtension.ets","label": "$string:WorkSchedulerExtensionAbility_label","description": "$string:WorkSchedulerExtensionAbility_desc","type": "workScheduler"}]}
}

实现延迟任务调度:

import workScheduler from '@ohos.resourceschedule.workScheduler';
import { BusinessError } from '@ohos.base';
// 创建workinfo
const workInfo: workScheduler.WorkInfo = {workId: 1,networkType: workScheduler.NetworkType.NETWORK_TYPE_WIFI,bundleName: 'com.example.application',abilityName: 'MyWorkSchedulerExtensionAbility'
}try {workScheduler.startWork(workInfo);console.info(`startWork success`);
} catch (error) {console.error(`startWork failed. code is ${(error as BusinessError).code} message is ${(error as BusinessError).message}`);
}
// 创建workinfo
const workInfo: workScheduler.WorkInfo = {workId: 1,networkType: workScheduler.NetworkType.NETWORK_TYPE_WIFI,bundleName: 'com.example.application', abilityName: 'MyWorkSchedulerExtensionAbility' 
}try {workScheduler.stopWork(workInfo);console.info(`stopWork success`);
} catch (error) {console.error(`stopWork failed. code is ${(error as BusinessError).code} message is ${(error as BusinessError).message}`);
}

3.4、能效资源

import backgroundTaskManager from '@ohos.resourceschedule.backgroundTaskManager';// 申请能效资源
let request = {resourceTypes: backgroundTaskManager.ResourceType.COMMON_EVENT|backgroundTaskManager.ResourceType.TIMER,isApply: true,timeOut: 0,reason: "apply",isPersist: true,isProcess: true,
};let res;
try {res = backgroundTaskManager.applyEfficiencyResources(request);console.info("the result of request is: " + res);
} catch (error) {console.error(`Operation applyEfficiencyResources failed. code is ${error.code} message is ${error.message}`);
}// 释放部分资源
request = {resourceTypes: backgroundTaskManager.ResourceType.COMMON_EVENT,isApply: false,timeOut: 0,reason: "reset",isPersist: true,isProcess: true,
};
try {res = backgroundTaskManager.applyEfficiencyResources(request);console.info("the result of request is: " + res);
} catch (error) {console.error(`Operation applyEfficiencyResources failed. code is ${error.code} message is ${error.message}`);
}// 释放全部资源
try {backgroundTaskManager.resetAllEfficiencyResources();
} catch (error) {console.error(`Operation resetAllEfficiencyResources failed. code is ${error.code} message is ${error.message}`);
}
  // 使用示例也是一样clickCallback = () => {backgroundTaskManager.applyEfficiencyResources(request);//申请能效资源hiTraceMeter.startTrace('computeTask', 0); // 开启性能打点let timeCost = this.computeTask(totalTimes);//进行任务逻辑处理this.message = util.format(calculateResult, timeCost.toString());hiTraceMeter.finishTrace('computeTask', 0); // 结束性能打点//任务逻辑处理完释放资源,下面是释放部分资源和释放全部资源,这里根据业务二选一即可backgroundTaskManager.applyEfficiencyResources(request);backgroundTaskManager.resetAllEfficiencyResources();}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词