What are the correct paths for iOS to save downloaded files (persistent, "Libary")

2,135 views
Skip to first unread message

Marc Wäsche

unread,
Sep 18, 2015, 12:45:09 PM9/18/15
to phonegap
Hello!

My app downloaded and saves mp3 files from my server. For Android it works like a charme. But for iOS I was coding, testing and researching yesterday for the whole day. I wasn't able to bring it to work. It "seems" that downloading and saving is working fine. But I don't know what  the correct path is to play back that saved mp3 files. It "seems" that the download and save process worked because the success callback was called but I don't know how to find out if it was really saved. For coding I use Phonegap Build.


In the config.xml
    <gap:plugin name="org.apache.cordova.device" />
    <gap:plugin name="org.apache.cordova.file" />
    <preference name="iosExtraFilesystems" value="library,library-nosync,documents,documents-nosync,cache,bundle,root" />
    <preference name="iosPersistentFileLocation" value="Library" />
    <preference name="AndroidPersistentFileLocation" value="Internal" />
    <preference name="BackupWebStorage" value="none" />
    <gap:plugin name="org.apache.cordova.file-transfer" />
    <gap:plugin name="org.apache.cordova.media" />
    <gap:plugin name="org.apache.cordova.geolocation" />  

---------------------------------------------------

function downloadFile(file){
  
var fileURL = "cdvfile://localhost/persistent/s"+file+".mp3";
var fileTransfer = new FileTransfer();
var uri = encodeURI("http://www.domain.com/mp3/s"+file+".mp3");

fileTransfer.download(
    uri,
    fileURL,
    function(entry) {

   alert("download complete");
    },
    function(error) {
        alert("download error source " + error.source);
        alert("download error target " + error.target);
        alert("upload error code" + error.code);
    },
    false,
    {
        headers: {
            "Authorization": "Basic dGVzdHVzZXJuYW1lOnRlc3RwYXNzd29yZA=="
        }
    }
); 
}

         <a href="#" onclick="playAudio('cdvfile://localhost/persistent/s1.mp3');">Play Test 1</a><br>
         <a href="#" onclick="playAudio('file://var/mobile/Containers/Data/Application/' + device.uuid + '/Library/files/s1.mp3');">Play Test 2</a><br> 
         <a href="#" onclick="playAudio('localhost/Libary/s1.mp3');">Play Test 3</a><br>
         <a href="#" onclick="playAudio('cdvfile://localhost/Libary/s1.mp3');">Play Test 4</a><br>       
         <a href="#" onclick="playAudio('file://localhost/Libary/s1.mp3');">Play Test 5</a><br>


---------------------------------------------------

I tried a lot of different path as you can see in the bottom of the code but never found the correct one. The playAudio() function I didn't here here but that one is working. I have no problems to play a mp3 file which is coming with the installation and is saved in the app storage folder.

What did I wrong? Is it only a path problem? And if so, which is the correct path?

Best regards
Marc

jcesarmobile

unread,
Sep 18, 2015, 6:52:15 PM9/18/15
to phonegap
on the success callback from the download you have the entry, you can get the url from there

Marc Wäsche

unread,
Sep 18, 2015, 8:42:32 PM9/18/15
to phonegap

Am Freitag, 18. September 2015 23:52:15 UTC+1 schrieb jcesarmobile:
on the success callback from the download you have the entry, you can get the url from there

You mean entry.fullpath? Or entry._localURL?  alert(entry.fullpath) or similar does not work for me. The alert box is empty then. Okay, time to confess that I have no idea how the often quoted "console.log" command works. :-) I also installed the cordova plugin "console" not knowing if this has really to do with the console.log command but even this didn't make me able to use this debugging feature. :-) I am using my iPhone itsself for testing. Does console.log doesn't work on real devices? In my estimation console.log does not tell me more than alert() but I can be wrong here... am I? :-)

Marc

Kerri Shotts

unread,
Sep 20, 2015, 5:05:10 PM9/20/15
to phonegap
Remote debugging with Safari is your friend. Console.log will log to the JavaScript console, which you can view when the debugger is attached to your device. Furthermore, you get a javascript repl, which makes it easy to experiment with things. See https://blog.idrsolutions.com/2015/02/remote-debugging-ios-safari-on-os-x-windows-and-linux/

