1 关键字

MediaLibrary;音频;AudioPlayer;

2 问题描述

开发板:WGR

OH 版本:3.2.3.5

问题现象:通过MediaLibrary的getAllObject方法获取的FileAsset对象的uri地址值设置给AudioPlayer的src属性不能实现播放。

3 问题原因

3.1 正常机制

从MediLibrary中获取的音频文件能通过AudioPlayer进行播放。

3.2 异常机制

将MediaLibrary中获取的音频文件对应的FileAsset对象的uri地址值设置给AudioPlayer的src属性不能实现播放。

4 解决方案

通过FileAsset对象的open方法获取对应音频文件的fd(文件描述符),将获取的fd拼接上fd://组成uri,再将uri设置给AudioPlayer的src属性能够实现播放。

5 定位过程

1.在媒体库中创建音频文件,核心代码如下:

 createAudioFileAsset() {
    let mediaType = mediaLibrary.MediaType.AUDIO;
    let DIR_IMAGE = mediaLibrary.DirectoryType.DIR_AUDIO;
    const path = await this.iMediaLibrary.getPublicDirectory(DIR_IMAGE);
    console.info(`mediaTest:path:${path}`);
    this.iMediaLibrary.createAsset(mediaType, "audiotest.mp3", path)
    .then((result) => {
      console.info(`mediaTest:create fileAsset sucess:${JSON.stringify(result)}`);
    })
    .catch((e) => {
        console.info(`mediaTest:create fileAsset fail`)
    })
  }
​

这里仅创建了一个空的mp3文件,对应的文件目录:/storage/media/100/local/files/Audios/audiotest.mp3

2.将预先准备好的mp3文件通过命令发送到媒体库中。

hdc_std  file send  D:\audiotest.mp3  /storage/media/100/local/files/Audios/audiotest.mp3

3.获取之前放置的mp3文件并进行播放,核心代码如下:

import mediaLibrary from '@ohos.multimedia.mediaLibrary';
import media from '@ohos.multimedia.media';
​
class MediaService {
  private iMediaLibrary: mediaLibrary.MediaLibrary;
  private audioPlayer: media.AudioPlayer;
  ...
  ...
  createMediaPlayer() {
    this.audioPlayer = media.createAudioPlayer();
    this.audioPlayer.loop = true; //设置循环播放
    this.registerListenerForAudioPlayer();
    console.info(`mediaTest:create audioPlayer success`);
  }
​
  registerListenerForAudioPlayer() {
    this.audioPlayer.on("dataLoad", () => {
      console.info(`mediaTest:data load success`);
      this.audioPlayer.play();
    })
    this.audioPlayer.on("play", () => {
      console.info(`mediaTest:play success`);
    })
    this.audioPlayer.on("pause", () => {
      console.info(`mediaTest:pause successs`);
    })
    this.audioPlayer.on("finish", () => {
      console.info(`mediaTest:finish success`)
    })
  }
​
  async getAudioSource() {
    let fileAssetResult = await this.iMediaLibrary.getFileAssets({
      selections: mediaLibrary.FileKey.MEDIA_TYPE + '= ?',
      selectionArgs: [mediaLibrary.MediaType.AUDIO.toString()],
    });
    console.info(`mediaTest:getfileAssets success:${JSON.stringify(fileAssetResult)}`);
    let fileAssetArray = await fileAssetResult.getAllObject();
    for (let i = 0;i < fileAssetArray.length; i++) {
      console.info(`mediaTest:getAllObject success:${JSON.stringify(fileAssetArray[i].uri)}`);
    }
​
    let path = fileAssetArray[0].uri; //获取数组中第一个音频文件的uri
    this.audioPlayer.src = path;
  }
  ...
  ...
}
​
let mediaService: MediaService = new MediaService();
​
export default mediaService;

在WGR上运行后无法播放之前放置的mp3文件,且没有触发在AudioPlayer注册的回调函数。

打印日志:

08-02 10:04:44.283  9060  9060 I A0fefe/JsApp: mediaTest:getfileAssets success:{}
08-02 10:04:44.284  9060  9060 I A0fefe/JsApp: mediaTest:getAllObject success:"datashare:///media/audio/16"
​

4.在sdk中查看AudioPlayer的src属性,发现AudioPlayer仅支持播放fd://xx、file://xx、http://xx或者https://xx四种路径类型的音频文件。

5.尝试使用fd://路径类型播放,更改上述部分代码如下:

async getAudioSource(){
   console.info(`mediaTest:getfile uri start:${JSON.stringify(this.iMediaLibrary)}`);
   let fileAssetResult=await this.iMediaLibrary.getFileAssets({
         selections: mediaLibrary.FileKey.MEDIA_TYPE + '= ?',
         selectionArgs: [mediaLibrary.MediaType.AUDIO.toString()],
          });
   console.info(`mediaTest:getfileAssets success:${JSON.stringify(fileAssetResult)}`);
   let fileAssetArray=await fileAssetResult.getAllObject();
   for(let i=0;i<fileAssetArray.length;i++){
     console.info(`mediaTest:getAllObject success:${JSON.stringify(fileAssetArray[i].uri)}`);
   }
   let fd=await fileAssetArray[0].open("rw");////获取数组中第一个音频文件的fd
   let path="fd://"+fd;
   console.info(`mediaTest:fileAsset fdpath:${path}`);
   this.audioPlayer.src=path;
  }

在WGR上再次运行后成功播放媒体库中的mp3文件。

打印日志:

08-01 20:20:10.472  3363  3363 I A0fefe/JsApp: mediaTest:getfileAssets success:{}
08-01 20:20:10.474  3363  3363 I A0fefe/JsApp: mediaTest:getAllObject success:"datashare:///media/audio/16"
08-01 20:20:10.477  3363  3363 I A0fefe/JsApp: mediaTest:fileAsset fdpath:fd://55
08-01 20:20:10.503  3363  3363 I A0fefe/JsApp: mediaTest:data load success
08-01 20:20:10.508  3363  3363 I A0fefe/JsApp: mediaTest:play success
08-01 20:20:13.389  3363  3363 I A0fefe/JsApp: mediaTest:pause successs
​

6 知识分享

  • MediaLibrary.createAsset()方法能在媒体库中创建指定类型的文件。

  • AudioPlayer的src属性目前只支持fd://xx、file://xx、http://xx或者https://xx四种路径格式

Logo

社区规范:仅讨论OpenHarmony相关问题。

更多推荐