HarmonyOS鸿蒙Next中目前APP存在多种不同课程要实现后台播放,配置完成后,点击一种课程之后(后台播放功能正常),再进入其他课程,其他课程后台播放功能失败,目前解决了但不知道是否合理。

HarmonyOS鸿蒙Next中目前APP存在多种不同课程要实现后台播放,配置完成后,点击一种课程之后(后台播放功能正常),再进入其他课程,其他课程后台播放功能失败,目前解决了但不知道是否合理。 【问题描述】:每次创建新的播控中心实例,后台播放功能正常,前台视频不能正常播放

【问题现象】:未提示报错信息

【版本信息】:dev6.0.0、OS5.1.0.150、Api语言版本 5.0.5(17)

【复现代码】:

/* if (!AvSessionController.instance) {
 }*/   // 注释掉实例判断逻辑后功能就可以正常使用
 AvSessionController.instance = new AvSessionController();// 每次调用都创建新实例
 if (courseInfo && AvSessionController.instance.courseInfo !== courseInfo) {
   AvSessionController.instance.courseInfo = courseInfo;
 }
 return AvSessionController.instance;
}

【尝试解决方案】:注释掉实例判断逻辑后功能就可以正常使用

需求:多个视频后台播放是否需要创建多个AvSessionController实例,这是否合理。


更多关于HarmonyOS鸿蒙Next中目前APP存在多种不同课程要实现后台播放,配置完成后,点击一种课程之后(后台播放功能正常),再进入其他课程,其他课程后台播放功能失败,目前解决了但不知道是否合理。的实战教程也可以访问 https://www.itying.com/category-93-b0.html

9 回复

开发者你好,

AVSession创建AVSession会对后台的音频播放、VOIP通话做约束,以单例形式存在,一个应用进程仅允许存在一个会话,重复创建会失败。

AVSessionController:媒体会话控制器,媒体会话控制器的持有者,一般指媒体会话控制方,可以控制媒体会话提供方的应用播放行为,也可以获取应用的播放信息,还可以监听音视频应用播放状态的变化,用于确保媒体会话信息在音视频应用和播控中心之间的同步,参考本地媒体会话概述

单个媒体应用进程内,作为媒体会话提供方,多个视频或者单个视频播控场景下,均仅可创建一个AVSession作为本地媒体会话。媒体会话控制方AVSessionController可以采用多实例形式,但不需要,推荐通过单例模式统一进行媒体会话控制。

参考示例

更多关于HarmonyOS鸿蒙Next中目前APP存在多种不同课程要实现后台播放,配置完成后,点击一种课程之后(后台播放功能正常),再进入其他课程,其他课程后台播放功能失败,目前解决了但不知道是否合理。的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


不需要创建多个AVSessionController实例,当前方案不合理

您的代码修改为每次创建新实例后“功能正常”,实际是掩盖了根本问题,但会引发新风险:

  • 表面正常:新实例强制覆盖旧会话,元数据被重置,系统误认为新课程开始播放。
  • 实际隐患
    • 资源泄漏:旧会话未正确销毁(需调用session.destroy())。
    • 状态错乱:多个控制器同时操作同一会话,触发不可预知的播控命令。
    • 违反规范:AVSession应长期存在,频繁创建违反“避免局部变量保存”原则。

正确步骤如下:

1. 创建单例AVSession(应用初始化时执行一次)

// 在应用启动或首次播放时创建,确保全局唯一
let avSession: AVSession | null = null;

async function initAVSession() {
  if (!avSession) {
    let context = ...; // 获取UIAbilityContext
    avSession = await avSession.createAVSession(context, 'COURSE_PLAYER', 'video');
    await avSession.activate();
  }
  return avSession;
}

2. 切换课程时更新元数据(而非创建新实例)

async function switchCourse(courseInfo: CourseInfo) {
  const session = await initAVSession();
  
  // 关键:更新元数据标识新课程
  await session.setAVMetadata({
    assetId: courseInfo.id, // 唯一标识课程
    title: courseInfo.title,
    artist: courseInfo.teacher,
    duration: courseInfo.duration
  });

  // 同步更新播放状态
  await session.setAVPlaybackState({
    state: 'play', // 或 'pause'
    position: 0,   // 新课程从头开始
    speed: 1.0
  });
}

3. 控制器管理(使用会话自带控制器)

// 通过会话获取控制器,无需自行创建
const controller = await avSession.getController();

