写点什么

鸿蒙 NEXT 开发之后台任务开发服务框架学习笔记

作者:威哥爱编程
  • 2024-12-19
    北京
  • 本文字数:8996 字

    阅读完需:约 30 分钟

大家好,我是 V 哥,在学习鸿蒙时,想做一个音乐播放器,其中播放音乐的功能,一定要使用到后台任务开发服务,鸿蒙 NEXT 就提供了这样的能力,Background Tasks Kit(后台任务开发服务)是一个强大的框架,它允许开发者高效地管理和调度后台任务,实现应用功能的持续运行。今天的内容,我们来讨论学习后台任务开发服务框架的能力。

Background Tasks Kit 简介

Background Tasks Kit 是鸿蒙 NEXT 提供的后台任务开发框架,好像是一句废话,哈哈,来看主要作用包括:


  1. 降低设备能耗:通过规范后台任务的使用,避免应用在后台过度消耗设备资源,延长设备续航时间。

  2. 优化用户体验:确保后台任务的正常运行,避免应用在后台被系统杀掉,保证用户体验的连贯性。

  3. 提供多种后台任务类型:支持短时任务、长时任务、延迟任务、代理提醒等多种后台任务类型,满足不同场景的开发需求。

后台任务类型及特点

我们来看一下,Background Tasks Kit 提供的四种后台任务类型,每种类型都有其独特的特点和适用场景:


  1. 短时任务(Transient Task)

  2. 特点:实时性要求高,耗时不长。

  3. 适用场景:保存状态、发送消息、网络请求等。

  4. 长时任务(Continuous Task)

  5. 特点:长时间后台运行。

  6. 适用场景:音乐播放、导航、设备连接、位置跟踪等。

  7. 延迟任务(Deferred Task)

  8. 特点:允许条件触发。

  9. 适用场景:有网络时不定期主动获取邮件、定期同步数据等。

  10. 代理提醒(Agent-powered Reminder)

  11. 特点:系统在后台代理应用执行的提醒任务。

  12. 适用场景:倒计时、闹钟、日历、会议提醒等。

应用场景

后台任务开发服务,应用场景是非常多的,比如以下 4 种应用,就会用到:


  1. 音乐播放应用

  2. 在音乐播放应用中,即使用户将应用切换到后台,也可以通过申请长时任务(Continuous Task)来保证音乐播放的连续性,提升用户体验。

  3. 导航应用

  4. 导航应用在后台运行时,可以通过长时任务(Continuous Task)持续提供导航服务,即使在屏幕关闭或应用不在前台时也能继续导航。

  5. 文件下载

  6. 对于需要在后台下载大文件的场景,可以利用长时任务(Continuous Task)来保证下载任务的持续进行,如浏览器后台下载文件。

  7. 邮件同步

  8. 邮件应用可以利用延迟任务(Deferred Task)在有网络连接时定期同步邮件,确保用户及时收到新邮件。


接下来,V 哥将分别对短时任务,长时任务,延迟任务和代理提醒四种类型,通过案例来讲解如何使用哈。

实现短时任务(Transient Task)的案例

我们来看一个使用 ArkTS 实现短时任务(Transient Task)的完整案例代码:

案例代码

import backgroundTaskManager from '@ohos.resourceschedule.backgroundTaskManager';
@Entry@Componentstruct 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(); let timeCost = this.computeTask(50000000); // 循环次数为50000000 this.message = `Total time costed = ${timeCost} ms.`; 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) }}
复制代码

代码解释

  1. 导入背景任务管理器


   import backgroundTaskManager from '@ohos.resourceschedule.backgroundTaskManager';
复制代码


导入鸿蒙系统的背景任务管理器模块,用于申请和管理短时任务。


  1. 定义组件和状态


   @Entry   @Component   struct Index {     @State message: string = 'Click button to calculate.';     private requestId: number = 0;   }
复制代码


