鸿蒙后台任务管理开发指南【2】

2025-06-30 23:38:10
106次阅读
0个评论

第二篇:长时任务开发实战

概述

长时任务(Continuous Task)适用于长时间运行在后台、用户可感知的任务,例如后台播放音乐、导航、设备连接等。与短时任务不同,长时任务可以在后台持续运行较长时间,但需要用户明确感知到这些任务的存在,通常会在系统通知栏显示相应的通知。

长时任务为需要持续后台运行的应用提供了解决方案,如音乐播放器、导航应用、健康监测应用等。通过长时任务,这些应用可以在后台持续提供服务,而不会被系统挂起。

1. 长时任务基础概念

1.1 长时任务类型

鸿蒙系统支持多种类型的长时任务:

音频播放:后台音乐播放、播客播放等音频相关任务。

录音:语音记录、通话录音等录音相关任务。

导航定位:GPS导航、位置跟踪等定位相关任务。

蓝牙相关:蓝牙设备连接、数据传输等蓝牙相关任务。

多媒体:视频播放、直播等多媒体相关任务。

VOIP:网络电话、视频通话等VOIP相关任务。

任务保活:其他需要保持应用活跃的任务。

1.2 权限配置

长时任务需要在应用的配置文件中声明相应权限:

{
  "module": {
    "requestPermissions": [
      {
        "name": "ohos.permission.KEEP_BACKGROUND_RUNNING",
        "reason": "用于后台长时任务运行",
        "usedScene": {
          "abilities": ["MainAbility"],
          "when": "inuse"
        }
      }
    ]
  }
}

2. 长时任务实现

2.1 基础长时任务管理

import { backgroundTaskManager } from '@kit.BackgroundTasksKit';
import { wantAgent, WantAgent } from '@kit.AbilityKit';
import { BusinessError } from '@kit.BasicServicesKit';

export class ContinuousTaskManager {
  private wantAgentObj: WantAgent | undefined;
  private taskId: number = 0;

  /**
   * 创建WantAgent,用于点击通知栏时的跳转
   */
  private async createWantAgent(): Promise<WantAgent> {
    const wantAgentInfo: wantAgent.WantAgentInfo = {
      wants: [
        {
          bundleName: 'com.example.myapplication',
          abilityName: 'MainAbility'
        }
      ],
      operationType: wantAgent.OperationType.START_ABILITY,
      requestCode: 0,
      wantAgentFlags: [wantAgent.WantAgentFlags.UPDATE_PRESENT_FLAG]
    };

    try {
      const agent = await wantAgent.getWantAgent(wantAgentInfo);
      console.info('WantAgent创建成功');
      return agent;
    } catch (error) {
      const err = error as BusinessError;
      console.error(`WantAgent创建失败: ${err.code}, ${err.message}`);
      throw error;
    }
  }

  /**
   * 启动长时任务
   * @param taskType 任务类型
   * @param taskName 任务名称
   */
  async startContinuousTask(
    taskType: backgroundTaskManager.BackgroundMode,
    taskName: string
  ): Promise<boolean> {
    try {
      // 创建WantAgent
      this.wantAgentObj = await this.createWantAgent();

      // 启动长时任务
      await backgroundTaskManager.startContinuousTask({
        context: getContext(),
        bgMode: taskType,
        wantAgent: this.wantAgentObj,
        abilityName: 'MainAbility'
      });

      console.info(`长时任务启动成功: ${taskName}`);
      return true;
    } catch (error) {
      const err = error as BusinessError;
      console.error(`长时任务启动失败: ${err.code}, ${err.message}`);
      return false;
    }
  }

  /**
   * 停止长时任务
   */
  async stopContinuousTask(): Promise<boolean> {
    try {
      await backgroundTaskManager.stopContinuousTask({
        context: getContext()
      });

      console.info('长时任务停止成功');
      return true;
    } catch (error) {
      const err = error as BusinessError;
      console.error(`长时任务停止失败: ${err.code}, ${err.message}`);
      return false;
    }
  }
}

2.2 音乐播放长时任务示例

import { audio } from '@kit.AudioKit';

export class MusicPlayerManager {
  private continuousTaskManager: ContinuousTaskManager;
  private audioPlayer: audio.AudioPlayer | undefined;
  private isPlaying: boolean = false;

  constructor() {
    this.continuousTaskManager = new ContinuousTaskManager();
  }

  /**
   * 开始播放音乐
   * @param audioUrl 音频文件URL
   */
  async startPlayMusic(audioUrl: string): Promise<void> {
    try {
      // 启动音频播放长时任务
      const success = await this.continuousTaskManager.startContinuousTask(
        backgroundTaskManager.BackgroundMode.AUDIO_PLAYBACK,
        '音乐播放'
      );

      if (!success) {
        console.error('长时任务启动失败,无法播放音乐');
        return;
      }

      // 创建音频播放器
      this.audioPlayer = audio.createAudioPlayer();
      
      // 设置音频播放器回调
      this.setupAudioPlayerCallbacks();
      
      // 设置音频源并开始播放
      this.audioPlayer.src = audioUrl;
      this.audioPlayer.play();
      
      this.isPlaying = true;
      console.info('音乐播放开始');
      
    } catch (error) {
      console.error('音乐播放启动失败:', error);
      await this.continuousTaskManager.stopContinuousTask();
    }
  }

