Yesterday I blogged my experiment with downloading files to a PhoneGap application. Today I decided to take my code and try it out on iOS. Along the way I discovered a little bug, and encountered the White List issue with iOS PhoneGap apps. As with the previous entry, please note that this could possibly be done better.
Before we even get started, I wanted to correct a small issue in the previous code base. The code that handles file downloads looked like so:
var dlPath = DATADIR.fullPath + "/" + res[i];
console.log("downloading crap to " + dlPath);
ft.download("http://www.raymondcamden.com/demos/2012/jan/17/" + escape(res[i]), dlPath, function(){
renderPicture(dlPath);
console.log("Successful download");
}, onError);
I noticed, however, that my images were all the same URL, but only when the app was run for the first time and the images had to be downloaded. Why? I was using dlPath inside my closure and it wasn't using the right value. Classic JavaScript scoping issue and one I can't believe I made.
Luckily, the FileTransfer event includes all the data I need. Here's the new version:
var dlPath = DATADIR.fullPath + "/" + res[i];
console.log("downloading crap to " + dlPath);
ft.download("http://www.raymondcamden.com/demos/2012/jan/17/" + escape(res[i]), dlPath, function(e){
renderPicture(e.fullPath);
console.log("Successful download of "+e.fullPath);
}, onError);
Nice and obvious once you see it. Ok, so what about iOS? I had struggled a bit last week to get my first iOS/PhoneGap running, but most of that struggle was due to the fact I had never run XCode before. It's a strange beast! Plus I'm using it over VNC, which works ok for the most part but is a bit tricky at times.
Once I got past getting my application certificate crap running (thank you, Apple, for protecting me from my own hardware, lord forbid you allow me to just install anything without asking for permission first... oh crap, I'm going off on a sermon again) everything was mostly kosher. And rants aside - the iOS Simulator makes the Android Simulator look like a TRS-80. (And yes, I know the Android thing is doing more. Guess what - I don't care. It's a pain in the ass and slower than waiting for a picture to download over 14.4 baud modem.)
With my code in place, I immediately ran into an issue with my remote URL. Remember I'm hitting raymondcamden.com to get a list of images. XCode actually fleshed this error out quite obviously in the debugger. It's also something "everyone" knows so I wasn't too surprised. You simply need to go into PhoneGap.plist and add your domain:

The next change I made was one that would probably work fine in Android too. Instead of switching to an Android based directory:
fileSystem.root.getDirectory("Android/data/com.camden.imagedownloaddemo",{create:true},gotDir,onError);
I did this instead:
fileSystem.root.getDirectory("com.camden.imagedownloaddemo",{create:true},gotDir,onError);
My gut tells me this same path would be fine on both - but in my third entry, where I talk about using integrating the iOS/Android version, I'll use this as one of the things I do differently on each platform. Anyway, it runs!

Archived Comments
Uhmm your third entry?
Is it just me that can't find this or did I misunderstand something?
Part 3 is here: http://www.raymondcamden.co...
Part 4 is here: http://www.raymondcamden.co...
I found my new god. Really thanks Raymond for this example. It works nice :)
Heh, careful now, someone may get offended. ;)
Haha :)
Juste a little question about your imagelister. How do you generate it.
I tried with a json_encode($var) with $var, the name of my .jpeg on my list.php for the $.get but the synthax is not the same.
I don't have "[]" at the beginning and at the end, and also don't have the "," between each name.
Ps: I'm french and sorry my english is not well :)
-But all it's doing is returning a JSON-encoded array of images-
I didn't see it was an array, i got the same synthax now. :stupid:
Sorry for double comments!
No worries - just glad you got it.
Hey Raymond is still me.
Did you have any idea to create several directories using the sampe principe. Return a JSON with the name of the directory and create it to download into them the images.
Thank you in advance
I can describe it in abstract. Pretend for a minute that we wanted to organize pictures by subject. You could return data like so:
[
{ img:"foo.jpg", subject:"sports"},
{ img:"foo2.jpg", subject:"music"},
{ img:"foo3.jpg", subject:"sports"}
]
Your code would treat subject like a subdirectory and use the FileSystem API to create the folder if it needs to be created.
Then it uses that directory when storing the file.
Yes, i see how do, i will try to do this.
Thank you for your fast answer, and thanks a lot for everything. :)
Hey Raymond, I have one last question. :)
All works nice in my app but, is it possible to copy/paste or direct donwload images in a directory in www ?
I don't believe so. You want to use the system storage instead.
Arf, ok, thanks anyway again.
I do not get it work :( help me please
http://pastebin.com/gq9wwCa3
You need to figure out _where_ it isn't working. Just saying the whole thing isn't working is enough. Describe what part fails.
This shows no errors. this does not show images
So your next step would be to try adding console.log messages, or even alerts, to see if you can figure out where it breaks. FOr example, I'd consider deviceready is firing with a simple alert message.
I'm trying to adapt your example to my code, and I wondered if in your url the number 17 is the folder where the images is?, I do not know how to access the imagens from php, I already create the list with the names of all pictures.
Can you show me the php code?
1) Yes, 17 was just part of the folder name. Nothing special.
2) What PHP code? My example was built in CF. But it would be done in PHP.
Hi Raymond!
Any possibility to see the code demo??
Richard
Sorry I don't have a direct link for this, but if you get the code from P1 and just do the fix I mentioned in the entry, that is it.
Thanks Ray For you quick answer!
Richard
Does this also work for Phonegap Build? Cause I tried it, in combination with Phonegap 2.9 and it's not working.
How is it not working? Don't forget to use config.xml to specify raymondcamden.com in your access block. Or another server if you set up your own service.
Strange, that actually did do the trick, even though I put * in the access block. Now to find out why it isn't working in my adaptation! Thanks!
@Anneleen
The * should work. Make sure you are setting this in the good config.xml as you can have multiple config.xml in a phonegap project and this can be very confusing.
@Raymon, I have an app with lot of images organized in chapters and the total app size is 300mo while max app size is 60mo (OTA), and I want to use your file-download-example to download the additional chapters right after first launch, and keep initial app size small. Do you have any best practice to do this while making sure the app get accepted by Apple validation team? Is your technique suitable for my need?
Thanks
A few thoughts.
1) Create a placeholder image in case the user somehow clicks into something that would use one of the images. That way they see something.
2) Just fire off a process in the background to handle getting the images. You want to ensure you remember where you left off in case you don't complete them all.
Hello friend, you would not have to provide the link with the code?
Hello, updated their code to the cord => 3.0, if you want to then do an update of your post, and if possible post the code to download
Are you asking for a copy of the code? I can't really tell. As for an update, what I have *should* still work in 3.X.
Wanted a copy, but I've run, the way you did not work in version => 3 needs some tweaking if you want it updated to post here pass me your email I will send you
Can you post a zip publicly and share the URL here?
@Samtj: I just deleted your comment. Please do not post your files in the comment block. Post a Gist URL instead.
Hello, it is a great tutorial.
But i want to know. When i want to check. IF the file already exists with the same name then do not download the file again.
How can i do that?
I try to put a FOR loop to check this. But didnt work out it starts to give some error like IO exception. Any way you can suggest?
Thank you!
See http://www.raymondcamden.co...