arielfaur / ionic-audio

An audio player for Ionic 3 and Angular 4. Works with HTML 5 audio or native audio using Cordova Media plugin.
http://arielfaur.github.io/ionic-audio/2.0/index.html
MIT License
321 stars 163 forks source link

About using ionic-audio with local files #92

Closed Marian0 closed 7 years ago

Marian0 commented 7 years ago

Hello !

I'm trying to use this plugin in a ionic2 project with local mp3 files. These files are located at /assets/sounds/example.mp3.

When using HTML, the plugin works perfect but when I compile it into an Android device I got an error like that on chrome devices inspector:

Loading track assets/sounds/sonido1.mp3
main.js:39936 Audio error => track assets/sounds/sonido1.mp3 Object {code: 1}

Do you know what I'm doing wrong?

Thanks

borodiliz commented 7 years ago

Hi @Marian0 ,

I'm playing mp3 on both IOS and Android without problems with this plugin (version 2.3.0) . In my case I'm downloading files and storing them on the device. Before playing I use cordova-file to get the fileUrl, something similar to:

import { File  } from 'ionic-native';
...
    checkFileAvailable() {
        if (!this.platform.is('cordova')) {
            return;
        }
            if (this.platform.is('android')) {
                this._store = cordova.file.externalDataDirectory;
            }
            else {
                this._store = cordova.file.documentsDirectory;
            }
            console.log("this._store" + this._store);
        console.log(" Checking " + this.document.file);
        File.resolveLocalFilesystemUrl(this._store + this.document.file)
            .then((fileEntry) => {
                this._fileAvailable = true;
                this._fileUrl = fileEntry.toURL();
            })
            .catch((err) => {
                this._fileAvailable = false;
            });
    }

After getting the fileUrl with cordova-file, pass it to ionic-audio module as the src of your mp3

Marian0 commented 7 years ago

Hi @borodiliz ,

Thank you! I've solved by one more hardcoded approach 😆 and now it's working either with webview and on Android.

        //default path (web view)
        let path = 'assets/sounds/';

       //android path
        if (this.platform.is('android')) {
            path = '/android_asset/www/assets/sounds/';
        }

       //@todo: use cordova functions to get path from android and iOs

        let sounds = [{
            src: `${path}sound1.mp3`,
            title: 'Sonido1 ',
            preload: 'metadata'
        }, {
            src: `${path}sonido2.mp3`,
            title: 'Sonido 2',
            preload: 'metadata'
        }];
kunjanthakkar1 commented 7 years ago

@borodiliz I am trying to play an audio file which I am downloading on the device. However, when I try to play the saved file I see an error 'Not allowed to load local resource: file:///'. I tried using cdvfile path too, however, with the same result. This happens only for iOS I am able to get it working for android. Am I missing anything?

borodiliz commented 7 years ago

@kunjanthakkar1 The following code works for me:

1.- Before downloading, set the appropriated storage. On IOS store files on cordova.file.documentsDirectory

        if (this.platform.is('cordova')) {
            if (this.platform.is('android')) {
                //Android
                this._storage = cordova.file.externalDataDirectory;
            }
            else {
                //Ios
                this._storage = cordova.file.documentsDirectory;
            }
            console.log("this._storage" + this._storage);
        }

2.- Download file:

    private downloadFile() {

        const ft: FileTransferObject = this.transfer.create();
        this._downloading = true;
        ft.onProgress(this.onProgress);
        ft.download(
            encodeURI(this.document.path),
            encodeURI(this._storage + this.document.file),
            false,
            {headers: {"apikey": this.user.getToken()}}
        ).then((entry) => {
            this._downloading = false;
            console.log('download complete: ' + entry.toURL());
            this.checkFileAvailable();

        }).catch((err) => {
            this._downloading = false;
            alert("Error downloading. Code: " + err.code)
        });
    }

3- Once the file is downloaded and before playing it I'm using cordova-file to get the fileUrl, something similar to:

    checkFileAvailable() {
        console.log(" Checking " + this.document.file);
        this.file.resolveLocalFilesystemUrl(this._storage + this.document.file)
            .then((fileEntry) => {
                this._fileAvailable = true;
                this._fileUrl = fileEntry.toURL();
            })
            .catch(() => {
                this._fileAvailable = false;
            });

    }

4.- Pass this._fileUrl to ionic-audio

        this.singleTrack = {
            src: this._fileUrl,
            artist: '',
            title: '',
            art: 'assets/img/waveform.jpg',
            preload: 'none' // tell the plugin to preload metadata such as duration for this track, set to 'none' to turn off
        };
kunjanthakkar1 commented 7 years ago

@borodiliz Thank you so much for your quick response! I tried out the exact steps that you have mentioned, however, despite that I still get the same error. Here is my code in home.ts file

download() {
    const ft: FileTransferObject = this.fileTransfer.create();
    this._downloading = true;
    ft.onProgress(this.onProgress);
    ft.download(
      encodeURI('https://s3.amazonaws.com/membershipsite-downloadables/PROGRAMS-HTM/Associate-Training/2017-ASSOCIATE-10-OCT-MON-A/ASSOCIATES-OCT2017-A-WEEK01.mp3'),
      encodeURI(this._storage + 'Track2.mp3'),
      false,
    ).then((entry) => {
      this._downloading = false;
      console.log('download complete: ' + entry.toURL());
      this.checkFileAvailable();

    }).catch((err) => {
      this._downloading = false;
      alert("Error downloading. Code: " + err.code)
    });
  }
  public checkFileAvailable() {
    this.file.resolveLocalFilesystemUrl(this._storage + 'Track2.mp3')
      .then((fileEntry) => {
        this._fileAvailable = true;
        this._fileUrl = fileEntry.toURL();
        this._fileInternalUrl = fileEntry.toInternalURL();
        console.log("fileurl:", this._fileUrl);
        console.log('cdvfile:', this._fileInternalUrl);
        this.myTracks.push({
          src: this._fileUrl,
          artist: '',
          title: 'Internal',
          art: 'assets/imgs/Stephane.jpg',
          preload: 'none'
        })
      })
      .catch(() => {
        this._fileAvailable = false;
      });

  }

The file gets downloaded successfully however I get the following error in console - Not allowed to load local resource: file:///Users/Library/Developer/CoreSimulator/Devices/B56ADA53-1DE1-41FF-A429-C2DF15E1BF38/data/Containers/Data/Application/C15534E5-89C5-4075-AA32-11FB215EABBD/Documents/Track2.mp3

I also tried with fileEntry.toInternalURL() which gives me a cdvfile path, with that I get the following error - 'Failed to load resource: unsupported URL'

I have the following permissions in my config.xml:

<access origin="file:///*" />
<access origin="cdvfile://*" />
<allow-navigation href="file:///*/*" />
<allow-navigation href="cdvfile://*" />

This is a very important feature for the app that I am working on, I would really appreciate any more pointers that you can give me. Thanks in advance!

borodiliz commented 7 years ago

Hi @kunjanthakkar1 . Sorry but no idea why you are getting this error.

My config.xml (No allow-navigation tags ):

    <access origin="*" />
arielfaur commented 6 years ago

168