// 注册播控命令监听(如播放/暂停)
controller.on('play', () => {
  // 处理播放逻辑
});

实际应用中,大多数音视频都有后台播放的需求,本指南将详细讲解如何实现后台长时间播放的方法。

基本概念

开始之前,开发者应了解以下基本概念,以便根据自身播放器的类型,更有效地实现后台播放。

  • 长时任务:请参考长时任务(ArkTS)说明。

    设备返回主界面、锁屏、应用切换等操作会使应用退至后台。当应用退至后台时,再继续活动,可能会出现设备耗电快、用户界面卡顿等问题。为了降低设备耗电速度、保障用户使用流畅度,系统会对退至后台的应用进行管控,包括进程挂起和进程终止。

    当应用退至后台并需要长时间运行用户可感知的任务(如播放音乐、播放视频等)时,为防止应用进程被挂起,导致对应功能异常,可以申请长时任务,使应用在后台长时间运行。

  • AVSession:请参考AVSession Kit简介

    AVSession Kit(音视频播控服务)是系统提供的音视频管控服务,用于统一管理系统中音视频行为,帮助开发者快速构建音视频统一展示和控制能力。音视频类应用接入AVSession后,可以设置应用的数据(如正在播放的歌曲、歌曲的播放状态等)。用户可以通过系统播控中心来展示和控制不同应用的播放。AVSession会对后台的媒体播放有约束行为,所以通常来说,音频应用、听书类应用、视频应用等都需要接入AVSession。如果应用在没有创建AVSession的情况进行上述业务,系统会在检测到应用退至后台时,停止对应的音视频播放,以达到约束应用行为的目的。

  • AVPlayer:参考AVPlayer说明。

    AVPlayer是一款功能强大的媒体播放器。使用AVPlayer可以实现端到端地播放多种音视频格式(如mp4、mp3、mkv、mpeg-ts等),开发者提供媒体源即可启动播放,无需关注复杂的解封装、解码处理。

  • AudioRenderer:请参考使用AudioRenderer开发音频播放功能说明。

    AudioRenderer是音频渲染器,用于播放PCM(Pulse Code Modulation)音频数据。相比AVPlayer而言,AudioRenderer可以在输入前添加数据预处理,更适合有音频开发经验的开发者,以实现更灵活的播放功能。

应用接入规范

  • 当应用需要在后台播放媒体类型(流类型为STREAM_USAGE_MUSIC、STREAM_USAGE_MOVIE和STREAM_USAGE_AUDIOBOOK)和游戏类型(流类型为STREAM_USAGE_GAME)时,必须接入AVSession和申请长时任务。流类型请参考使用合适的音频流类型,长时任务支持的类型请参考BackgroundMode

  • 除了上述播放类型,针对用户可感知的其他播放任务,如果应用需要在后台长时间运行该任务,必须申请AUDIO_PLAYBACK类型长时任务。

如果应用不满足上述接入规范,退至后台播放时会被系统静音并冻结,无法在后台正常播放。直到应用重新切回前台时,才会被解除静音并恢复播放。

开发步骤

音视频应用进行后台播放的基本步骤如下所示。

启动播放器

应用播放可以通过AudioRenderer、AVPlayer、其他第三方或自研的播放器来播放音视频。

  • AudioRenderer:使用AudioRenderer创建播放音频流时应该注意使用合适的音频流类型。流类型的不同对音量控制、音频焦点管理以及输入/输出设备都具有决定性影响。详细内容请参考使用合适的音频流类型

    同时需要注意正确处理音频焦点,系统预设了默认的音频焦点策略,根据音频流的类型及启动的先后顺序,对所有播放和录制音频流进行统一管理。在应用播放或录制音频的过程中,若有其他音频流申请焦点,系统会根据焦点策略进行焦点处理。若判定本音频流的焦点有变化,系统会自动执行一些必要操作(如暂停、继续、降低音量、恢复音量等),并通过音频焦点事件(InterruptEvent)通知应用。详细内容请参考处理音频焦点变化

    开发指导请参考使用AudioRenderer开发音频播放功能

  • AVPlayer:使用AVPlayer可以实现端到端播放原始媒体资源。如果要实现后台播放或熄屏播放,需要接入AVSession和申请长时任务,避免播放被系统强制中断。AVPlayer可通过audioInterruptMode属性设置焦点管理策略,该策略默认使用SHARE_MODE共享焦点模式。

    开发指导请参考使用AVPlayer播放音频(ArkTS)

