电子说
使用ArkTS语言实现了一个简易的音乐播放器应用,主要包含以下功能:
gitee.com/li-shizhen-skin/harmony-os/blob/master/README.md
]完成本篇Codelab我们首先要完成开发环境的搭建,本示例以RK3568开发板为例,参照以下步骤进行:
HarmonyOS与OpenHarmony鸿蒙文档籽料:mau123789是v直接拿
本篇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,实现应用内音频资源的播放,并可进行上一曲、下一曲、播放、暂停、切换播放模式(顺序播放、单曲循环、随机播放)等操作。
使用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'); } ... }
说明:只能在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; } }
通过后台任务管理模块申请长时任务,可避免设备熄屏后,应用进入挂起状态。
首先在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}`); } } }
审核编辑 黄宇
全部0条评论
快来发表一下你的评论吧 !