定义一个组件 Index,并初始化两个状态:message 用于显示信息,requestId 用于存储请求短时任务的 ID。


  1. 申请短时任务


   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}`);     }   }
复制代码


定义 requestSuspendDelay 方法,用于申请短时任务。如果申请成功,将请求 ID 存储在 requestId 中,并设置一个回调函数,当短时任务即将超时时,取消短时任务。


  1. 取消短时任务


   cancelSuspendDelay() {     backgroundTaskManager.cancelSuspendDelay(this.requestId);     console.info('Request suspension delay cancel.');   }
复制代码


定义 cancelSuspendDelay 方法,用于取消已申请的短时任务。


  1. 计算任务


   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;   }
复制代码


定义 computeTask 方法,执行一个耗时的计算任务,并返回执行时间。


  1. 点击回调


   clickCallback = () => {     this.requestSuspendDelay();     let timeCost = this.computeTask(50000000);     this.message = `Total time costed = ${timeCost} ms.`;     this.cancelSuspendDelay();   }
复制代码


定义 clickCallback 方法,当用户点击按钮时,申请短时任务,执行计算任务,并在完成后取消短时任务。


  1. 构建界面


   build() {     Column() {       Row(){         Text(this.message)       }       Row() {         Button('开始计算')           .onClick(this.clickCallback)       }       .width('100%')       .justifyContent(FlexAlign.Center)     }     .width('100%')     .height('100%')     .justifyContent(FlexAlign.Center)   }
复制代码


定义 build 方法,构建应用的界面,包括显示信息的文本和开始计算的按钮。


这个案例展示了如何在鸿蒙 NEXT 开发中使用 Background Tasks Kit 来实现短时任务,确保在后台执行耗时不长的任务,如状态保存、发送消息、网络请求等。

长时任务(Continuous Task)的案例

我们来看一个使用 ArkTS 实现长时任务(Continuous Task)的案例:

案例代码

// 导入必要的模块import { backgroundTaskManager } from '@ohos.resourceschedule.backgroundTaskManager';import { wantAgent } from '@ohos.app.ability.wantAgent';
@Entry@Componentstruct Index { @State message: string = 'ContinuousTask'; private context: Context = getContext(this);
// 申请长时任务 startContinuousTask() { let wantAgentInfo: wantAgent.WantAgentInfo = { wants: [ { bundleName: "com.example.myapplication", abilityName: "MainAbility" } ], actionType: wantAgent.OperationType.START_ABILITY, requestCode: 0, actionFlags: [wantAgent.WantAgentFlags.UPDATE_PRESENT_FLAG] }; wantAgent.getWantAgent(wantAgentInfo).then((wantAgentObj: wantAgent.WantAgent) => { backgroundTaskManager.startBackgroundRunning(this.context, backgroundTaskManager.BackgroundMode.AUDIO_RECORDING, wantAgentObj).then(() => { console.info("Operation startBackgroundRunning succeeded"); }).catch((error: BusinessError) => { console.error(`Failed to Operation startBackgroundRunning. code is ${error.code} message is ${error.message}`); }); }); }
// 取消长时任务 stopContinuousTask() { backgroundTaskManager.stopBackgroundRunning(this.context).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() { Row() { Column() { Text("Index") .fontSize(50) .fontWeight(FontWeight.Bold) Button() { Text('申请长时任务').fontSize(25).fontWeight(FontWeight.Bold) } .type(ButtonType.Capsule) .margin({ top: 10 }) .backgroundColor('#0D9FFB') .width(250) .height(40) .onClick(() => { this.startContinuousTask(); }) Button() { Text('取消长时任务').fontSize(25).fontWeight(FontWeight.Bold) } .type(ButtonType.Capsule) .margin({ top: 10 }) .backgroundColor('#0D9FFB') .width(250) .height(40) .onClick(() => { this.stopContinuousTask(); }) } .width('100%') } .height('100%') }}
复制代码

代码解释

  1. 导入模块


   import { backgroundTaskManager } from '@ohos.resourceschedule.backgroundTaskManager';   import { wantAgent } from '@ohos.app.ability.wantAgent';
复制代码


导入鸿蒙系统的背景任务管理器模块和 wantAgent 模块,用于申请和管理长时任务。


  1. 定义组件和状态


   @Entry   @Component   struct Index {     @State message: string = 'ContinuousTask';     private context: Context = getContext(this);   }
复制代码


定义一个组件 Index,并初始化一个状态 message 用于显示信息,以及 context 用于获取当前上下文。


  1. 申请长时任务


   startContinuousTask() {     let wantAgentInfo: wantAgent.WantAgentInfo = {       wants: [         {           bundleName: "com.example.myapplication",           abilityName: "MainAbility"         }       ],       actionType: wantAgent.OperationType.START_ABILITY,       requestCode: 0,       actionFlags: [wantAgent.WantAgentFlags.UPDATE_PRESENT_FLAG]     };     wantAgent.getWantAgent(wantAgentInfo).then((wantAgentObj: wantAgent.WantAgent) => {       backgroundTaskManager.startBackgroundRunning(this.context,         backgroundTaskManager.BackgroundMode.AUDIO_RECORDING, wantAgentObj).then(() => {         console.info("Operation startBackgroundRunning succeeded");       }).catch((error: BusinessError) => {         console.error(`Failed to Operation startBackgroundRunning. code is ${error.code} message is ${error.message}`);       });     });   }
复制代码


定义 startContinuousTask 方法,用于申请长时任务。通过 wantAgent 模块获取 WantAgent 对象,并使用 backgroundTaskManagerstartBackgroundRunning 方法申请长时任务。


  1. 取消长时任务


   stopContinuousTask() {     backgroundTaskManager.stopBackgroundRunning(this.context).then(() => {       console.info(`Succeeded in operationing stopBackgroundRunning.`);     }).catch((err: BusinessError) => {       console.error(`Failed to operation stopBackgroundRunning. Code is ${err.code}, message is ${err.message}`);     });   }
复制代码


定义 stopContinuousTask 方法,用于取消已申请的长时任务。


  1. 构建界面


   build() {     Row() {       Column() {         Text("Index")           .fontSize(50)           .fontWeight(FontWeight.Bold)         Button() {           Text('申请长时任务').fontSize(25).fontWeight(FontWeight.Bold)         }         .type(ButtonType.Capsule)         .margin({ top: 10 })         .backgroundColor('#0D9FFB')         .width(250)         .height(40)         .onClick(() => {           this.startContinuousTask();         })         Button() {           Text('取消长时任务').fontSize(25).fontWeight(FontWeight.Bold)         }         .type(ButtonType.Capsule)         .margin({ top: 10 })         .backgroundColor('#0D9FFB')         .width(250)         .height(40)         .onClick(() => {           this.stopContinuousTask();         })       }       .width('100%')     }     .height('100%')   }
复制代码


定义 build 方法,构建应用的界面,包括显示信息的文本和两个按钮,分别用于申请和取消长时任务。


这个案例展示了如何在鸿蒙 NEXT 开发中使用 Background Tasks Kit 来实现长时任务,确保在后台执行长时间运行的任务,如音乐播放、导航等。

延迟任务(Deferred Task)的案例

我们来看一个使用 ArkTS 实现延迟任务(Deferred Task)的案例:

案例代码

// 导入模块import workScheduler from '@ohos.resourceschedule.workScheduler';import { BusinessError } from '@ohos.base';
// 创建workInfo对象,配置延迟任务参数const workInfo: workScheduler.WorkInfo = { workId: 1, // 任务唯一标识 networkType: workScheduler.NetworkType.NETWORK_TYPE_WIFI, // 指定网络类型为Wi-Fi bundleName: 'com.example.application', // 应用的bundle名称 abilityName: 'MyWorkSchedulerExtensionAbility', // 任务执行时回调的Ability名称 batteryLevel: 30, // 电池电量低于30%时执行 chargerType: workScheduler.ChargingType.CHARGER_TYPE_NONE, // 不考虑充电类型,仅网络和电池状态 isPersisted: true, // 是否持久化保存工作};
// 申请延迟任务function requestDeferredTask() { 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}`); }}
// 取消延迟任务function cancelDeferredTask() { 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}`); }}
// 导出函数,供外部调用export { requestDeferredTask, cancelDeferredTask };
复制代码

