当前位置: 首页 > news >正文

《悬浮窗效果》三、Interface_AVPlayer使用指南

HarmonyOS Interface (AVPlayer) 使用指南:从入门到实战

摘要:AVPlayer是 HarmonyOS 媒体播放的核心接口,支持音频和视频的端到端播放。本文基于 HarmonyOS NEXT开发实践,系统讲解AVPlayer的状态机模型、完整播放流程、资源加载方式和控制方法,帮助开发者快速实现音频播放功能。


效果

一、AVPlayer 概述

AVPlayer位于@kit.MediaKit模块的media命名空间下,是 HarmonyOS 推荐的媒体播放组件。相比旧版PlayerAVPlayer提供了更完善的状态机管理和更丰富的功能支持。

1.1 导入方式

import{media}from'@kit.MediaKit';

1.2 支持的播放源

播放源类型说明设置方式
fdSrc本地文件描述符(rawfile资源)avPlayer.fdSrc = { fd, offset, length }
url网络URL地址avPlayer.url = 'https://...'
dataSrc内存数据流avPlayer.dataSrc = dataSrcDescriptor

二、状态机模型

AVPlayer采用有限状态机设计,所有操作必须在正确的状态下调用。理解状态机是使用AVPlayer的关键。

2.1 状态流转图

┌──────────────────────────────────────────────┐ │ │ ▼ │ [idle] ──setPlaySource──▶ [initialized] ──prepare──▶ [prepared] │ ▲ │ │ │ ▼ │ │ reset() [released] ◄──release()── [stopped] ◄──play()──▶[playing] │ ▲ ▲ │ │ │ │ ▼ │ │ stop() [paused] │ │ │ │ │ │ │ play()│ │ │ │ │ │ │ ▼ │ │ │ [completed]───────┘ │ │ │ │ │ │ (循环播放) │ │ ▼ │ └────────────────────── [prepared] │ └── error ──▶ [error] ──reset()──▶ [idle]

2.2 各状态说明

状态触发条件可执行操作
idle初始状态 / reset后 / error后release()
initialized设置播放源后(fdSrc/url)prepare()
preparedprepare成功后play()seek()setPlaybackSpeed()
playingplay成功后pause()stop()seek()
pausedpause成功后play()stop()seek()
completed播放结束stop()seek()
stoppedstop后prepare()(循环播放)
releasedrelease后不可再操作,实例已销毁
error操作出错reset()回到 idle

三、完整播放流程

3.1 创建 AVPlayer 实例

letavPlayer:media.AVPlayer=awaitmedia.createAVPlayer();

3.2 注册回调函数

必须在设置播放源之前注册回调,否则可能错过状态变化通知。

// 状态机变化回调(最核心的回调)avPlayer.on('stateChange',async(state:string,reason:media.StateChangeReason)=>{switch(state){case'idle':// idle状态:reset后触发,可release释放资源avPlayer.release();break;case'initialized':// initialized状态:设置播放源后触发avPlayer.prepare();// 准备播放break;case'prepared':// prepared状态:准备完成,可以播放avPlayer.play();// 开始播放break;case'playing':// 正在播放break;case'paused':// 已暂停break;case'completed':// 播放完成avPlayer.stop();// 停止播放break;case'stopped':// 已停止,可重新prepare循环播放avPlayer.prepare();break;case'released':// 已释放资源break;}});// seek操作完成回调avPlayer.on('seekDone',(seekDoneTime:number)=>{console.info(`seek完成,当前位置:${seekDoneTime}ms`);});// 错误回调avPlayer.on('error',(err)=>{console.error(`播放错误: code=${err.code}, message=${err.message}`);avPlayer.reset();// 出错后调用reset回到idle状态});

3.3 设置播放源

