大家好,我是 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 到了嗎,如果你在開發中有不同的應用場景,歡迎一起討論,把握鴻蒙趨勢,不做等等人,關注威哥愛程式設計,一起學鴻蒙。