接入AVSession

当创建的音频流类型为STREAM_USAGE_MUSIC、STREAM_USAGE_MOVIE、STREAM_USAGE_AUDIOBOOK或STREAM_USAGE_GAME时,无论是将应用退至后台继续播放,还是在后台启动播放,都必须接入AVSession。

关于AVSession的创建和释放时机,建议在应用启动或开始播放业务之前进行创建,并在应用进程结束或完全退出播放业务且不再播放时予以释放,以避免频繁创建和释放AVSession,从而保证应用播放业务的连续性和稳定性。应用后台播放时,需要确保AVSession对象实例在应用后台活动期间一直存在,避免被系统回收、释放,比如不要使用局部变量保存AVSession对象等。

创建AVSession后,为了保证接入体验,要求设置以下元数据并注册以下控制命令。

  • 元数据:标题、副标题/歌手、封面图。具体操作请参考设置元数据

  • 注册控制命令:播放/暂停。具体操作请参考注册控制命令

AVSession的接入开发请参考指南应用接入AVSession场景介绍

申请长时任务

在长时任务中可以申请多种类型的任务。例如:当后台播音的任务类型为AUDIO_PLAYBACK时,应用在后台播放音频、视频或通过AVSession投播组件投播,都可申请类型为AUDIO_PLAYBACK的长时任务。

  • 播放时申请长时任务,如果应用明确有后台播放业务(例如:视频应用开启后台放音选项),可以在前台播放时申请长时任务。
  • 暂停或停止时主动取消长时任务。(例如:用户主动点击音乐暂停播放时,应用需及时取消对应的长时任务;用户再次点击音乐播放时,需重新申请长时任务。)
  • 若音频在后台播放时被打断(例如:焦点打断),系统会自行检测,冻结或者取消长时任务。当应用重启音频播放时,需要再次申请长时任务。
  • 应用收到AVSession播控指令,收到音频设备变更等需要做出对应播放和暂停操作时,都需要在暂停时取消长时任务,播放时重新申请长时任务。
  • 通过AVSession投播组件后台投播,开始投播时申请长时任务,断开投播时取消长时任务。投播过程中音频暂停,无须对长时任务做处理。

具体操作请参考长时任务(ArkTS)中的开发步骤

监听前后台状态

如果应用本身没有后台播放业务,可以通过监听生命周期函数onBackground来判断应用是否已进入后台并主动停止播放。否则会受到AVSession与长时任务模块管控,对应用正常的播放业务造成影响。如需在应用回到前台时重启播放,可以通过监听生命周期函数onForeground来判断应用是否回到前台。

完整示例

使用AVPlayer后台播放

  • 本示例主要展示通过系统播放器AVPlayer实现视频类应用的开发,功能包括后台播放和系统播控中心的交互。

使用AudioRenderer后台播放

  • 本场景解决方案主要面向前台音频开发人员。指导开发者基于AudioRenderer开发音频播控功能。功能包括后台播放、系统播控中心的交互、适配不同类型的焦点打断策略、切换路由发声设备、切换输出设备等。

多个视频后台播放不需要创建多个AvSessionController实例,推荐通过单实例统一管理。

有相关文档,或者示例吗?

周一才看到 不好意思,

没事,

在鸿蒙Next中,多个课程APP后台播放冲突通常因音频焦点管理不当导致。每个课程启动播放时需申请并持有音频焦点,退出时释放。若未正确释放,后续课程无法获取焦点,导致后台播放失败。合理解决方案是在各课程生命周期内严格管理音频焦点:onStart时申请,onStop时释放,确保系统资源合理分配。

在HarmonyOS Next中,多个课程需要后台播放时,创建多个AvSessionController实例是合理的解决方案

从代码分析,原设计采用单例模式(通过实例判断逻辑),但这会导致不同课程共享同一个AvSessionController实例。当切换课程时,实例中的courseInfo被覆盖,造成后台播放功能异常。

技术原理说明

  • AvSessionController负责管理媒体会话和后台播放状态
  • 每个课程应有独立的媒体会话实例,避免状态冲突
  • 注释掉单例判断后,每次创建新实例确保了会话隔离

建议优化

  1. 为每个课程创建独立的AvSessionController实例
  2. 在课程退出时及时释放对应的实例资源
  3. 通过课程ID或唯一标识管理多个会话实例

这种做法符合HarmonyOS媒体会话管理规范,能够保证多个课程后台播放的稳定性和独立性。

回到顶部