HarmonyOS开发案例:【音乐播放器】

电子说

1.3w人已加入

描述

介绍

使用ArkTS语言实现了一个简易的音乐播放器应用,主要包含以下功能:

  1. 播放应用中的音频资源文件,并可进行上一曲、下一曲、播放、暂停、切换播放模式(顺序播放、单曲循环、随机播放)等操作。
  2. 结合后台任务管理模块,实现熄屏后继续播放音频。

OpenHarmony

相关概念

  • [AVPlayer]:AVPlayer主要工作是将Audio/Video媒体资源转码为可供渲染的图像和可听见的音频模拟信号,并通过输出设备进行播放,同时对播放任务进行管理,包括开始播放、暂停播放、停止播放、释放资源、设置音量、跳转播放位置、获取轨道信息等功能控制。
  • [后台任务管理]:针对应用或业务模块处于后台(无可见界面)时,有需要继续执行或者后续执行的业务,可基于业务类型,申请短时任务延迟挂起或者长时任务避免进入挂起状态;如后台播放音乐可使用长时任务避免进入挂起状态。
  • 鸿蒙开发指导文档:[gitee.com/li-shizhen-skin/harmony-os/blob/master/README.md]

约束与限制

  1. 本篇Codelab部分能力依赖于系统API,需下载full-SDK并替换DevEco Studio自动下载的public-SDK。具体操作可参考指南[《如何替换full-SDK》]。
  2. 本篇Codelab使用的部分API仅系统应用可用,需要提升应用等级。

环境搭建

软件要求

  • [DevEco Studio]版本:DevEco Studio 3.1 Release。
  • OpenHarmony SDK版本:API version 9。

硬件要求

  • 开发板类型:[润和RK3568开发板]。
  • OpenHarmony系统:3.2 Release。

环境搭建

完成本篇Codelab我们首先要完成开发环境的搭建,本示例以RK3568开发板为例,参照以下步骤进行:

  1. [获取OpenHarmony系统版本]:标准系统解决方案(二进制)。以3.2 Release版本为例:
    OpenHarmony
  2. 搭建烧录环境。
    1. [完成DevEco Device Tool的安装]
    2. [完成RK3568开发板的烧录]
  3. 搭建开发环境。
    1. 开始前请参考[工具准备],完成DevEco Studio的安装和开发环境配置。
    2. 开发环境配置完成后,请参考[使用工程向导]创建工程(模板选择“Empty Ability”)。
    3. 工程创建完成后,选择使用[真机进行调测]。
    4. HarmonyOS与OpenHarmony鸿蒙文档籽料:mau123789是v直接拿

OpenHarmony

代码结构解读

本篇Codelab只对核心代码进行讲解,对于完整代码,我们会在gitee中提供。

├──entry/src/main/ets// 代码区│ ├──common│ │ ├──constants│ │ │ └──CommonConstants.ets// 公共常量│ │ ├──model│ │ │ └──PlayBarModel// 播放栏数据模型│ │ └──utils│ │ ├──AvSessionUtil.ets// 媒体会话工具类│ │ ├──BackgroundTaskUtil.ets// 后台任务工具类│ │ ├──CommonUtil.ets// 公共工具类│ │ ├──GlobalContext.ets// 公共工具类│ │ ├──Logger.ets// 日志类│ │ └──ResourceManagerUtil.ets// 资源管理工具类│ ├──controller│ │ ├──AudioPlayerController.ets// 音乐播放器控制器│ │ └──PlayBarController.ets// 播放栏控制器│ ├──entryability│ │ └──EntryAbility.ets// 程序入口类│ ├──pages│ │ ├──AudioStartUp.ets// 启动页│ │ ├──MusicList.ets// 歌单页│ │ └──Play.ets// 播放页│ ├──view│ │ ├──MusicCardView.ets// 播放卡片模块│ │ ├──MusicView.ets// 歌单音乐模块│ │ ├──PlayBarView.ets// 播放控制模块│ │ ├──PlayListDialogView.ets// 弹窗模块│ │ ├──PlayListMusicView.ets// 弹窗音乐模块│ │ └──ProgressView.ets// 播放页│ └──viewmodel│ ├──MusicItem.ets// 音乐类│ └──MusicViewModel.ets// 歌单音乐模型└──entry/src/main/resources// 应用资源目录

实现音频播放

本案例使用播放管理类AVPlayer,实现应用内音频资源的播放,并可进行上一曲、下一曲、播放、暂停、切换播放模式(顺序播放、单曲循环、随机播放)等操作。

OpenHarmony

使用AVPlayer播放器,需要先创建一个AVPlayer实例。在AudioPlayerController中使用createAVPlayer方法完成音频播放实例的创建。

// AudioPlayerController.etsinitAudioPlayer(){ media.createAVPlayer((error, video) = > {if(video ===undefined) {this.avPlayer = video; Logger.error(TAG,`createAVPlayer fail, error:${error}`); }else{this.avPlayer = video; Logger.info(TAG,'createAVPlayer success'); } }); }

根据业务需要设置监听事件,搭配播放场景使用。

// AudioPlayerController.ets// 注册AVPlayer回调函数setEventCallBack(){ ...// 状态变更回调函数。this.avPlayer.on('stateChange',async(state) = > { ...switch(state) {caseStateEvent.IDLE:// 调用reset成功后触发此状态。...caseStateEvent.INITIALIZED:// 设置播放源触发此状态。...caseStateEvent.PREPARED: ...caseStateEvent.PLAYING: ...caseStateEvent.COMPLETED: ...default: Logger.error('unknown state: '+ state);break; } }) }