方式一:播放 rawfile 资源(推荐用于本地音频)
import{common}from'@kit.AbilityKit';asyncfunctionplayRawfileAudio(ctx:Context){letavPlayer=awaitmedia.createAVPlayer();// 注册回调(省略,见3.2)registerCallbacks(avPlayer);// 获取rawfile资源letcontext=ctxascommon.UIAbilityContext;letfileDescriptor=awaitcontext.resourceManager.getRawFd('audio.mp3');letavFileDescriptor:media.AVFileDescriptor={fd:fileDescriptor.fd,offset:fileDescriptor.offset,length:fileDescriptor.length};// 设置播放源 → 触发 initialized 状态avPlayer.fdSrc=avFileDescriptor;}
方式二:播放网络URL
asyncfunctionplayUrlAudio(){letavPlayer=awaitmedia.createAVPlayer();// 注册回调(省略,见3.2)registerCallbacks(avPlayer);// 设置URL → 触发 initialized 状态avPlayer.url='https://example.com/audio.mp3';}

3.4 播放控制

// 播放avPlayer.play();// 暂停avPlayer.pause();// 停止avPlayer.stop();// 跳转(单位:毫秒)avPlayer.seek(30000);// 跳转到30秒// 释放资源avPlayer.release();// 重置(回到idle状态)avPlayer.reset();

四、完整示例:音频播放服务

以下示例封装了一个完整的音频播放服务类,支持播放/暂停切换、错误处理和资源管理。

4.1 音频播放服务类

import{media}from'@kit.MediaKit';import{common}from'@kit.AbilityKit';import{audio}from'@kit.AudioKit';import{hilog}from'@kit.PerformanceAnalysisKit';exportclassAudioPlayerService{privateavPlayer?:media.AVPlayer=undefined;privatecurrentState:string='';publicstaticinstance:AudioPlayerService=newAudioPlayerService();/** * 注册AVPlayer回调函数 */privateregisterCallbacks(avPlayer:media.AVPlayer):void{// 状态机变化回调avPlayer.on('stateChange',async(state:string)=>{hilog.info(0x0000,'AudioPlayer','状态变化: %{public}s',state);this.currentState=state;switch(state){case'idle':// reset后到达idle,释放资源avPlayer.release();break;case'initialized':// 设置播放源后到达,配置音频参数并准备avPlayer.audioRendererInfo={usage:audio.StreamUsage.STREAM_USAGE_MUSIC,rendererFlags:0};avPlayer.prepare();break;case'prepared':// 准备完成,开始播放avPlayer.play();break;case'playing':hilog.info(0x0000,'AudioPlayer','正在播放');break;case'paused':hilog.info(0x0000,'AudioPlayer','已暂停');break;case'completed':// 播放完成,停止后可重新prepare实现循环avPlayer.stop();break;case'stopped':// 停止后重新准备,实现循环播放avPlayer.prepare();break;case'released':hilog.info(0x0000,'AudioPlayer','资源已释放');break;}});// seek完成回调avPlayer.on('seekDone',(seekDoneTime:number)=>{hilog.info(0x0000,'AudioPlayer','seek完成: %{public}d',seekDoneTime);});// 错误回调avPlayer.on('error',(err)=>{hilog.error(0x0000,'AudioPlayer','播放错误: code=%{public}d, message=%{public}s',err.code,err.message);avPlayer.reset();});}/** * 播放rawfile中的音频资源 */asyncplayFromRawfile(ctx:Context,resourceName:string):Promise<void>{letavPlayer=awaitmedia.createAVPlayer();this.registerCallbacks(avPlayer);letcontext=ctxascommon.UIAbilityContext;letfileDescriptor=awaitcontext.resourceManager.getRawFd(resourceName);letavFileDescriptor:media.AVFileDescriptor={fd:fileDescriptor.fd,offset:fileDescriptor.offset,length:fileDescriptor.length};avPlayer.fdSrc=avFileDescriptor;this.avPlayer=avPlayer;}/** * 切换播放/暂停 */togglePlayPause(ctx:Context,resourceName:string):void{if(this.avPlayer===undefined){// 首次播放,创建播放器this.playFromRawfile(ctx,resourceName);}elseif(this.currentState==='playing'){this.avPlayer.pause();}else{this.avPlayer.play();}}/** * 获取当前状态 */getState():string{returnthis.currentState;}}

4.2 在组件中使用

import{AudioPlayerService}from'../utils/AudioPlayerService';@Entry@Componentstruct AudioPage{@LocalisPlaying:boolean=false;privatectx?:Context=this.getUIContext().getHostContext();build(){Column({space:20}){Text('AVPlayer 音频播放示例').fontSize(20).fontWeight(FontWeight.Bold)Text(this.isPlaying?'正在播放...':'已暂停').fontSize(16).fontColor(this.isPlaying?'#4CAF50':'#999999')Button(this.isPlaying?'暂停':'播放').fontSize(16).onClick(()=>{AudioPlayerService.instance.togglePlayPause(this.ctx!,'sample.wav');this.isPlaying=!this.isPlaying;})}.width('100%').height('100%').justifyContent(FlexAlign.Center)}}

五、音频渲染参数配置

5.1 audioRendererInfo

initialized状态下设置音频渲染参数:

avPlayer.audioRendererInfo={// 音频流使用类型usage:audio.StreamUsage.STREAM_USAGE_MUSIC,// 音乐// rendererFlags: 0 // 音频渲染器标志};

常用 StreamUsage 类型:

类型说明
STREAM_USAGE_MUSIC音乐播放
STREAM_USAGE_VOICE_COMMUNICATION语音通话
STREAM_USAGE_NOTIFICATION通知提示音
STREAM_USAGE_ALARM闹钟
STREAM_USAGE_GAME游戏音效

5.2 其他播放参数

// 设置音量(0.0 ~ 1.0)avPlayer.volume=0.8;// 设置播放速度(0.5x ~ 2.0x)avPlayer.setPlaybackSpeed(1.5);// 设置循环模式(需要手动在completed状态处理)// AVPlayer本身不直接支持循环,需在stateChange回调中实现

六、开发要点与最佳实践

6.1 回调注册时机

正确顺序: 1. createAVPlayer() → 创建实例 2. on('stateChange') → 注册状态回调 ★ 必须在设置播放源之前 3. on('error') → 注册错误回调 ★ 必须在设置播放源之前 4. fdSrc / url → 设置播放源(触发状态机流转) 错误顺序: 1. createAVPlayer() 2. fdSrc → ✗ 可能错过 initialized 状态 3. on('stateChange') → ✗ 已来不及接收状态变化

6.2 错误处理策略

avPlayer.on('error',(err)=>{// 1. 记录错误日志hilog.error(0x0000,'AVPlayer','错误: %{public}s',JSON.stringify(err));// 2. 调用reset回到idle状态avPlayer.reset();// 3. 在idle状态的stateChange回调中release释放资源});

6.3 资源释放

// 正确的资源释放流程avPlayer.stop();// 先停止// → stopped 状态// 在 stateChange 的 idle 回调中:avPlayer.release();// 释放资源// → released 状态,实例不可再使用

6.4 循环播放实现

AVPlayer不直接支持循环播放,需要在状态机回调中手动实现:

avPlayer.on('stateChange',async(state:string)=>{if(state==='completed'){avPlayer.stop();// 播放完成后停止// → stopped 状态}if(state==='stopped'){avPlayer.prepare();// 停止后重新准备// → prepared 状态 → play() 自动播放}});

6.5 单例模式管理

推荐使用单例模式管理 AVPlayer 实例,避免创建多个播放器:

exportclassAudioPlayerService{publicstaticinstance:AudioPlayerService=newAudioPlayerService();privateavPlayer?:media.AVPlayer;// 确保全局只有一个播放器实例}

七、AVPlayer 回调事件速查表

事件名说明回调参数
stateChange状态机变化(state: string, reason: StateChangeReason)
seekDoneseek操作完成(seekDoneTime: number)
error操作出错(err: BusinessError)
timeUpdate播放时间更新(time: number)
durationUpdate总时长更新(duration: number)
bufferingUpdate缓冲更新(infoType: BufferingInfoType, value: number)
audioInterruptBegin音频焦点被抢占开始()
audioInterruptEnd音频焦点恢复()

八、总结

AVPlayer是 HarmonyOS 媒体播放的核心组件,掌握以下要点即可应对大部分音频播放场景:

  1. 状态机模型:理解 idle → initialized → prepared → playing → paused → completed → stopped 的完整流转
  2. 回调注册:必须在设置播放源之前注册stateChangeerror回调
  3. 播放源设置:支持 fdSrc(本地资源)、url(网络地址)、dataSrc(内存数据)
  4. 播放控制:play、pause、stop、seek、release、reset
  5. 错误处理:error 状态下调用 reset 回到 idle,再 release 释放资源
  6. 循环播放:在 completed → stop → prepare 链路中实现

相关文档:

  • Interface (Window) 使用指南
  • Interface (WindowStage) 使用指南
  • 简约风格悬浮窗效果案例指南
  • ArkTS 悬浮窗开发避坑指南
http://www.gsyq.cn/news/1607635.html

相关文章:

  • Burp-Hunter插件实战:自动化Web漏洞挖掘与Burp Suite协同测试
  • 吃灰板子利旧系列--ESP32-S3养ESP官方虾ESP-Claw
  • 本体论从入门到实战-08.本体模型驱动工程:从分析到设计与实现
  • Qt6.5.2 集成官方MQTT模块:从源码编译到项目部署的CMake实践指南
  • 目标检测评估进阶——从AP到mAP的算法实现与实战解析
  • 跨城企业搬迁的物流工程方案——从分档运输到两城协同到业务恢复的执行逻辑
  • Shiro-550漏洞复现:Java反序列化与权限框架安全实践
  • 2026年苏州玻璃间隔纸公司实测:防潮防粘,平整度极佳
  • 怎样高效管理Switch存储:实用NAND操作手册
  • 【机器学习实战】三大聚类算法DBSCAN、K-means、Mean Shift核心差异与场景选型指南
  • XHS-Downloader:3分钟掌握小红书无水印下载的终极解决方案
  • 老旧电视重获新生:MyTV-Android开源直播应用的完整解决方案
  • Sesame-TK:蚂蚁森林自动化助手终极指南
  • 本地商家运营策划怎么选?慧多派运营策划部核心能力解析
  • SpringBoot与Quarkus对比:如何选择适合的框架
  • Playwright与MCP协议结合:打造低门槛UI自动化测试新方案
  • 从二叉树到四叉树:RFID标签防碰撞算法的演进与实战解析
  • 数模电路实战解析 —— 4. 特殊二极管选型与应用场景指南
  • 山西温泉酒店快装
  • CVE-2012-1823漏洞复现:PHP-CGI参数注入原理与Web安全实战
  • ChatGPT Function Calling深度解析(OpenAI官方未公开的调用时序与错误码映射表)
  • 计算机毕业计算机之党务活动记录系统
  • 大模型置信度校准:从幻觉分数到可执行决策
  • 【UE Niagara】从零构建:打造随风摇曳的蒲公英粒子特效
  • 致远OA文件上传漏洞深度解析:从原理到防御的Web安全实战
  • Halcon 19.11.0与VS2017 C#环境搭建:从零开始的工业视觉开发配置指南
  • 2026深度实测|两款主流AI编程工具完整对比,vibe coding实战差距一目了然
  • 护栏网采购怎么选?边坡、球场、锌钢护栏优质厂家实地甄选指南
  • Unity之无代码实现电影级镜头,Cinemachine插件进阶应用指南
  • ista1a标准,ista1a跌落测试是啥,ista1a跌落高度试验