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

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

Background Tasks Kit 简介

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

  1. 降低设备能耗:通过规范后台任务的使用,避免应用在后台过度消耗设备资源,延长设备续航时间。
  2. 优化用户体验:确保后台任务的正常运行,避免应用在后台被系统杀掉,保证用户体验的连贯性。
  3. 提供多种后台任务类型:支持短时任务、长时任务、延迟任务、代理提醒等多种后台任务类型,满足不同场景的开发需求。

后台任务类型及特点

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

  1. 短时任务(Transient Task)

    • 特点:实时性要求高,耗时不长。
    • 适用场景:保存状态、发送消息、网络请求等。
  2. 长时任务(Continuous Task)

    • 特点:长时间后台运行。
    • 适用场景:音乐播放、导航、设备连接、位置跟踪等。
  3. 延迟任务(Deferred Task)

    • 特点:允许条件触发。
    • 适用场景:有网络时不定期主动获取邮件、定期同步数据等。
  4. 代理提醒(Agent-powered Reminder)

    • 特点:系统在后台代理应用执行的提醒任务。
    • 适用场景:倒计时、闹钟、日历、会议提醒等。

应用场景

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

  1. 音乐播放应用

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

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

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

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

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

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

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

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

@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();
    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. 导入背景任务管理器
typescript 复制代码
   import backgroundTaskManager from '@ohos.resourceschedule.backgroundTaskManager';

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

  1. 定义组件和状态
typescript 复制代码
   @Entry
   @Component
   struct Index {
     @State message: string = 'Click button to calculate.';
     private requestId: number = 0;
   }

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

  1. 申请短时任务
typescript 复制代码
   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. 取消短时任务
typescript 复制代码
   cancelSuspendDelay() {
     backgroundTaskManager.cancelSuspendDelay(this.requestId);
     console.info('Request suspension delay cancel.');
   }

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

  1. 计算任务
typescript 复制代码
   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. 点击回调
typescript 复制代码
   clickCallback = () => {
     this.requestSuspendDelay();
     let timeCost = this.computeTask(50000000);
     this.message = `Total time costed = ${timeCost} ms.`;
     this.cancelSuspendDelay();
   }

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

  1. 构建界面
typescript 复制代码
   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)的案例:

案例代码
typescript 复制代码
// 导入必要的模块
import { backgroundTaskManager } from '@ohos.resourceschedule.backgroundTaskManager';
import { wantAgent } from '@ohos.app.ability.wantAgent';

@Entry
@Component
struct 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. 导入模块
typescript 复制代码
   import { backgroundTaskManager } from '@ohos.resourceschedule.backgroundTaskManager';
   import { wantAgent } from '@ohos.app.ability.wantAgent';

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

  1. 定义组件和状态
typescript 复制代码
   @Entry
   @Component
   struct Index {
     @State message: string = 'ContinuousTask';
     private context: Context = getContext(this);
   }

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

  1. 申请长时任务
typescript 复制代码
   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. 取消长时任务
typescript 复制代码
   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. 构建界面
typescript 复制代码
   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)的案例:

案例代码
typescript 复制代码
// 导入模块
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. 导入模块
typescript 复制代码
   import workScheduler from '@ohos.resourceschedule.workScheduler';
   import { BusinessError } from '@ohos.base';

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

  1. 创建workInfo对象
typescript 复制代码
   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. 申请延迟任务
typescript 复制代码
   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. 取消延迟任务
typescript 复制代码
   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. 导出函数
typescript 复制代码
   export { requestDeferredTask, cancelDeferredTask };

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

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

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

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

案例代码
typescript 复制代码
// 导入必要的模块
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. 导入模块
typescript 复制代码
   import { reminderAgentManager } from '@kit.BackgroundTasksKit';
   import { notificationManager } from '@kit.NotificationKit';
   import { BusinessError } from '@kit.BasicServicesKit';

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

  1. 定义倒计时提醒实例
typescript 复制代码
   let targetReminderAgent: reminderAgentManager.ReminderRequestTimer = {
     // ...属性配置
   };

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

  1. 发布倒计时提醒
typescript 复制代码
   reminderAgentManager.publishReminder(targetReminderAgent).then((res: number) => {
     // ...成功处理
   }).catch((err: BusinessError) => {
     // ...错误处理
   });

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

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

最后

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

相关推荐
xinzheng新政43 分钟前
纸板制造制胶工艺学习记录4
学习·制造
AlbertZein2 小时前
HarmonyOS5 凭什么学鸿蒙—— GetContext
架构·harmonyos
我们从未走散3 小时前
JVM学习笔记-----类加载
笔记·学习
前路不黑暗@4 小时前
C语言:操作符详解(二)
c语言·开发语言·经验分享·笔记·学习·学习方法·visual studio
蜡笔小电芯4 小时前
【STM32】STM32H750 CubeMX 配置 USB CDC 虚拟串口笔记
笔记·stm32·嵌入式硬件
xiaoxiaoxiaolll4 小时前
金刚石基植入体新突破!Adv. Funct. Mater. 报道首例增材制造固态摩擦电能量收集器
学习
x.Jessica4 小时前
网络的构成元素
网络·学习·计算机网络
森之鸟5 小时前
flutter项目适配鸿蒙
flutter·华为·harmonyos
快乐zbc5 小时前
数学建模Topsis法笔记
笔记·数学建模
yiqiqukanhaiba5 小时前
STM32学习笔记14-I2C硬件控制
笔记·stm32·学习