设置音频资源,AVPlayer进入initialized状态。在initialized状态回调中,调用prepare方法,准备播放,AVPlayer进入prepared状态。

// AudioPlayerController.etsasyncplay(src: media.AVFileDescriptor, seekTo:number){ Logger.info(TAG,'audioPlayer play'); ...// 设置播放源this.avPlayer.fdSrc = src; }setEventCallBack(){ ...this.avPlayer.on('stateChange',async(state) = > { ...switch(state) { ...caseStateEvent.INITIALIZED:// 设置播放源后进入initialized状态Logger.info(TAG,'state initialized called');this.avPlayerState = PlayerState.INITIALIZED;this.avPlayer.prepare().then(() = > { Logger.info(TAG,'prepare success'); }, (err) = > { Logger.error(TAG,`prepare failed,error message is:${err.message}`); })break; ... } }) }

AVPlayer进入prepared状态,可进行音频播控操作。包括播放play()、跳转至指定位置播放seek()、暂停pause()、停止stop()等操作。

// AudioPlayerController.etssetEventCallBack(){ ...this.avPlayer.on('stateChange',async(state) = > { ...switch(state) { ...caseStateEvent.PREPARED: Logger.info(TAG,'state prepared called');this.avPlayer.play();break; ... } }) }

切换歌曲播放时,需调用reset()重置资源。此时AVPlayer重新进入idle状态,允许更换资源。

// AudioPlayerController.etsasyncplay(src: media.AVFileDescriptor, seekTo:number){ ...if(this.avPlayerState === PlayerState.INITIALIZED) {awaitthis.avPlayer.reset(); Logger.info(TAG,'play reset success'); } ... }

OpenHarmony说明:只能在initialized/prepared/playing/paused/complete/stopped/error状态调用reset()。

调用release()销毁实例,AVPlayer进入released状态,退出播放。

// AudioPlayerController.etsasyncrelease(){ Logger.info(TAG,'audioPlayer release');if(typeof(this.avPlayer) !=='undefined') {if(this.timeId === CommonConstants.DEFAULT_TIME_ID) {clearInterval(this.timeId); }awaitthis.avPlayer.release();this.avPlayer =undefined; } }

实现熄屏后播放

通过后台任务管理模块申请长时任务,可避免设备熄屏后,应用进入挂起状态。

OpenHarmony

首先在module.json5文件中配置长时任务权限和后台模式类型。

"module": { ..."abilities": [ { ..."backgroundModes": ["audioPlayback"], ... } ],"requestPermissions": [ {"name":"ohos.permission.KEEP_BACKGROUND_RUNNING"} ], }

在播放音乐时,申请长时任务。这样在应用切换至后台或设备熄屏后,仍可以继续播放音乐。

// BackgroundTaskUtil.etsimportwantAgentfrom'@ohos.app.ability.wantAgent';importbackgroundTaskManagerfrom'@ohos.resourceschedule.backgroundTaskManager'; ...exportclassBackgroundTaskUtil{ ...publicstaticstartContinuousTask(context: Context){if(context ===undefined) { Logger.info(TAG,'startContinuousTask fail,context is empty.');return; }letwantAgentInfo = {// 点击通知后需要执行的动作wants: [ {bundleName: CommonConstants.BUNDLE_NAME,abilityName: CommonConstants.ABILITY_NAME } ],// 单击通知后的动作类型operationType: wantAgent.OperationType.START_ABILITY,// 用户定义的私有属性requestCode: CommonConstants.BACKGROUND_REQUEST_CODE }aswantAgent.WantAgentInfo;// 通过WanAgent模块的方法获取WanAgent对象wantAgent.getWantAgent(wantAgentInfo).then((wantAgentObj) = > {try{ backgroundTaskManager.startBackgroundRunning(context, backgroundTaskManager.BackgroundMode.AUDIO_PLAYBACK, wantAgentObj).then(() = > { Logger.info(TAG,'startBackgroundRunning succeeded'); }).catch((err:Error) = > { Logger.error(TAG,'startBackgroundRunning failed, Cause: '+JSON.stringify(err)); }); }catch(error) { Logger.error(TAG,`startBackgroundRunning failed. code is${error.code}message is${error.message}`); } }); } ... }

暂停音乐播放,结束长时任务。

// BackgroundTaskUtil.etsimportwantAgentfrom'@ohos.app.ability.wantAgent';importbackgroundTaskManagerfrom'@ohos.resourceschedule.backgroundTaskManager'; ...exportclassBackgroundTaskUtil{ ...publicstaticstopContinuousTask(context: Context){if(context ===undefined) { Logger.info(TAG,'stopContinuousTask fail,context is empty.');return; }try{ backgroundTaskManager.stopBackgroundRunning(context).then(() = > { Logger.info(TAG,'stopBackgroundRunning succeeded'); }).catch((err:Error) = > { Logger.error(TAG,'stopBackgroundRunning failed Cause: '+JSON.stringify(err)); }); }catch(error) { Logger.error(TAG,`stopBackgroundRunning failed. code is${error.code}message is${error.message}`); } } }

审核编辑 黄宇

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表德赢Vwin官网 网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分