大家好,我是 V 哥,在学习鸿蒙时,想做一个音乐播放器,其中播放音乐的功能,一定要使用到后台任务开发服务,鸿蒙 NEXT 就提供了这样的能力,Background Tasks Kit(后台任务开发服务)是一个强大的框架,它允许开发者高效地管理和调度后台任务,实现应用功能的持续运行。今天的内容,我们来讨论学习后台任务开发服务框架的能力。
Background Tasks Kit 简介
Background Tasks Kit是鸿蒙 NEXT 提供的后台任务开发框架,好像是一句废话,哈哈,来看主要作用包括:
- 降低设备能耗:通过规范后台任务的使用,避免应用在后台过度消耗设备资源,延长设备续航时间。
- 优化用户体验:确保后台任务的正常运行,避免应用在后台被系统杀掉,保证用户体验的连贯性。
- 提供多种后台任务类型:支持短时任务、长时任务、延迟任务、代理提醒等多种后台任务类型,满足不同场景的开发需求。
后台任务类型及特点
我们来看一下,Background Tasks Kit 提供的四种后台任务类型,每种类型都有其独特的特点和适用场景:
短时任务(Transient Task)
- 特点:实时性要求高,耗时不长。
- 适用场景:保存状态、发送消息、网络请求等。
长时任务(Continuous Task)
- 特点:长时间后台运行。
- 适用场景:音乐播放、导航、设备连接、位置跟踪等。
延迟任务(Deferred Task)
- 特点:允许条件触发。
- 适用场景:有网络时不定期主动获取邮件、定期同步数据等。
代理提醒(Agent-powered Reminder)
- 特点:系统在后台代理应用执行的提醒任务。
- 适用场景:倒计时、闹钟、日历、会议提醒等。
应用场景
后台任务开发服务,应用场景是非常多的,比如以下4种应用,就会用到:
音乐播放应用
- 在音乐播放应用中,即使用户将应用切换到后台,也可以通过申请长时任务(Continuous Task)来保证音乐播放的连续性,提升用户体验。
导航应用
- 导航应用在后台运行时,可以通过长时任务(Continuous Task)持续提供导航服务,即使在屏幕关闭或应用不在前台时也能继续导航。
文件下载
- 对于需要在后台下载大文件的场景,可以利用长时任务(Continuous Task)来保证下载任务的持续进行,如浏览器后台下载文件。
邮件同步
- 邮件应用可以利用延迟任务(Deferred Task)在有网络连接时定期同步邮件,确保用户及时收到新邮件。
接下来,V 哥将分别对短时任务,长时任务,延迟任务和代理提醒四种类型,通过案例来讲解如何使用哈。
实现短时任务(Transient Task)的案例
我们来看一个使用 ArkTS 实现短时任务(Transient Task)的完整案例代码:
案例代码
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)
}
}
代码解释
- 导入背景任务管理器:
import backgroundTaskManager from '@ohos.resourceschedule.backgroundTaskManager';
导入鸿蒙系统的背景任务管理器模块,用于申请和管理短时任务。
- 定义组件和状态:
@Entry
@Component
struct Index {
@State message: string = 'Click button to calculate.';
private requestId: number = 0;
}
定义一个组件 Index
,并初始化两个状态:message
用于显示信息,requestId
用于存储请求短时任务的ID。
- 申请短时任务:
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
中,并设置一个回调函数,当短时任务即将超时时,取消短时任务。
- 取消短时任务:
cancelSuspendDelay() {
backgroundTaskManager.cancelSuspendDelay(this.requestId);
console.info('Request suspension delay cancel.');
}
定义 cancelSuspendDelay
方法,用于取消已申请的短时任务。
- 计算任务:
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
方法,执行一个耗时的计算任务,并返回执行时间。
- 点击回调:
clickCallback = () => {
this.requestSuspendDelay();
let timeCost = this.computeTask(50000000);
this.message = `Total time costed = ${timeCost} ms.`;
this.cancelSuspendDelay();
}
定义 clickCallback
方法,当用户点击按钮时,申请短时任务,执行计算任务,并在完成后取消短时任务。
- 构建界面:
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
@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%')
}
}
代码解释
- 导入模块:
import { backgroundTaskManager } from '@ohos.resourceschedule.backgroundTaskManager';
import { wantAgent } from '@ohos.app.ability.wantAgent';
导入鸿蒙系统的背景任务管理器模块和wantAgent模块,用于申请和管理长时任务。
- 定义组件和状态:
@Entry
@Component
struct Index {
@State message: string = 'ContinuousTask';
private context: Context = getContext(this);
}
定义一个组件 Index
,并初始化一个状态 message
用于显示信息,以及 context
用于获取当前上下文。
- 申请长时任务:
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
对象,并使用 backgroundTaskManager
的 startBackgroundRunning
方法申请长时任务。
- 取消长时任务:
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
方法,用于取消已申请的长时任务。
- 构建界面:
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 };
代码解释
- 导入模块:
import workScheduler from '@ohos.resourceschedule.workScheduler';
import { BusinessError } from '@ohos.base';
导入鸿蒙系统的workScheduler
模块,用于操作延迟任务,以及BusinessError
模块,用于处理可能发生的错误。
- 创建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名称、电池电量阈值、充电类型以及是否持久化保存工作。
- 申请延迟任务:
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
方法启动任务,并处理可能发生的错误。
- 取消延迟任务:
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
方法停止任务,并处理可能发生的错误。
- 导出函数:
export { requestDeferredTask, cancelDeferredTask };
将requestDeferredTask
和cancelDeferredTask
函数导出,以便在其他模块中调用。
这个案例展示了如何在鸿蒙 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}`);
});
代码解释
- 导入模块:
import { reminderAgentManager } from '@kit.BackgroundTasksKit';
import { notificationManager } from '@kit.NotificationKit';
import { BusinessError } from '@kit.BasicServicesKit';
导入鸿蒙系统的reminderAgentManager
模块用于代理提醒管理,notificationManager
模块用于通知管理,以及BusinessError
模块用于错误处理。
- 定义倒计时提醒实例:
let targetReminderAgent: reminderAgentManager.ReminderRequestTimer = {
// ...属性配置
};
定义一个倒计时提醒实例targetReminderAgent
,配置提醒的类型、触发时间、操作按钮、目标能力、标题、内容等属性。
- 发布倒计时提醒:
reminderAgentManager.publishReminder(targetReminderAgent).then((res: number) => {
// ...成功处理
}).catch((err: BusinessError) => {
// ...错误处理
});
使用reminderAgentManager
的publishReminder
方法发布倒计时提醒。成功时,会返回提醒的ID,失败时,会捕获并处理错误。
这个案例展示了如何在鸿蒙 NEXT 开发中使用代理提醒功能来实现一个倒计时提醒,适用于需要后台代理提醒的场景,如会议提醒、待办事项提醒等。
最后
以上四种用于开发后台任务的类型,你都 get 到了吗,如果你在开发中有不同的应用场景,欢迎一起讨论,把握鸿蒙趋势,不做等等人,关注威哥爱编程,一起学鸿蒙。