Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ionic 2 / iOS - Native audio does not find a file in cordova.file.dataDirectory

I am using cordova-plugin-nativeaudio to play audio in the application. When I am trying to preload a file with iOS device:

preload('testsound', cordova.file.dataDirectory + "audio/0/Hello.mp3");

I am getting an error of:

ERROR: Unhandled Promise rejection: (NATIVE AUDIO) Asset not found. (file:///var/mobile/Containers/Data/Application/"[GUID]/Library/NoCloud/audio/0/Hello.mp3) ; Zone: ; Task: setTimeout ; Value: (NATIVE AUDIO) Asset not found. (file:///var/mobile/Containers/Data/Application/[GUID]/Library/NoCloud/audio/0/Hello.mp3)

The target file

The target file (audio/0/Hello.mp3) is downloaded from external url and stored in cordova.file.dataDirectory. It is downloaded successfully as following console output:

download complete: file:///var/mobile/Containers/Data/Application/[GUID]/Library/NoCloud/audio/0/Hello.mp3

To make sure it is really stored in the intended location, I checked:

this.file.checkFile(cordova.file.dataDirectory, "audio/0/Hello.mp3")

Console output shows it is stored successfully:

file:///var/mobile/Containers/Data/Application/[GUID]/Library/NoCloud/audio/0/Hello.mp3 file does EXIST!

Now I tried to preload the file with native audio, I get the error above (the first error in this question).

Problem seems to be where the file is stored

I also tried preload from local applicationDirectory (/www/assets/audio/0/Hello.mp3), preload worked fine. However applicationDirectory is readonly directory, so I cannot download audios from external url and save them there.

Native audio should supports preload from url (not only from local applicationDirectory) since it is stated in their Ionic API doc.

screenshot of the API doc of preload function

I am getting same error with both emulator and iOS device.

Have anyone experienced a same issue, and managed to sort it out?

Thanks for your help. BR/

like image 664
Nanako Avatar asked Jun 18 '17 12:06

Nanako


2 Answers

In iOS if you need to play a sound synchronously as part of sequence or transition, the only thing that worked for me is Native Audio preloadComplex with file in my /asset.

import { NativeAudio } from '@ionic-native/native-audio';

...

let id = new Date().toISOString();
this.nativeAudio.preloadComplex(id, 'assets/file.m4a', 1, 1, 0).then(() => {
  this.nativeAudio.play(id, () => {
    this.nativeAudio.unload(id).then(() => {
      // Next step
    });
  });
});

If the sound can be play asynchronously and is user recorded, the only thing that worked for me is Media Plugin.

import { Media, MediaObject } from '@ionic-native/media';

...

if (this.mediaObject) {
  this.mediaObject.release();
}      
this.mediaObject = this.media.create('../Library/NoCloud/MediaFiles/file.m4a');
this.mediaObject.play();

...

ionViewDidLeave() {
  if (this.mediaObject) {
    this.mediaObject.release();
  }
}
like image 62
Jean-Pierre Fortin Avatar answered Nov 15 '22 13:11

Jean-Pierre Fortin


I have found a workaround, which is to use Media plugin, instead of Native audio to play mp3 file.

Though Media plugin seems to have a same problem - you cannot access to the cordova.file.dataDirectory with iOS, and it is discussed in this Jira - there is at least a workaround for it, which is to use .toInternalURL().

toInternalURL: returns the path in the form file:///persistent/path/to/entry (Firefox, IE). Chrome returns the path in the form cdvfile://localhost/persistent/file.

internalURL of cordova.file.dataDirectory (file:///var/mobile/Containers/Data/Application/[GUID]/Library/NoCloud) is "cdvfile://localhost/library-nosync/"

So by replacing:

storageDirectory = cordova.file.dataDirectory;

with:

storageDirectory = "cdvfile://localhost/library-nosync/"

Now the media plugin can load and play mp3 files downloaded and stored in cordova.file.dataDirectory with iOS device.

audioMedia = new MediaPlugin(storageDirectory + "test.mp3");

audioMedia.play();

P.S.1 This is a working solution as of June 2017.

P.S.2 I have tried to use internalURL with Native Audio, which did not work.

like image 41
Nanako Avatar answered Nov 15 '22 14:11

Nanako