代码解释

  1. 导入模块


   import workScheduler from '@ohos.resourceschedule.workScheduler';   import { BusinessError } from '@ohos.base';
复制代码


导入鸿蒙系统的workScheduler模块,用于操作延迟任务,以及BusinessError模块,用于处理可能发生的错误。


  1. 创建 workInfo 对象


   const workInfo: workScheduler.WorkInfo = {     workId: 1,     networkType: workScheduler.NetworkType.NETWORK_TYPE_WIFI,     bundleName: 'com.example.application',     abilityName: 'MyWorkSchedulerExtensionAbility',     batteryLevel: 30,     chargerType: workScheduler.ChargingType.CHARGER_TYPE_NONE,     isPersisted: true,   };
复制代码


配置延迟任务的参数,包括任务 ID、网络类型、应用 bundle 名称、任务执行时回调的 Ability 名称、电池电量阈值、充电类型以及是否持久化保存工作。


  1. 申请延迟任务


   function requestDeferredTask() {     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}`);     }   }
复制代码


定义requestDeferredTask函数,用于申请延迟任务。使用workScheduler.startWork方法启动任务,并处理可能发生的错误。


  1. 取消延迟任务


   function cancelDeferredTask() {     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}`);     }   }
复制代码


定义cancelDeferredTask函数,用于取消已经申请的延迟任务。使用workScheduler.stopWork方法停止任务,并处理可能发生的错误。


  1. 导出函数


   export { requestDeferredTask, cancelDeferredTask };