One other question: How to you /know/ playAudio() is working? Never assume that the problem isn't possibly in there... so it would help to see that code as well.

Marc Wäsche

unread,
Sep 22, 2015, 11:58:06 AM9/22/15
to phonegap
Thanks for that advice with the console. I will use it from now on. :-)
And here is the code from my playAudio()

      var my_media = null;
        var mediaTimer = null;

        function playAudio(src) {
       
  if( device.platform === 'iOS' ) {
    src = src.replace('file://', '');
}          

            my_media = new Media(src);

            my_media.play();

            if (mediaTimer == null) {
                mediaTimer = setInterval(function() {
                    my_media.getCurrentPosition(
                    );
                }, 1000);
            }
        }


--------------------------------------------------------------------------
The iOS depending string formatting

    if( device.platform === 'iOS' ) {
       src = src.replace('file://', '');
     }

is from one of my tests. I also tried to change things here including not-using it at all but without success.



Marc Wäsche

unread,
Sep 22, 2015, 12:13:38 PM9/22/15
to phonegap
Am Sonntag, 20. September 2015 22:05:10 UTC+1 schrieb Kerri Shotts:
Remote debugging with Safari is your friend. Console.log will log to the JavaScript console, which you can view when the debugger is attached to your device. Furthermore, you get a javascript repl, which makes it easy to experiment with things. See https://blog.idrsolutions.com/2015/02/remote-debugging-ios-safari-on-os-x-windows-and-linux/

HOW COOL IS THAT??? I love it!! :-)

Kerri Shotts

unread,
Sep 22, 2015, 4:35:21 PM9/22/15
to phonegap
It's awesome! Chrome remote debugging Android 4.4+ is even better!

First: make sure you install the File plugin.

Second, you need to be sure to use the correct path to the audio file. In function(entry) {...}, try logging `entry.toURL()` to your console. It should look like your `cdvfile://` examples, but it is wise to be sure.

Next, in `playAudio`, you have a bug, namely the check for `file://`. The incoming URL /should/ have `cdvfile://localhost/persistent/s1.mp3` as the scheme, but your code is going to change it to `cdvlocalhost/persistent/s1.mp3`, which is obviously incorrect.

If you must strip `file://`, there's a better way:

function stripFileScheme (src) {
  const FILE_SCHEME_REGEXP = /^file:\/\//i;   // const is ES6; use var if ES5
  return (device.platform === "iOS") ? src.replace(FILE_SCHEME_REGEXP, "") : src;
}

console.log(stripFileScheme("cdvfile://localhost/persistent/s1.mp3")); // (1)
console.log(stripFileScheme("file://some/other/path/s1.mp3"));         // (2)


For (1), the original string is returned, regardless of platform. For (2), "file://" is eliminated only on iOS. Notice that I'm using a regular expression in the call to replace() -- that caret (^) anchors the matching process to the start of the line.

I think that should give you enough to go on. If not, holler! :-)

Marc Wäsche

unread,
Sep 22, 2015, 6:32:51 PM9/22/15
to phonegap
Wow, that are grate advices! Thank you very much, Kerri!! I am out ouf house the next days so I don't know when I can test it out but I will come back here and report. Once again: Thank you very much for your help! :-)

Marc

Marc Wäsche

unread,
Sep 24, 2015, 9:10:05 PM9/24/15
to phonegap
Hello!

Obviously I was able to fix my bug. :-) The console feature helped me a lot to go through this.
The reason was that cordova wrote the downloaded files into the folder

  var/mobile/Containers/Data/Application/{ID}/Library/files/

while a

   resolveLocalFileSystemURL(cordova.file.dataDirectory, function(entry3) {
   path = entry3.toURL();

brought me to

  var/mobile/Containers/Data/Application/{ID}/Library/NoCloud/

I fixed it with

   resolveLocalFileSystemURL(cordova.file.applicationStorageDirectory, function(entry3) {
   path = entry3.toURL();
   path = path + "Library/files/";

The funny thing is that this path's prefix starts then with

   file:////

With 4(!) slashes. ;-) I had to remove the complete prefix to make my app able to play back the mp3 files.

Thanks again, Kerri!

Best regards
Marc

Reply all
Reply to author
Forward
0 new messages