AudioRenderer适合录音
AVPlayer:简单的本地单曲播放
MP3文件放置的地方
import media from '@ohos.multimedia.media'
import common from '@ohos.app.ability.common';
@Entry
@Component
struct Index {
//第1步:
avPlayer:media.AVPlayer = null
async onPageShow(){
//第2步:异步创建播放器对象
this.avPlayer = await media.createAVPlayer()
//第3步:设置回调函数,监听对象的状态变化,
this.setAVPlayerCallback();
}
build() {
Row() {
Column() {
Button('播放本地歌曲').onClick(()=>{
this.playLocalMusic()
})
}
.height('100%')
}
}
async playLocalMusic(){
//第4步:获取上下文
const context = getContext(this) as common.UIAbilityContext
//第5步:获取文件描述符
const rawFieldFd = await context.resourceManager.getRawFd("kn.mp3")
//第6步:fdSrc是本地文件描述符,
if(this.avPlayer) {
this.avPlayer.fdSrc = rawFieldFd
}
}
setAVPlayerCallback() {
// seek操作结果回调函数
this.avPlayer.on('seekDone', (seekDoneTime: number) => {
console.info(`AVPlayer seek succeeded, seek time is ${seekDoneTime}`);
})
// error回调监听函数,当avPlayer在操作过程中出现错误时调用 reset接口触发重置流程
this.avPlayer.on('error', (err) => {
console.error(`Invoke avPlayer failed, code is ${err.code}, message is ${err.message}`);
this.avPlayer.reset(); // 调用reset重置资源,触发idle状态
})
// 状态机变化回调函数
this.avPlayer.on('stateChange', async (state: string, reason: media.StateChangeReason) => {
switch (state) {
case 'idle': // 成功调用reset接口后触发该状态机上报
console.info('AVPlayer state idle called.');
this.avPlayer.release(); // 调用release接口销毁实例对象
break;
case 'initialized': // avplayer 设置播放源后触发该状态上报
console.info('AVPlayer state initialized called.');
this.avPlayer.prepare();
break;
case 'prepared': // prepare调用成功后上报该状态机
console.info('AVPlayer state prepared called.');
this.avPlayer.play(); // 调用播放接口开始播放
break;
case 'playing': // play成功调用后触发该状态机上报
console.info('AVPlayer state playing called.');
break;
case 'paused': // pause成功调用后触发该状态机上报
console.info('AVPlayer state paused called.');
this.avPlayer.play(); // 再次播放接口开始播放
break;
case 'completed': // 播放结束后触发该状态机上报
console.info('AVPlayer state completed called.');
this.avPlayer.stop(); //调用播放结束接口
break;
case 'stopped': // stop接口成功调用后触发该状态机上报
console.info('AVPlayer state stopped called.');
this.avPlayer.reset(); // 调用reset接口初始化avplayer状态
break;
case 'released':
console.info('AVPlayer state released called.');
break;
default:
console.info('AVPlayer state unknown called.');
break;
}
})
}
}
AVPlayer:播放网络歌曲
播放网络歌曲,需要增加网络访问权限
import media from '@ohos.multimedia.media'
import common from '@ohos.app.ability.common';
@Entry
@Component
struct Index {
//第1步:
avPlayer:media.AVPlayer = null
async onPageShow(){
//第2步:异步创建播放器对象
this.avPlayer = await media.createAVPlayer()
//第3步:设置回调函数,监听对象的状态变化,
this.setAVPlayerCallback();
}
build() {
Row() {
Column() {
Button('播放网络歌曲').onClick(()=>{
this.playNetMusic()
})
}
.height('100%')
}
}
/**
* 播放网络歌曲
*/
playNetMusic(){
const url = 'https://www.yyq.cn/audio/audiomp3/0/16/8f6/0168f69e0e3a0c5c2638c366d53908a5.mp3'
this.avPlayer.url = url
}
setAVPlayerCallback() {
// seek操作结果回调函数
this.avPlayer.on('seekDone', (seekDoneTime: number) => {
console.info(`AVPlayer seek succeeded, seek time is ${seekDoneTime}`);
})
// error回调监听函数,当avPlayer在操作过程中出现错误时调用 reset接口触发重置流程
this.avPlayer.on('error', (err) => {
console.error(`Invoke avPlayer failed, code is ${err.code}, message is ${err.message}`);
this.avPlayer.reset(); // 调用reset重置资源,触发idle状态
})
// 状态机变化回调函数
this.avPlayer.on('stateChange', async (state: string, reason: media.StateChangeReason) => {
switch (state) {
case 'idle': // 成功调用reset接口后触发该状态机上报
console.info('AVPlayer state idle called.');
this.avPlayer.release(); // 调用release接口销毁实例对象
break;
case 'initialized': // avplayer 设置播放源后触发该状态上报
console.info('AVPlayer state initialized called.');
this.avPlayer.prepare();
break;
case 'prepared': // prepare调用成功后上报该状态机
console.info('AVPlayer state prepared called.');
this.avPlayer.play(); // 调用播放接口开始播放
break;
case 'playing': // play成功调用后触发该状态机上报
console.info('AVPlayer state playing called.');
break;
case 'paused': // pause成功调用后触发该状态机上报
console.info('AVPlayer state paused called.');
this.avPlayer.play(); // 再次播放接口开始播放
break;
case 'completed': // 播放结束后触发该状态机上报
console.info('AVPlayer state completed called.');
this.avPlayer.stop(); //调用播放结束接口
break;
case 'stopped': // stop接口成功调用后触发该状态机上报
console.info('AVPlayer state stopped called.');
this.avPlayer.reset(); // 调用reset接口初始化avplayer状态
break;
case 'released':
console.info('AVPlayer state released called.');
break;
default:
console.info('AVPlayer state unknown called.');
break;
}
})
}
}
鸿蒙网络访问 Axios的使用
首先安装ohpm,如何查找phpm库安装路径
ohpm安装指南
Axios是第三方库,需要安装。
/**
* 获取网络歌曲数据,封装到对应的bean对象中
*/
async getMusicData(){
//发送网络请求,获取数据
const resp = await axios({
method: 'get',
url: 'https://www.yyq.cn/api/getPlayData?playid=4926%2C4925%2C4924%2C4923%2C4922%2C4921%2C4920%2C4919%2C4918%2C4917%2C4916%2C4915&typeid=3'
})
if(resp.status === 200){
this.songs = resp.data
this.songs.forEach((song) =>{
song.img = song.img
song.src = 'https://www.yyq.cn/' + song.src
console.log('getData',song.img, song.src);
})
}
}
import media from '@ohos.multimedia.media'
import emitter from '@ohos.events.emitter'
import { songItemType } from '../models/music'
import { PlayStateType } from '../models/playState'
import { EmitEventType } from '../constants/EventConstants'
/**
* 播放工具类,我们需要把这个工具类同步到界面,这就需要线程通信。
* 鸿蒙中的线程通信,叫Emitter(发布订阅)和worker(并行计算)。
* 我们这里用Emitter,发布者是播放器,订阅者是使用信息的页面(可以有多个订阅者)
*/
export class AvPlayerUtils{
static player: media.AVPlayer | null = null
//记录播放的音乐的总时长,可以从播放器中获取,
static duration: number = 0
//当前的播放的时长
static time: number = 0
//当前歌曲的播放状态,
static isPlay: boolean = false
//播放模式:自动播放,单曲循环,随机播放,默认是自动播放
static playMode: 'auto' | 'repeat' | 'random' = 'auto'
//歌曲名称,作者,图片等等
//定义播放歌曲列表
static playList: songItemType[] = []
//当前的播放索引
static playIndex: number = -1
//在EntryAbility的onWindowStageCreate(){}中初始化,就不需要再所有的页面中初始化了
// 注意:EntryAbility的后缀名要改成.ets
// 初始化播放对象,可以在页面显示的时候初始化
static async init(){
//创建播放对象
this.player = await media.createAVPlayer()
this.player.on('stateChange', (state)=>{
switch(state){
case 'initialized':
this.player.prepare()
break;
case 'prepared':
this.player.play()
//更新播放状态
this.isPlay = true
break
}
})
//监听音乐的总时长
this.player.on('durationUpdate',(duration)=>{
this.duration = duration
console.log('logData', this.duration)
})
//监听播放时长
this.player.on('timeUpdate',(time)=>{
this.time = time
console.log('logData', this.time, '发送数据')
//定义一个数据,发送通知出去
// 收集要通知的信息
const playState:PlayStateType = {
img:this.playList[this.playIndex].img,
name:this.playList[this.playIndex].name,
author:this.playList[this.playIndex].author,
url: this.playList[this.playIndex].url,
playIndex: this.playIndex,
time: this.time,
duration:this.duration,
isPlay:this.isPlay,
playMode:this.playMode,
playList:this.playList
}
//发布通知
this.updateState(playState)
})
}
//单曲指定播放,
//播放器播放状态无法更替URL,需要把播放器置为idle(可以调用reset())状态
static playSingle(song: songItemType){
// 判断是不是列表中的歌曲
const isList = this.playList.some((item:songItemType)=>item.id === song.id)
// 如果是歌曲列表中的歌曲
if(isList){
// 是不是正在播放的
if(this.player.url === song.url){
// 重新播放(切换当前播放索引的歌曲)
this.changePlay()
}else{
// 切换歌曲(更新播放索引切换歌曲)
this.playIndex = this.playList.findIndex((item:songItemType)=>item.id===song.id)
this.changePlay()
}
}else{
// 添加到播放列表中,再进行播放
//为了防止playList是空,每播一首歌就加入清单
this.playList.unshift(song)
this.playIndex = 0
this.changePlay()
}
}
/**
* 切换播放
*/
static async changePlay(){
//重置播放器状态,才能重新设置url
await this.player.reset()
//需要重置播放器数据
this.duration = 0
this.time = 0
//为了防止playList是空,每播一首歌就加入清单
this.player.url = this.playList[this.playIndex].url
}
//发布通知,订阅者就可以得到数据
// 更新歌曲信息至页面
static updateState(playState: PlayStateType) {
emitter.emit({
eventId: EmitEventType.UPDATE_STATE
}, {
data: {
playStateStr: JSON.stringify(playState)
}
})
}
}
播放器的seek要与seeDone连用