  /**
   * 停止播放音乐
   */
  async stopPlayMusic(): Promise<void> {
    try {
      if (this.audioPlayer) {
        this.audioPlayer.stop();
        this.audioPlayer.release();
        this.audioPlayer = undefined;
      }

      this.isPlaying = false;
      
      // 停止长时任务
      await this.continuousTaskManager.stopContinuousTask();
      
      console.info('音乐播放停止');
    } catch (error) {
      console.error('音乐播放停止失败:', error);
    }
  }

  /**
   * 暂停播放
   */
  pausePlayMusic(): void {
    if (this.audioPlayer && this.isPlaying) {
      this.audioPlayer.pause();
      this.isPlaying = false;
      console.info('音乐播放暂停');
    }
  }

  /**
   * 恢复播放
   */
  resumePlayMusic(): void {
    if (this.audioPlayer && !this.isPlaying) {
      this.audioPlayer.play();
      this.isPlaying = true;
      console.info('音乐播放恢复');
    }
  }

  /**
   * 设置音频播放器回调
   */
  private setupAudioPlayerCallbacks(): void {
    if (!this.audioPlayer) return;

    // 播放完成回调
    this.audioPlayer.on('finish', () => {
      console.info('音乐播放完成');
      this.stopPlayMusic();
    });

    // 播放错误回调
    this.audioPlayer.on('error', (error) => {
      console.error('音乐播放错误:', error);
      this.stopPlayMusic();
    });

    // 播放准备就绪回调
    this.audioPlayer.on('dataLoad', () => {
      console.info('音频数据加载完成');
    });
  }

  /**
   * 获取播放状态
   */
  getPlayingStatus(): boolean {
    return this.isPlaying;
  }
}

3. 长时任务扩展能力

3.1 ContinuousTaskExtensionAbility

对于复杂的长时任务场景,可以使用ContinuousTaskExtensionAbility:

import { ContinuousTaskExtensionAbility } from '@kit.BackgroundTasksKit';
import { backgroundTaskManager } from '@kit.BackgroundTasksKit';

export default class MyContinuousTaskExtensionAbility extends ContinuousTaskExtensionAbility {
  
  /**
   * 长时任务开始回调
   */
  onContinuousTaskStart(workInfo: backgroundTaskManager.WorkInfo): void {
    console.info(`长时任务开始: ${JSON.stringify(workInfo)}`);
    
    // 根据不同的任务类型执行不同的逻辑
    switch (workInfo.bgMode) {
      case backgroundTaskManager.BackgroundMode.AUDIO_PLAYBACK:
        this.handleAudioPlayback();
        break;
      case backgroundTaskManager.BackgroundMode.LOCATION:
        this.handleLocationTracking();
        break;
      case backgroundTaskManager.BackgroundMode.BLUETOOTH_INTERACTION:
        this.handleBluetoothInteraction();
        break;
      default:
        console.warn('未知的长时任务类型');
    }
  }

  /**
   * 长时任务停止回调
   */
  onContinuousTaskStop(workInfo: backgroundTaskManager.WorkInfo): void {
    console.info(`长时任务停止: ${JSON.stringify(workInfo)}`);
    
    // 执行清理工作
    this.cleanup();
  }

  /**
   * 处理音频播放任务
   */
  private handleAudioPlayback(): void {
    console.info('开始处理音频播放长时任务');
    // 实现音频播放逻辑
  }

  /**
   * 处理位置跟踪任务
   */
  private handleLocationTracking(): void {
    console.info('开始处理位置跟踪长时任务');
    // 实现位置跟踪逻辑
  }

  /**
   * 处理蓝牙交互任务
   */
  private handleBluetoothInteraction(): void {
    console.info('开始处理蓝牙交互长时任务');
    // 实现蓝牙交互逻辑
  }

  /**
   * 清理资源
   */
  private cleanup(): void {
    console.info('执行长时任务清理工作');
    // 释放资源,停止相关服务
  }
}

4. 长时任务监控与管理

4.1 任务状态监控

export class ContinuousTaskMonitor {
  private taskStatus: Map<string, boolean> = new Map();
  private monitorTimer: number | undefined;

  /**
   * 开始监控长时任务状态
   */
  startMonitoring(): void {
    this.monitorTimer = setInterval(() => {
      this.checkTaskStatus();
    }, 30000); // 每30秒检查一次
    
    console.info('长时任务监控已开始');
  }

  /**
   * 停止监控
   */
  stopMonitoring(): void {
    if (this.monitorTimer) {
      clearInterval(this.monitorTimer);
      this.monitorTimer = undefined;
      console.info('长时任务监控已停止');
    }
  }

  /**
   * 检查任务状态
   */
  private checkTaskStatus(): void {
    // 检查各个长时任务的运行状态
    this.taskStatus.forEach((isRunning, taskName) => {
      if (isRunning) {
        console.info(`长时任务 ${taskName} 正在运行`);
        // 可以在这里添加健康检查逻辑
      }
    });
  }

  /**
   * 注册任务状态
   */
  registerTask(taskName: string, isRunning: boolean): void {
    this.taskStatus.set(taskName, isRunning);
    console.info(`任务 ${taskName} 状态已注册: ${isRunning ? '运行中' : '已停止'}`);
  }

  /**
   * 更新任务状态
   */
  updateTaskStatus(taskName: string, isRunning: boolean): void {
    this.taskStatus.set(taskName, isRunning);
    console.info(`任务 ${taskName} 状态已更新: ${isRunning ? '运行中' : '已停止'}`);
  }
}

通过本篇的学习,开发者可以掌握鸿蒙长时任务的实现方法,为需要持续后台运行的应用提供稳定可靠的解决方案。

收藏00

登录 后评论。没有帐号? 注册 一个。