androidionic-frameworkaudiocapacitorionic-native

Ionic 7 - Download and play mp3 file with audio controls


My server has some mp3 files stored.

I want my application to download and store them.

Then, user can select which file to play. I'd like it to be just like Spotify. A list of audios, and user clicks to play the audio.

I'm using Ionic's native File plugin to save the file, in this.file.dataDirectory

Downloading files

this.http.sendRequest(url, {method: "get", responseType: "arraybuffer"}).then(
    res => {
      let blob = new Blob([res.data], {type: 'audio/mp3'});
      this.saveFile(blob);
    }
);

Saving files

this.file.createFile(folderPath, fileName, true).then(
    _ => {
      if(blob == null) {
        console.error("Downloaded file is null");
        reject(false);
      } else {
        this.file.writeFile(folderPath, fileName, blob, {replace: true}).then(_ => {
          console.log("File created");
        });
      }
})

I'm getting the "file created" message. Nice! However, I cannot see those files in "Internal Storage -> Android -> io.ionic.starter -> data", but if I use the this.file.checkFile(folderPath, filename), it returns true.

Playing the audio

This is the nightmare part. When I give an URL to Javascript's Audio, it works nicely, just like:

let audioAsset = new Audio(audioLink);
audioAsset.play();

But it doesn't work with local files!

Not allowed to load local resource: file:///data/user/0/io.ionic.starter/files/myfile.mp3

I tried NativeAudio, but I get the "FileNotFoundException". It worked when I had my audio files already added in assets folder, but not to those I download to "dataDirectory".

Some forums mention MediaObject, just like THIS ONE. However, there is no @ionic-native/media package anymore. It seems to be an Enterprise Feature now.

This should be a very simple task, but it is becoming a nightmare with Ionic! Can anyone help me?


Solution

  • Solved the issue after several hours. Here are some hints to make the Ionic developer's life easier.

    Downloading a file: Use Native HTTP

    import { HTTP } from '@awesome-cordova-plugins/http/ngx';
    
    constructor(private http: HTTP) { }
    
    this.http.sendRequest(url, {method: "get", responseType: "arraybuffer"}).then(
      res => { this.saveFile(new Blob([res.data], {type: 'audio/mp3')) }
    );
    

    Saving a file: use Native File and externalApplicationStorageDirectory as your folder

    import { File } from '@awesome-cordova-plugins/file/ngx';
    
    constructor(private file: File) {}
    
    saveFile(blob) {
      let path = this.file.externalApplicationStorageDirectory;
      let filename = 'myfile.mp3';
      this.file.writeFile(path, filename, blob, {replace: true}).then(res => {/*code here*/})
    }
    

    And finally, PLAYING THE AUDIO: Turns out that Media was not only an Enterprise feature. HERE is the community version. It was hard to find. Bad job, Ionic...

    import { Media, MediaObject } from '@awesome-cordova-plugins/media/ngx';
    import { File } from '@awesome-cordova-plugins/file/ngx';
    
    constructor(private media: Media, private file: File) {}
    
    playSound() {
      let path = this.file.externalApplicationStorageDirectory;
      let filepath = `${path}/myfile.mp3`;
      let file: MediaObject = this.media.create(filepath);
      file.play();
    }
    

    And DO NOT forget to set the permissions. Here are mine:

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
    

    BONUS ROUND: Audio controls on the notification bar are awesome, right? There is a MediaSession API plugin for cordova HERE. Many thanks to THIS GUY too.