复制代码


requestDeferredTaskcancelDeferredTask函数导出,以便在其他模块中调用。


这个案例展示了如何在鸿蒙 NEXT 开发中使用 Background Tasks Kit 来实现延迟任务,适用于对实时性要求不高、可延迟执行的任务,如数据同步、文件下载等场景。

代理提醒(Agent-powered Reminder)的案例

我们来看一个使用 ArkTS 实现代理提醒(Agent-powered Reminder)的案例:

案例代码

// 导入必要的模块import { reminderAgentManager } from '@kit.BackgroundTasksKit';import { notificationManager } from '@kit.NotificationKit';import { BusinessError } from '@kit.BasicServicesKit';
// 定义一个倒计时提醒实例let targetReminderAgent: reminderAgentManager.ReminderRequestTimer = { reminderType: reminderAgentManager.ReminderType.REMINDER_TYPE_TIMER, // 倒计时提醒类型 triggerTimeInSeconds: 10, // 触发时间(秒) actionButton: [{ // 操作按钮 title: 'close', type: reminderAgentManager.ActionButtonType.ACTION_BUTTON_TYPE_CLOSE }], wantAgent: { // 目标能力 pkgName: 'com.example.myapplication', abilityName: 'EntryAbility' }, maxScreenWantAgent: { // 最大化屏幕目标能力 pkgName: 'com.example.myapplication', abilityName: 'EntryAbility' }, title: 'this is title', // 提醒标题 content: 'this is content', // 提醒内容 expiredContent: 'this reminder has expired', // 提醒过期内容 notificationId: 100, // 通知ID slotType: notificationManager.SlotType.SOCIAL_COMMUNICATION // 通知通道类型};
// 发布倒计时提醒reminderAgentManager.publishReminder(targetReminderAgent).then((res: number) => { console.info('Succeeded in publishing reminder. '); let reminderId: number = res; // 发布的提醒 ID}).catch((err: BusinessError) => { console.error(`Failed to publish reminder. Code: ${err.code}, message: ${err.message}`);});
复制代码

代码解释

  1. 导入模块


   import { reminderAgentManager } from '@kit.BackgroundTasksKit';   import { notificationManager } from '@kit.NotificationKit';   import { BusinessError } from '@kit.BasicServicesKit';
复制代码


导入鸿蒙系统的reminderAgentManager模块用于代理提醒管理,notificationManager模块用于通知管理,以及BusinessError模块用于错误处理。


  1. 定义倒计时提醒实例


   let targetReminderAgent: reminderAgentManager.ReminderRequestTimer = {     // ...属性配置   };
复制代码


定义一个倒计时提醒实例targetReminderAgent,配置提醒的类型、触发时间、操作按钮、目标能力、标题、内容等属性。


  1. 发布倒计时提醒


   reminderAgentManager.publishReminder(targetReminderAgent).then((res: number) => {     // ...成功处理   }).catch((err: BusinessError) => {     // ...错误处理   });
复制代码


使用reminderAgentManagerpublishReminder方法发布倒计时提醒。成功时,会返回提醒的 ID,失败时,会捕获并处理错误。


这个案例展示了如何在鸿蒙 NEXT 开发中使用代理提醒功能来实现一个倒计时提醒,适用于需要后台代理提醒的场景,如会议提醒、待办事项提醒等。

最后

以上四种用于开发后台任务的类型,你都 get 到了吗,如果你在开发中有不同的应用场景,欢迎一起讨论,把握鸿蒙趋势,不做等等人,关注威哥爱编程,一起学鸿蒙。

发布于: 2024-12-19阅读数: 2
用户头像

华为 HDE、CSDN 博客专家、Java畅销书作者 2018-05-30 加入

全栈领域优质创作者(Java/HarmonyOS/AI),公众号:威哥爱编程

评论

发布
暂无评论
鸿蒙 NEXT 开发之后台任务开发服务框架学习笔记_HarmonyOS_威哥爱编程_InfoQ写作社区