开发者技术支持 - 后台音频播放

举报
yd_296469199 发表于 2025/09/17 17:11:10 2025/09/17
【摘要】 后台播放音频,目前已知支持avPlayer和阿里云播放器

一、问题说明:

  app切换到后台或者返回桌面时,音频停止播放!

二、原因分析:

  音频播放没有配置后台长时任务!

三、解决思路:

  为音频播放功能配置后台长时任务.

四、解决方案:

前言:

  此文章是一篇针对音频后台播放功能解决方案

4.1、入口模块配置后台任务权限

  此权限是系统开放权限,无需向用户申请,直接用即可

"requestPermissions": [
      {
        "name": "ohos.permission.KEEP_BACKGROUND_RUNNING",
        //在所属模块的resource-base-element-string.json文件中配置即可
        "reason": "$string:background_permission_reason",
        "usedScene": {
          "abilities": [
            "EntryAbility"
          ],
          "when": "always"
        }
      }
]

4.2、在入口模块的module.json5文件中声明后台任务类型

"module": {
    "abilities": [
        {
            "backgroundModes": [
              // 长时任务类型的配置项
             "audioPlayback"//后台播放音频类型
            ]
        }
 ],
 // ...
}

4.3、导入模块

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

// 在元服务中,请删除WantAgent导入

4.4、创建会话

  用于管理后续请求

//三个参数分别为:上下文、后台任务标签、后台任务类型
this.session = await avSession.createAVSession(getContext(), 'BackgroundPlaying', 'audio')
await this.session.activate()

4.5、配置wantAgentInfo参数并获取wantAgentObj对象

  //配置wantAgentInfo参数
  let wantAgentInfo: wantAgent.WantAgentInfo = {
    // 点击通知后,将要执行的动作列表
    // 添加需要被拉起应用的bundleName和abilityName
    wants: [{
      bundleName: "应用包名",//可在App.json5文件中查看,也可通过bundleManager获取
      abilityName: "入口ability(EntryAbility)",
    } as Want],
    
    // 使用者自定义的一个私有值
    requestCode: 100,
    
    actionType: wantAgent.OperationType.START_ABILITY,//不加此参数,报错:提示输入参数无效
    
    wantAgentFlags: [wantAgent.WantAgentFlags.UPDATE_PRESENT_FLAG]//可加可不加
  };
  
  //获取wantAgentObj对象
  let wantAgentObj = await wantAgent.getWantAgent(wantAgentInfo)

4.6、创建后台任务

 await backgroundTaskManager.startBackgroundRunning(context, backgroundTaskManager.BackgroundMode.AUDIO_PLAYBACK,
        wantAgentObj);

4.7、停止后台任务

backgroundTaskManager.stopBackgroundRunning(getContext()).then(() => {
    console.info(`Succeeded in operationing stopBackgroundRunning.`);
  }).catch((err: BusinessError) => {
    console.error(`Failed to operation stopBackgroundRunning. Code is ${err.code}, message is ${err.message}`);
  });

4.8、封装长时任务工具类

import { Want, wantAgent } from '@kit.AbilityKit';
import { avSession } from '@kit.AVSessionKit';
import { backgroundTaskManager } from '@kit.BackgroundTasksKit';


export class ContinuousTaskManager {
  session?: avSession.AVSession;
  private static _instance?: ContinuousTaskManager

  public static getInstance() {
    if (!ContinuousTaskManager._instance) {
      ContinuousTaskManager._instance = new ContinuousTaskManager()
    }
    return ContinuousTaskManager._instance
  }

  async getSession() {
    if (!this.session) {
      this.session = await avSession.createAVSession(getContext(), 'BackgroundPlaying', 'audio')
    }
    return this.session;
  }

  // 申请长时任务
  async startBackgroundRunning() {
    try {
      const context = getContext()
      Logger.info(JSON.stringify(context))
      if (this.session) {
        // YAlert(`已存在长时任务:\n\r sessionId:${this.session.sessionId} \n\r sessionType:${this.session.sessionType} `)
        return;
      }
      // 重点1: 提供音频后台约束能力,音频接入AVSession后,可以进行后台音频播放
      const session = await this.getSession()
      await session.activate()

      let wantAgentInfo: wantAgent.WantAgentInfo = {
        // 点击通知后,将要执行的动作列表
        // 添加需要被拉起应用的bundleName和abilityName
        wants: [{
          bundleName: "应用包名",
          abilityName: "入口ability(EntryAbility)",
        } as Want],
        // 使用者自定义的一个私有值
        requestCode: 100,
        actionType: wantAgent.OperationType.START_ABILITY, //不加此参数,报错:提示输入参数无效
        // wantAgentFlags: [wantAgent.WantAgentFlags.UPDATE_PRESENT_FLAG]//加不加都行
      };
      
      let wantAgentObj = await wantAgent.getWantAgent(wantAgentInfo)
      //方便断点调式
      Logger.info('wantAgentObj:', JSON.stringify(wantAgentInfo))
      
      // 重点2: 创建后台任务
      await backgroundTaskManager.startBackgroundRunning(context, backgroundTaskManager.BackgroundMode.AUDIO_PLAYBACK,
        wantAgentObj);
      // YAlert('后台任务建立成功')
    } catch (err) {
      Logger.info('开启后台任务失败: ', JSON.stringify(err))
      YAlertError('开启后台任务失败', err.code, err.message);
    }
  }

  // 停止后台任务
  async stopBackgroundRunning() {
    backgroundTaskManager.stopBackgroundRunning(getContext())
    // this.session?.deactivate()
    //下方两行代码避免返回重进进入创建会话失败
    this.session?.destroy()
    this.session = undefined;
  }
}


export function YAlertError(tip: string, code: number, message: string) {
  AlertDialog.show({ message: `${tip} \n\r code:${code} \n\r  message:${message}`, autoCancel: true })
}

export function YAlert(message: string) {
  AlertDialog.show({ message: `${message}`, autoCancel: true })
}

4.9、使用方法

//在播放接口调用上方或者下方调用都可  例:
this.avPlayer?.play();
ContinuousTaskManager.getInstance.startBackgroundRunning();

//注意在aboutToDisappear或者停止播放(不是暂停)时停止会话,避免内存泄露
ContinuousTaskManager.getInstance.stopBackgroundRunning();
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。