鴻蒙 NEXT 開發之後臺任務開發服務框架學習筆記

威哥爱编程發表於2024-12-19

大家好,我是 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)的完整案例程式碼:

案例程式碼

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. 匯入背景工作管理員
   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
@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. 匯入模組
   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 到了嗎,如果你在開發中有不同的應用場景,歡迎一起討論,把握鴻蒙趨勢,不做等等人,關注威哥愛程式設計,一起學鴻蒙。

相關文章