For the past week or so I've been looking at file system access and downloads with PhoneGap. Before going any further, I want to warn folks that I'm still a bit fuzzy on the details here. It was a bit of a struggle to get this working right, and I plan to follow this entry up with a look at iOS and also how to get all platforms working right, but for now, consider this a first draft. I also want to give thanks to Simon Mac Donald for his help. Anything right here is thanks to him and anything wrong is my fault.
Ok, with that out of the way. Let's talk about file downloads. A reader pinged me recently to ask about how to support offline PhoneGap applications. Specifically, he wanted to work with images that were remote and make them available to the application when the device was offline. I decided to work on a simple application that would fetch images from a server and store them locally.
I began by looking over the File docs at PhoneGap. This is - for the most part - a wrapper for the W3C File API. I had a real hard time grokking this API. My gut take on it is this:
- You begin by requesting a file system. This request is either for a persistent or temporary storage. Obviously which you pick depends on what your needs are. For my demo application, I need the persistent storage.
- What you get back is a file system object. From what I see in the spec, the object contains a few properties, but your primary usage of this is to get a directory entry.
- Once you have a directory object, you can enumerate files, read them, whatever.
Based on what I learned from Simon, in Android, the place you want to store your files is:
Android/data/X
Where X is the identify of your application. For my demo, this was com.camden.imagedownloaddemo. For the first iteration of my demo, I requested the file system, the directory, and then a list of files:
<!DOCTYPE HTML>
<html>
<head>
<meta name="viewport" content="width=320; user-scalable=no" />
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<title>Image Download Demo</title>
<script type="text/javascript" charset="utf-8" src="phonegap-1.3.0.js"></script>
<script type="text/javascript" charset="utf-8">
//Global instance of DirectoryEntry for our data
var DATADIR;
//Loaded my file system, now let's get a directory entry for where I'll store my crap
function onFSSuccess(fileSystem) {
fileSystem.root.getDirectory("Android/data/com.camden.imagedownloaddemo",{create:true},gotDir,onError);
}
//The directory entry callback
function gotDir(d){
DATADIR = d;
var reader = DATADIR.createReader();
reader.readEntries(gotFiles,onError);
}
//Result of reading my directory
function gotFiles(entries) {
console.log("The dir has "+entries.length+" entries.");
for (var i=0; i<entries.length; i++) {
console.log(entries[i].name+' '+entries[i].isDirectory);
}
}
function onError(e){
console.log("ERROR");
console.log(JSON.stringify(e));
}
function onDeviceReady() {
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, onFSSuccess, null);
}
function init() {
document.addEventListener("deviceready", onDeviceReady, true);
}
</script>
</head>
<body onload="init();" >
<h2>Image Download Demo</h2>
<div id="status"></div>
</body>
</html>
As everything is async, the code gets a bit complex, but I begin by requesting the file system, requesting the directory (and notice, you can pass an optional argument to automatically create it, which is useful), and then the files.
Ok - so that seemed to work. It was then time to look into the file sync aspects. To keep things simple, my sync logic would just ask a remote server for a list of images. Every image the remote server had that I did not, I downloaded. Obviously this means I can be left with images locally I don'rt need, but I wanted to keep things as basic as possible. Here's the new version:
<!DOCTYPE HTML>
<html>
<head>
<meta name="viewport" content="width=320; user-scalable=no" />
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<title>Image Download Demo</title>
<script type="text/javascript" charset="utf-8" src="jquery.min.js"></script>
<script type="text/javascript" charset="utf-8" src="phonegap-1.3.0.js"></script>
<script type="text/javascript" charset="utf-8">
//Global instance of DirectoryEntry for our data
var DATADIR;
var knownfiles = [];
//Loaded my file system, now let's get a directory entry for where I'll store my crap
function onFSSuccess(fileSystem) {
fileSystem.root.getDirectory("Android/data/com.camden.imagedownloaddemo",{create:true},gotDir,onError);
}
//The directory entry callback
function gotDir(d){
console.log("got dir");
DATADIR = d;
var reader = DATADIR.createReader();
reader.readEntries(function(d){
gotFiles(d);
appReady();
},onError);
}
//Result of reading my directory
function gotFiles(entries) {
console.log("The dir has "+entries.length+" entries.");
for (var i=0; i<entries.length; i++) {
console.log(entries[i].name+' dir? '+entries[i].isDirectory);
knownfiles.push(entries[i].name);
renderPicture(entries[i].fullPath);
}
}
function renderPicture(path){
$("#photos").append("<img src='file://"+path+"'>");
console.log("<img src='file://"+path+"'>");
}
function onError(e){
console.log("ERROR");
console.log(JSON.stringify(e));
}
function onDeviceReady() {
//what do we have in cache already?
$("#status").html("Checking your local cache....");
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, onFSSuccess, null);
}
function appReady(){
$("#status").html("Ready to check remote files...");
$.get("http://www.raymondcamden.com/demos/2012/jan/17/imagelister.cfc?method=listimages", {}, function(res) {
if (res.length > 0) {
$("#status").html("Going to sync some images...");
for (var i = 0; i < res.length; i++) {
if (knownfiles.indexOf(res[i]) == -1) {
console.log("need to download " + res[i]);
var ft = new FileTransfer();
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);
}
}
}
$("#status").html("");
}, "json");
}
function init() {
document.addEventListener("deviceready", onDeviceReady, true);
}
</script>
<style>
img {
max-width: 200px;
}
</style>
</head>
<body onload="init();" >
<h2>Image Download Demo</h2>
<div id="status"></div>
<div id="photos"></div>
</body>
</html>
Ok, it's a bit much, but let's work through the various events. You can still see the file system request as well as the directory list. I do two new things now once I have the files. I remember them (storing them in knownfiles), and I render them using a simple utility function. Yes - you can pass a path to an image source and it works just fine.
Now - take a look at appReady. This handles my remote call. I'll share the ColdFusion code if folks want, but all it's doing is returning a JSON-encoded array of images. For each result, I see if I already have it, and if not, use the download method of the FileTransfer object. Note: One of my images had a space in the file name. This causes all kinds of problems until I simply escaped it:
ft.download("http://www.raymondcamden.com/demos/2012/jan/17/" + escape(res[i]), dlPath, function(){
Here's a quick screen shot. Obviously it is static so you can't see it working, but in my testing, when I pushed up a new image remotely, and reran the application, it immediately noticed it was missing one and grabbed it.

So - what's next? As I said, this is currently Android specific, and that's bad. I'm next going to test on iOS, and then get one application that can handle both. Also, I didn't actually bother checking to see if the device was online. That would be trivial via the Connection API and should be done. (I'll remember to do it for the final, "combined" demo.)
Does this make sense? Any questions?
Edit on January 20, 2012: Note that I made a mistake in my fileTransfer callback. I talk about this mistake here, but the critical fix is right here:
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);
Archived Comments
I Thought the cache.manifest was for storing offline files like images. This is all completely new info for me. Thanks for the code!
HTML5 Offline Storage could create a similar effect. In this case though the PhoneGap is local HTML, so you can't really use it. This approach could also be made much more complex - for example, it could download large images only when your connection is Wifi as opposed to cell.
Thanks for this post. I need it.
M.
Thanks Ray! Works fine on iOS without any issues. Filetransfer.download() was the key. Somehow I didn't see it in the PhoneGap API doc.
I'm downloading all the images on app load and then replacing the src of the image on page load.
/* change images to local on page load */
function renderLocalImage(){
var contentObj = $("#pageContent");
$('img',contentObj).each(function(index){
var src = $(this).attr('src');
var srcArray = src.split('/');
var imageName = srcArray[srcArray.length-1];
var localImage = 'file://' + imageDir.fullPath + '/' + imageName;
$(this).attr('src',localImage);
});
}
You missed it because it isn't listed on top. I missed it too at first. Sorry it took so long (for others, Sumit was the guy who kinda started me on this).
The funny thing is it works perfectly in iOS, but I can't get it to work on Android! The getDirectory method keeps throwing error 12 (FileError.PATH_EXISTS_ERR = 12).
Also, on ICS (4.0.3) I can't even get open database to work. That throws:
I/SqliteDatabaseCpp(8031): sqlite returned: error code = 14, msg = cannot open file at line 27701 of [8609a15dfa], db=/data/data/com.ten24.androidtest/databases/webview.db
Sumit, one thing I ran into was not being able to write to my SD when my phone was in Disk Mode. Is that something you have enabled? If you try w/o the path, or make the path match what I did in part 2, does that work?
Although - it sounds like maybe your apps can't write at all - since you can't even open a db. May be worth while posting to the Google Groups and seeing if they know something.
Ok, so I got it to work on Android 2.3.3 but 4.0.3 (ASUS Prime) throws connection error on download.
Few points:
- The database error seems to be always there but it still works.
- The File error is because getDirectory('xxx',{create:true}) throws error if the directory exists. getDirectory('xxx',{create:true,exclusive:false}) returns the directory if it exists.
- Also nested directory creation doesn't work. You can only create one folder at a time.
- In order to use file system make sure phone is _not_ connected in USB mode. Because connecting it in USB mode un-mounts the SD card. In DroidX the come is called "Charge Only".
I have to say, iOS development seems much more easier (trouble free) than Andriod.
Wow, this is truly surprising because you are seeing pretty much 100% the opposite of me:
1) No db errors for me.
2) When my directory existed, I never got an error.
3) Didn't test nested.
4) For me, my phone was in Charge Mode and it worked ok. It didn't work in disk mode.
Ray, Can you try your code on 4.0.3 AVD and see if you are getting error as well?
Found this thread about DB error where Simon says he has always seen it and to just ignore it:
http://groups.google.com/gr...
Yeah, you can safely ignore the DB error as it is just noise. I've grabbed Ray's code and tried it in a 4.0 emulator and it fails. I think, don't quote me yet, but I think it is a bug in Android 4.0 as it is failing to open a url connection. I'm going to raise a bug on Jira and do some more investigation.
Thanks Simon.
Thanks for testing this Simon (didn't get a chance to yet). Please post back when you hear more.
The download method in FileTransfer was setting the HttpURLConnection.setDoOutput to true. On Android 4.0 this would force the connection to be a POST when what we actually want is a GET.
I removed the offending line and tested the fix in 2.1, 2.2, 2.3 and 4.0. The fix is checked in for PhoneGap 1.4 which should be out early next week.
Damn. I'm pretty disappointed in PhoneGap. I mean - this took - what - 37 minutes? How can I have faith in a framework that needs so much time to correct issues.
;)
Thanks Simon - this is great to hear!
Wow! Simon, now you have set a very high expectation for future fixes. Haha...
Thanks a lot for the quick response. Is 1.4 available to play with?
Well fixes won't always come that fast but when I have a reproduction scenario and a stack trace it makes it a lot easier to track down and fix. If only all bugs had this much information.
You can always grab the latest code from:
https://git-wip-us.apache.o...
or the regularly updated mirror on github:
https://github.com/apache/i...
You won't have long to wait for the official 1.4 though as it should be out on Monday.
Thanks for this fantastic "tutorial" it saved me lots of time and a project i am working on.
I ran in a little problem, you compare the known files and the files downloadable files, do you have an idea how to identify a file tha needs to be updated?
What i do is i update the data in my app (download a JSON file) but only want to download the file if it has been changed since the last update.
regards
Alex
Alex, unfortunately, you can't (afaik!) get the file metadata on a remote file. Using a server side solution (like ColdFusion, PHP, Ruby, etc), I'd build a service that returns a list of files and their updated date. This sounds more complex (and I guess any change would be), but in theory it wouldn't be that much harder.
On the client side (your PhoneGap app), your code requests this server, and then compares it to the local directory.
Raymond, thx for replying.
I found a solution. I request a php page which returns an json containing a date.
I create an empty file on the phone and name it like the date.
Next time i check for the "datefile" if it exists i am not updating if it doesnt i download the update.
Thanks for pointing me in the right direction.
If you just want to store that date, why bother using a file? Just use localStorage.
Thx again for pointing me in the right direction.
Completely forgot about localStorage.
If i may i have one last question (as i am not very familiar with jquery).
I use your code to download a file but it seems that the app "starts" before the file is complete.
Result, old data is shown instead of the new on. Do you have any idea how to tell the app to wait for the download to complete and display a short message?
thx for all your help
The download api has a success call back, that's where I call renderPicture. So your app should start off with a "Please stand by" type message, and in your success callback, you can simply remove that and proceed.
Okay, my last question was not very precise ;-)
I use sencha touch for my app and the app starts before the download ist completed.
My idea is that i load the index.html and do all the update stuff. When all the updates are done (or not if the user has no internet connection) i want to move on to another page where i start the actual app.
In your example you would just download all the pictures and start the display of the pictures after all the downloading is done.
So instead of running renderPicture like I did, you would move the user to the ohter page. If you are using something like jQuery Mobile, there is an API for that. Otherwise, document.location should work.
Ahhh...
Ok, i am downloading multiple files. So what i could do is check if it is the last file and then move the user to the next page.
ft.download("http://my_download_path/" + escape(res[x]), dlPath, function(){
if ($x == res.length){
document.loction = 'app.html';
}
}, onError);
In the onError function i put also a location change if something goes wrong during download.
And before i even start downloading i check with
if (navigator.online)....
that an internet connection exists.
Ok..thx again for your patience and your help. Hope this was the last time i had to bother you :-)
One thing to remember though. If you are downloading N files, then it is possible that when the callback for the Nth one fires, that an earlier one is still working. That's the nature of asynch operations.
jQuery 1.5 added easier support for grouping together such tasks such that you can "do x when all is done". This feature is based on a feature called Deferreds. I'd do a bit of reading up on it. (Personally, I still struggle with the syntax.)
For my app I didn't have to worry about it.
I should force myself to update the app to use it. :)
Jep, that is exactly what happend...
Too bad.
Is there a way to download files NOT asynch?
Get list of files from the JSON and than download one after the other?
As far as i understand, the asynch method should prevent the app from making the user wait till all is loaded.
But when updating data i will tell the user that the app is updating and wait for the update to finish.
Nope, it must be asynch.
I'd really check the jQuery docs. I know I made it sound kind of scary, but it DOES work, and is very doable. It's just a topic I'm having a hard time wrapping my head around.
I had a first look at the jQuery docu but i think i will have to look for a few more examples.
Maybe i should first try to fully understand how all those callback functions work ;-)
I'll give it a try.
Here is how you can make is synchronous:
PS: there is some extra code in here that you can remove, but you will get the idea.
/* download all the images */
function downloadImages(data){
var imageList = data.IMAGELIST;
var imagePath = data.IMAGEPATH;
var imageName = "";
imageData.imagePath = imagePath;
imageData.imageList = [];
var colMap = new Object();
//create column map
for (var i = 0; i < imageList.COLUMNS.length; i++) {
colMap[imageList.COLUMNS[i]] = i;
}
for (var i = 0; i < imageList.DATA.length; i++) {
imageName = imageList.DATA[i][colMap["NAME"]];
imageData.imageList.push(imageName);
}
consoleLog('Total images to download: ' + imageData.imageList.length);
downloadImage();
}
/* download image syncronously */
function downloadImage(){
if(imageData.imageList.length > 0){
var imageName = imageData.imageList[0];
var imagePath = imageData.imagePath;
consoleLog('Start file download: ' + imagePath + imageName);
//check if file exists, pass the function as new closure, so the variable is preserved
imageDir.getFile(imageName, {create: false}, successImageExists, (function(name, path){
return function(){
failImageExists(name, path)
}
})(imageName, imagePath));
}
}
/* image exists */
function successImageExists(file){
consoleLog('Image Exists: ' + file.name);
updateImageDownloadProgress();
}
/* image doesn't exists */
function failImageExists(imageName,imagePath){
consoleLog('image does not Exists');
//start download
consoleLog('Download Image To: ' + imageDir.fullPath + '/' + imageName);
ft.download(imagePath + escape(imageName), imageDir.fullPath + '/' + imageName, onImageDownload, onImageDownloadFail);
}
/* on image download fail */
function onImageDownloadFail(error){
consoleLog('image not downloaded. Error: ' + JSON.stringify(error));
updateImageDownloadProgress();
}
/* on image download success */
function onImageDownload(image){
updateImageDownloadProgress();
}
/* update image download progress */
function updateImageDownloadProgress(){
imageData.imageList = imageData.imageList.slice(1);
consoleLog('images left to download: ' + imageData.imageList.length);
if(imageData.imageList.length == 0){
imagesDownloaded = true;
} else {
downloadImage();
}
}
Sumit, please please please use pasteBin in the future. :)
Sure, sorry :)
You can delete the earlier comment, if you want. Here is the paste bin version:
http://pastebin.com/kNvF166F
It's ok.
But... I will say this. Your implementation is not one I agree with. It looks like it would work, but you really should look at deferreds. It handles this much more elegantly.
If anything, you've convinced me to try to find time to update my demo. ;)
I agree, it can be done more elegantly using deferreds, but I didn't had time to play with that and this was a quick and easy solution (and it does work ;))...
Well maybe deferred is more elegant, but Sumit gave me good idea for a workaround if i am not able to get deferred to work.
If i get deferred to work i will let you know and post my solution.
Sumit, thx for giving me an good idea for a workaround.
Thx to both of you for the great support :-)
Another point wanted to mention is, if you are downloading lot of file that are large in size, synchronous download is your only option. The Async starts failing because I guess its too many threads for the device to handle (at-least in iOS).
Yeah, sorry if I sounded too negative. I can promise you that Sumit's working version is better than the one I haven't written yet. ;)
@Sumit, ist possible to see the rest of your code?
I guess you set some of the variables used in your code outside.
e.g.
downloadImages(data)v <= what does Data contain
imageDir. <= where and how is this defined
imageData <= same as above
Would be great if you could show me how you modified raymonds code to work with your example.
Sorry for bothering you again :-)
Thx for your great help.
Alex,
Data is a struct returned from CF.
data.imagePath = "http://domain.com/path/to/i..."
data.imageList = list of image names (converted to JSON from query by CF)
Imagelist comes from cfdirectory.
imageDir is the reference to image directory in FileSystem. Same as DATADIR in Ray's example.
imageData is a global JS variable to hold the image name array, as files are downloaded image names are removed from this array.
HTH,
Sumit
As a side note, Sumit, I tried your technique in a different context (basically I needed to single thread N ajax calls) and it worked well. Thanks.
Sumit,
so data.imageList is almost the same as Raymonds
$.get("http://www.raymondcamden.co...", {}, function(res) {
....
}, "json");
So what i could do is take your function downloadImages() and change it to:
function downloadImages(data){
var imagePath = 'http://path_to_my_files/';
$.get("http://path_to_my_JSON/json.php", {}, function(res) {
var imageName = "";
imageData.imagePath = imagePath;
imageData.imageList = [];
var colMap = new Object();
//create column map
for (var i = 0; i < res.COLUMNS.length; i++) {
colMap[res.COLUMNS[i]] = i;
}
for (var i = 0; i < res.DATA.length; i++) {
imageName = res.DATA[i][colMap["NAME"]];
imageData.imageList.push(imageName);
}
consoleLog('Total images to download: ' + imageData.imageList.length);
}, "json");
downloadImage();
}
My webpage (json.php) returns something like this:
["files.json","data.json","dates.json"] (the files i want to download)
Ist this what your column mapper expects?
Btw. just to give you a short explaination why i ask so much instead of trying it all by myself.
This is my first try with HTML5, javascript and phonegap. I promised a friend to help him with a little non commercial app and i will be on holiday by the end of the week for 4 weeks ;-)
Yes to all except column mapper. You don't need it if you are getting the data as array of file names. You can just set imageData.imageList to that array. I'm using column mapper because I'm converting a query object (with image name and date modified) in CF to JSON.
I gave it try:
http://pastebin.com/gZQXL8P3
but it breaks after
..console.log("Start downloading...");
within downloadImages()
Btw. the download process is still triggerd by the init() script from Rays example. Is this the best way to start the download and make the page "wait" until the download is finished and then move on or relocate to another page?
Oh my god, that was really stupid...
i used console.Log instead of console.log....
Alex - I do that a lot myself. Don't feel bad. :)
Hi, http://www.raymondcamden.co..."
in the code above what do you mean by : imagelister.cfc?method=listimages
I am going to use this code but only stuck at above line. i am new to phonegap and i9 need to synchronize images from remote server. please help.
That is a file on my ColdFusion server. It could be any technology - PHP, Ruby, whatever. For me, I used ColdFusion.
Hello Raymond
Good tutorial, very helpful. However, I still got error while file downloading. I copied all code to my project, when I run it on my real mobile (android 2.3.5), the error came out. It says:
-----
03-20 23:51:34.863: E/FileTransfer(16025): Error while downloading
03-20 23:51:34.863: E/FileTransfer(16025): java.io.IOException: Error while downloading
03-20 23:51:34.863: E/FileTransfer(16025): at org.apache.cordova.FileTran...(FileTransfer.java:429)
03-20 23:51:34.863: E/FileTransfer(16025): at org.apache.cordova.FileTransfer.execute(FileTransfer.java:102)
03-20 23:51:34.863: E/FileTransfer(16025): at org.apache.cordova.api.PluginManager$1.run(PluginManager.java:150)
03-20 23:51:34.863: E/FileTransfer(16025): at java.lang.Thread.run(Thread.java:1019)
-----
Any thoughts?
What are you downloading? Can you share all the code? (Via pastebin of course.)
The codes are copied from your post in fact..So the images it downloaded are same from the json. The json can interpret currectly not the issues happened via downloading. Tricky..
So to be clear, it dies on the actual file download? You see all the other (previous) status messages as the app starts up?
Yes, I can see correct JOSN response and "starting downloading xxx" in console. But the images weren't downloaded at all. I have checked the folder created by this app, nothing inside. Interesting problem... Drive me crazy..
What I'd recommend then is adding some console.log messages. You need to find out _exactly_ where it breaks.
Could I send email to you with screenshots? I'm using phonegap 1.5.
Screenshots won't help. Try what I recommended - using console.log to try to diagnose where exactly it's failing.
Hi, can i get the sample code for imagelister.cfc?method=listimages File so i come to know how exctly i should write code in my PHP file?
Also i have tried your server to check the code and try to download the images but only get the below message and then nothing happen...
Checking your local cache....
Shailesh: All it does is list the directory and create an array of file names. As to your error, best I can suggest is what I told Jerry, to try some console messages.
I've gotten reports that 1.5 may be an issue. Sometime today/this weekend I'll try to replicate.
I'm using a similar approach to $,get a JSON object containing a list of various URL resources to store down to my app. The files are put into various directories, mirroring the directory structure of the web server.
Is there a way to set the gotFIles() function to do a scandir type of action so it can also check all subdirectories for any matched files?
Well, anything should be possible - you can write code to recursively scan folders. I don't know of any examples of that yet though.
I was hoping there would be some file reader method that would recursively scan folders. I guess a home brew is in order on this one.
One other issue I have run into is finding a way to trigger an "all files finished downloading" event. I have tried inserting a callback function after the .get function, in the get function if the last resource has been reached, and a handful of other places. It seems that the callback function will execute after the JSON object is scanned, but before the actual download process completes. I'm looking for something similar to the FileWriter's property of readyState that can indicate a "DONE" state. I have really had a hard time finding any documentation on the File Transfer download method.
If you've got N sets of transfers, you need a way to handle all of those asyncs being done. Afaik, jQuery Deferreds provide a way of doing this, but I'm still wrapping my head around them.
Hi,
I have downloaded image in emulator and its works fine but somehow on real device it is not downloading the images. don't where it stuck... ?? any idea about that?
Thanks in advance.
I recommend making liberal use of console.log to try and diagnose where it is failing. You should be able to do this and see the failure.
Sumit, did you find a fix to the FileError.PATH_EXISTS_ERR? I'm running my code on Android via build.phonegap.com (phonegap 1.6.1) and I get this when I try to open my app's main directory that already exsists: fileSystem.root.getDirectory("com.example.myapp", {create: true, exclusive: false}, ...)
Forgot to mention that I run it on Android 2.3.7
@Gavriel
Yes, please see my earlier comment.
http://www.raymondcamden.co...
Sumit
I already had the exclusive: false. And it also turned out that the directory wasn't there. So it is probably a bug in build.phonegap.com's version. When I create the directory (for example with my app, but built in Eclipse with cordova 1.7.2, then it creates the directory) then it can open it.
However now my next problem: FileTransfer.download gives me ABORT_ERR. Any idea why? I'm trying to download a file to the TEMPORARY filesystem
adding to config.xml:
<feature name="http://api.phonegap.com/1.0..."/>
<access origin="https://mydomain.com" />
fixed it
Same Code dosen't work on my android 2.2 return me below message.
05-31 16:58:32.972: DEBUG/SntpClient(59): request time failed: java.net.SocketException: Address family not supported by protocol
Please help me where i am making mistake i am using phonegap 1.7.0 version which i have changed in the code this code is created on 1.3.0.
When does this error get thrown?
When i am running my application it thrown this error.
Right, but what you need to do is try to determine when in the application flow. Notice the console messages? They would give you an idea of when things fail. If you do not know how to read the console, see my other blog post on the topic.
I got this error from console log.
Right... but my point is this. Use the console to figure out _when_ the error occurs. What part of the process defined in the application.
Hey Raymond,
getting this errors in debugger....
06-07 17:04:23.250: DEBUG/CordovaLog(560): file:///android_asset/www/index.html: Line 47 : ERROR
06-07 17:04:23.250: INFO/Web Console(560): ERROR at file:///android_asset/www/index.html:47
06-07 17:04:23.250: DEBUG/CordovaLog(560): {"code":12}
06-07 17:04:23.250: DEBUG/CordovaLog(560): file:///android_asset/www/index.html: Line 48 : {"code":12}
06-07 17:04:23.250: INFO/Web Console(560): {"code":12} at file:///android_asset/www/index.html:48
06-07 17:04:28.110: DEBUG/dalvikvm(251): GC_EXPLICIT freed 160 objects / 11848 bytes in 258ms
and line number 47 and 48 is
function onError(e){
47=> console.log("ERROR");
48=> console.log(JSON.stringify(e));
}
You still aren't hearing me though. Do you understand that when you do console.log("X"), it prints it out to your console (and in your case, that is the debugger). My point to you is that you should add messages to the code so you can see -when- this error is thrown.
For example, you can put one in onDeviceReady, you can put one in appReady. You can put one before the $.get, in the closure, etc.
Your job here is to find out -when- error code 12 was thrown. I can't tell you this from here.
I have done this problem is because of whitelist so i have resolved this.
Now i need some thing like live progress in that page which show how much work left.
Hey Raymond,
Thanks for this great post.
Now i am confused that how can i create nested directory like this.
fileSystem.root.getDirectory("Android/data/com.phonegap.myapp/dir_one/dir_two/",{create:true},gotDir,onError);
and i need to make 3 directories always in each case in my script any solution.
Unfortunately, you have to do it step by step. So to make /a/b/c, you have to make a (if you need to), then b (if you need to), and so on. For more details, see this excellent article:
http://www.html5rocks.com/e...
Hi Ray,
Just wondering, could you see a modified version of this code working for grabbing videos from a host on to the local?
Could you file size issues being an issue
Kenji: To your first paragraph, it is no different. It should just work. To your second paragraph, I'm not quite sure I get what you are syaing.
Hello...
I am beginner on mobile apps, especially phonegap.
I just try the script above, but it goes error...
07-03 15:46:29.409: E/Web Console(811): Uncaught TypeError: Object [object Object] has no method 'download' at file:///android_asset/www/index.html:67
the line is :
ft.download("http://www.raymondcamden.co..." + escape(res[i]), dlPath, function(){....
what should I do?
Add a quick console.dir(ft) and see if ft is a proper object. It is supposed to be an instance of FileTransfer, which supports a download method.
Hi it's me again...
I just change the version of phonegap.jar and .js with the newest version.. and ft.download doesn't error anymore...
but, i got another one -_-, it said:
Could not find class 'android.webkit.WebResourceResponse', referenced from method org.apache.cordova.CordovaWebViewClient.generateWebResourceResponse
That's a new one for me. I'd suggest the PhoneGap Google group. Sorry.
Hey Raymond.
Looks like that your function renderPicture(path){
41 $("#photos").append("<img src='file://"+path+"'>");
42 console.log("<img src='file://"+path+"'>");
43}
Doesn't need file:// anymore, I defently just ran this, phonegap 1.9 + jqm. and it was included in path.
Thanks AMet.
Hi, Ray & Imas: Don't know if Imas is still looking for information regarding that error, but I don't think it's of consequence. I came across this https://issues.apache.org/j....
Hi, umm T.T
When I run the emulator, error has occurred.
Error -> code: 12
I was working on android 2.3 and 4.0
but I don't know that
When I work with my cell phone, there was no error.
I'm having a hard time parsing your comment. You say it works on a real device but not the emulator?
Yes
code dosen't work on emulator.
The getDirectory method keeps throwing error.
error code is 12
Hello,
I tried and I get "401 Unauthorized" on ft.download() method call.
Thanks !!
Hi again,
I had forgotten to add the test url on my config.xml as a whitelist
AndroidProject/res/xml/config.xml
Thanks a lot for your awesome piece of code ;-)
Julius
Ah so it is all good now?
I have weird problem testing on Android Device,
It stops on the Directory reader event, it doesn't show any error o success... it just stops and nothing happens.
Any idea?
Best I can recommend is using the console to try to track down where things are failing.
got it working, I read about the console a few minutes later of post, tnx!
Hello, could you tell me who is
"imagelister.cfc?method=listimages"? at URL: ("http://www.raymondcamden.co...")
I need to do something similar to read a list of images from my dropbox folder.
Thanks in advance!
It's ColdFusion code that scans a directory for images and returns a list of these files as a JSON-encoded array. It's no more than 5 or so lines of code.
Could you please give me a snippet? or tell me how to look for information about creating that file and please excuse the audacity!
To be clear, this is like 3 lines of code or so. I don't mind sharing, but do you know ColdFusion? Do you use ColdFusion for your server-side code?
I do not know ColdFusion, I'm a .Net developer, web inexperienced, and I'm going to develop web applications for mobile devices with PhoneGap.
I thought about doing a demo application to read my dropbox photos and displays them in a list.
Thank you very much, I'm going to read about ColdFusion.
Ah, so you know .Net, but not necessarily in terms of web apps? As much as I'd like to see you learn ColdFusion, you really don't need too. This should be trivial in _any_ language. It's literally just a directory listing into an array turned to JSON. Shouldn't be more than 5 minutes of work in .Net, PHP, etc.
yeah, just read some ColdFusion and you're right when you say that is not what I need right now ...
I think I'll fix it by creating an XML file with the metadata of the images, put the file in my dropbox folder, read the file and download images one by one.
Thank you very much for the info.
Sure, XML would be fine too. I just fine XML much more of a pain to deal with in JS. If you are hand crafting a file, why not hand write a JSON file? :)
You're right! thanks again...
I downloaded the list of pdf files from my server using file download, and able to view in my device during online mode. But I want to view the file during offline and also need to synchronize the files. Is there a way to do file synchronisation from the server using file download
So, yes, this is definitely possible, but it is a bit non-trivial. Not terribly complex, just involved. Let's break it down.
First, your app can work in offline mode easily enough. There is an API to check network status. Use that and if offline, then you just display the files already downloaded.
The sync aspect is more interesting. So if you are online, you can get the list of file onlines and compare to those on the app's file system. THe files not there - simple - download. If they match, it gets more complex. If the files are something the user can edit, then you need to provide a way to prompt the user about which is more fresh. If not, you could just download, but that is wasteful. So you may waht your remote system to return datestamps of the files as well and compare them to the local copies. That isn't going to be perfect either as the user's device time system will probably be in a different TZ then the server.
To handle that, you may wish to use something like LocalStorage or WebSQL to associate metadata with the files that can be compared to values on the server.
Raymond,
Great posting and comment thread.
Have you had any experience or luck with using PhoneGap's FileTransfer download in conjunction with dynamically delivered / served images.
I follow your code...
http://www.raymondcamden.co...
returns a list of image file names, and they're obviously appending to arrive at resources for FileTransfer to download such as:
http://www.raymondcamden.co...
That's all well and good, and I confirmed this sort of stuff worked for me back at the start of my project (basically I confirmed that PhoneGap download worked).
The problem for me is that danger.jpg ultimately is a static resource and served up to anyone who knows the URL.
Id rather not have my images, and documents available to constant and static locations, so I'm attempting to serve them up through a script.
The backend is PHP, but obviously it doesn't really matter what server side language is involved.
http://www.example.com/docu...
I've done this many times before, and browsers are fine receiving images from scripts as long as they also send out the appropriate content type header, file size, and buffer the output.
In my example url, 12 represents and ID of a document or image. There are a myriad of reasons why I want to do this, mostly from a security standpoint. My actual urls contain other arguments representing rotating hashes and client user identifiers, etc.
The problem is that PhoneGap's FileTransfer download seems to not work with these dynamically generated images (try your captcha for example). I can't seem to make them palatable for ft.download.
Have you successfully downloaded images, documents etc from a dynamic source?
Files are created in the simulator (iOS) and on the devices, but they're empty. Zero (0) bytes.
Interesting. So - not knowing PHP, but knowing CF, I know that if I were to generate a dynamic image I'd _also_ ensure I used the right headers. Is your PHP code sending the right headers back?
It was related to the headers... as far as I can tell this was related to additional headers (session related headers) that PhoneGap didn't like. Stripping the script down the bare minimum and taking it out of the context of the larger application seems to have addressed my issue. A working combination in PHP is as follows:
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Headers: X-Requested-With');
header( "Content-Type: image/png" ); // Or whatever is appropriate for the file
header('Content-Length: ' . filesize( $sExampleFile ) );
ob_clean();
flush();
readfile( $sExampleFile );
exit();
Interesting. I wonder what head it was? If you can ever figure out, let me know. In theory, session stuff shouldn't matter to a file request. Unless your PHP code was checking for a login and redirecting.
When i am using data/data in the place of Android/data i am getting error
the error code is 12.
Please help me.
According to the source code, 12 = path exists error. So your code is trying to make a path that already exists.
Could the same method be used for videos instead of images. If so what should I look out for?
It could be used for anything. All I'd watch out for is the size of what you download of course.
I have download working with FileTransfer, but on some devices I start getting the following in my debug and the downloads fail...
02-04 12:13:31.686: E/FileTransfer(2228): java.net.SocketException: Socket is closed
02-04 12:13:31.686: E/FileTransfer(2228): at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.checkOpen(OpenSSLSocketImpl.java:262)
02-04 12:13:31.686: E/FileTransfer(2228): at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:273)
02-04 12:13:31.686: E/FileTransfer(2228): at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:257)
02-04 12:13:31.686: E/FileTransfer(2228): at libcore.net.http.HttpConnection.setupSecureSocket(HttpConnection.java:210)
02-04 12:13:31.686: E/FileTransfer(2228): at libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.makeSslConnection(HttpsURLConnectionImpl.java:477)
02-04 12:13:31.686: E/FileTransfer(2228): at libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.connect(HttpsURLConnectionImpl.java:441)
02-04 12:13:31.686: E/FileTransfer(2228): at libcore.net.http.HttpEngine.sendSocketRequest(HttpEngine.java:282)
02-04 12:13:31.686: E/FileTransfer(2228): at libcore.net.http.HttpEngine.sendRequest(HttpEngine.java:232)
02-04 12:13:31.686: E/FileTransfer(2228): at libcore.net.http.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:80)
02-04 12:13:31.686: E/FileTransfer(2228): at libcore.net.http.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:164)
02-04 12:13:31.686: E/FileTransfer(2228): at org.apache.cordova.FileTran...(FileTransfer.java:463)
02-04 12:13:31.686: E/FileTransfer(2228): at org.apache.cordova.FileTransfer.execute(FileTransfer.java:87)
02-04 12:13:31.686: E/FileTransfer(2228): at org.apache.cordova.api.PluginManager$1.run(PluginManager.java:192)
02-04 12:13:31.686: E/FileTransfer(2228): at java.lang.Thread.run(Thread.java:856)
Have you seen this before? It is not consistent between all devices and I can't make it fail in the simulator, but a few devices do it about 70% of the time. I have the code set to only try to run one download at a time, but that doesn't seem to fix it entirely either.
I'm sorry - that doesn't look familiar. Could you try posting to the PhoneGap Google Group (and please post back here if you get a response!)
Hi - I could not download the files on device ready but i can download on any other event. It gives me error "File could not be found". I am using PhoneGap 2.4.0. Please help.
The error implies that it can't find the file you are trying to download. You are saying it works if you use another event? To be clear, the deviceready event is the only one you *must* wait for.
Hi, i ma new to Cordova, i got this error while runing in Android2.3.6. "Could not find class 'android.webkit.WebResourceResponse', referenced from method org.apache.cordova.CordovaWebViewClient.getWhitelistResponse" Any solution for this. thanks in advance...
hi, i am again. Cordova working in Android 4.x.. but i dont know why.? if know any one about this. please explain. thanks!!!
I was able to use the code above for synchronous downloading that Sumit Verma (http://www.blogonria.com/) had posted, modified it a bit and got it working for iOS pastebin.com/cMJYAgu1
Hi Raymond, I tried your example, but it's not doing anything for me. I replaced com.camden.imagedownloaddemo with my own path, but no success. The images aren't visible and the Console Logs are even empty.
When console.log fails me - I go back to the old school sucky alerts. I'd suggest adding some in and seeing if you can trace down exactly where the error occurs. You can also try Weinre.
The debugger; statement is your friend.
That's not going to work - by itself - in PhoneGap.
Added alerts, but no success...
So you get *nothing*? Even if you put an alert as the first line of JS code? You mind sharing your JS via a Gist or Pastebin.
Oh god, never mind, I should stop coding so late at night. I forgot to replace the cordova version. It's working now! Thanks for your help and your tutorial!
It happens - good luck.
Okay, I'm back. Just wondering how I would go about downloading a folder with different types of files, like for examples images, JSON- & jsfiles. Any idea?
By default, your web server should NOT be responding to a / request with a directory index, so it wouldn't work out of the box. What I've done in the past is to build server side code to handle this. So I may ask for "latestimages" (as a parameter to my server side code), it hits a particular folder, gets a list of files, and returns it as a JSON-encoded array. Then your PG code needs to loop over them and grab each.
I've actually got an example of this for images - but I can't remember the blog entry title offhand. Maybe just search for phonegap.
Fixed it! Now just one question left, is there a way to delete files that aren't used in the app anymore?
FileSystem API, right?
Yes ^^
So - are you agreeing you should use it? :) Just to be clear - I was saying - use the FS API. It can remove stuff from the file system.
hi,
am using phone gap to download lots of files and it keeps telling me some files failed to download with time out error, thats on ios. is there a way i can increase the timeout cus it seems to time out after 60 secs. or any fix i can do
So to be clear, you are getting random errors? Or is it normally on larger files?
its same error on large files
this is the issue on http://stackoverflow.com/qu...
am the developer working on it
I posted a comment on the SO link. I have a slightly different approach that does work for me.
i also have this error, not sure if its ios or phone gap, times out after 60sec, wish someone could tell me how to solve this!!!!!
FileTransferError {
body = "";
code = 3;
"http_status" = 0;
greg i read you comment, for me am getting a list of files from an ajax post then i loop through to get each image and call filetranfer.download, but some of the files time out same kind of error like jack has, i output the error and i get some files timed out with code 3 error http_status = 0. but if i use a lan network no a wifi it works nice only fails on ios and wifi connection always times out after 60 secs of starting the download.
Does it give you the error after 60 sec of a single filetransfer.download or after 60 sec of total downloading time?
60 sec of total download, even if i use a single file and it takes more then 60 secs it times out,
Are you doing the downloading synchronously or async? I have it working synchronously.
Is there a way to let the system download the files everytime there's internet connection?
@Anneleen: In theory, it is just as simple as removing the logic that only gets "new" files. Is that what you meant?
Oh, thanks for the tip, I finally got it working! ^^
I am getting the following error while downloading image
javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
Are you talking to a server using HTTPS?
Yes...I am making an ajax request to a self signed (https) server which got some certification error...Whenever I try to download from some other http/https server then its allow same with the similar code...
Since I am new to phone gap and eclipse, I am not able to handle such kind of exception..
My logcat is loaded with more error message but just providing you an selected Error message :
Caused by: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found
xnet.provider.jsse.OpenSSLSocketImpl.verifyCertificateChain(OpenSSLSocketImpl.java:664)
I have used your above code for reference but still made no luck :(
There is an option to trust all hosts (self signed certs included). See the docs: http://cordova.apache.org/d...
I saw someone mention they were getting error 12 on getDirectory - and the error states the folder already exists. I'm getting this same error...
This isn't making sense to me - isn't getDirectory supposed to return the folder - even when the create flag is on? So that if the folder exists it's not created otherwise it is... If getDirectory() returns an error how to get the directory?
Also, looking in File explorer, I don't see the folder I am trying to create. I am using:
fileSystem.root.getDirectory("Android/data/com.gmrmarketing.healthy.re...", {create:true}, gotDir, gotError);
Little more on this - if I set create:true then I get error 12. If I set create:false I get error 1. I'm not sure what error 1 is, but have been at this for a while and would really like to be able to get a directory object.
Try the second option attribute, exclusive, and set it to false.
http://cordova.apache.org/d...
Thanks much for replying. Adding the flag doesn't seem to matter - with create:false I just get error: 1 as before and 12 with create true. This is quite frustrating, as I've got an approaching deadline and this seeming simple thing is taking way too long. Is there any device restrictions for this? The phone I'm testing on is an older LG Optimus V with Android 2.2.2 on it..
Finally I resolved my SSL certificate error by inserting a few line of code which actually work for me...
public class MainActivity extends DroidGap {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
super.setIntegerProperty("loadUrlTimeoutValue", 15000);
super.setStringProperty("loadingDialog", "loading your app...");
super.loadUrl("file:///android_asset/www/index.html");
//Call the fuction
trustEveryone();
}
public void trustEveryone() {
try {
HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier(){
public boolean verify(String hostname, SSLSession session) {
return true;
}});
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, new X509TrustManager[]{new X509TrustManager(){
public void checkClientTrusted(X509Certificate[] chain,
String authType) throws CertificateException {}
public void checkServerTrusted(X509Certificate[] chain,
String authType) throws CertificateException {}
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}}}, new SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(
context.getSocketFactory());
} catch (Exception e) { // should never happen
e.printStackTrace();
}
}
}
Doesn't seem to be a Android version issue. I tried the same code on one of the emulators at manymo.com and got the same error:1
Is there anywhere that describes how to get a folder within your installed application folder?
dmen - best I can suggest for now is - use what you are supposed to (create true and exclusive false) and if you still get 12, log a bug report. It should be working and if you can create a reproduceable case, you can then file a bug report.
Btw - something else to consider. Your path is this:
"Android/data/com.gmrmarketing.healthy.re..."
First - I think you need a / in front, don't you?
Second... and actually I change my mind - I don't think this is an issue - but I'll mention it anyway. You can't create N level deep stuff. Ie, "foo/moo" where both foo and moo don't exist. Last time I checked, if you needed to make 2 levels of folders deep, you had to make foo, then moo.
But I don't think that one is your issue.
Hi Raymond, thanks so much for helping me on this. I've managed to finally get it working, though I'm still not entirely sure why.
I moved the call to window.requestFileSystem into the deviceReady callback and it's working now. Originally, I had that call within another function that returned some xml. Not sure why it preferes to be in deviceReady but it's working - and I am using create:true, exclusive:false
Thanks!
"I moved the call to window.requestFileSystem into the deviceReady callback and it's working now. "
Woah... dude... seriously.... you know *all* PG stuff should be done after deviceReady, right? I assumed it was so well known that I never would have imagined you doing so without it.
I didn't mean to say it wasn't after deviceReady - it was. I got deviceReady and then I looked for an update xml file... if that file exists I then went ahead and do the requestFileSystem. That's what I was doing... which still seems it would work.
this is my code
<script type="text/javascript">
function onBodyLoad(){
document.addEventListener("deviceready", onDeviceReady, false);
}
function onDeviceReady() {
alert("device is ready");
window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem;
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, gotFS, fail);
downloadImage('http://upload.wikimedia.org...
}
function fail() {
alert("failed to get filesystem");
}
function gotFS(fileSystem) {
alert("got filesystem");
// save the file system for later access
alert(fileSystem.root.fullPath);
window.rootFS = fileSystem.root;
}
function downloadImage(url, fileName){
var ft = new FileTransfer();
alert(window.rootFS.fullPath + "/DCIM/Camera/" + fileName);
ft.download(
url,
// window.rootFS.fullPath + "/DCIM/Camera/" + fileName,
"/sdcard/DCIM/Camera/" + fileName,
function(entry) {
alert("download complete: " + entry.fullPath);
},
function(error) {
alert("download error" + error.code);
}
);
}
</script>
this code shows the message downloaded and file paht, but i can't find file in phone storage or sd card.
can you help me on this?
Not sure what to say. If you get a successful file down load and even see the path, then it should be there.
Hi,
The issue was , file was not showing in the folder, while the app was running and phone was attached with USB, when i reconnected with usb file appears in the folder..
one more question
for android i am using like
ft.download(
url, // mp3 path live
"/sdcard/DCIM/Camera/" + fileName, // phone storage folder path
will same path work for IOS? i am running on android and its working.. not sure about iphone for the path.
Thanks,
Mayank.
I can never remember paths for iOS. Dumb question - but did you try it?
hi,
i need to do download a file and save it on the local memory i have used your code but it calls only init method.
please help how to fix this
Sabarish, if you are the same person who emailed me, I'll reply there.
Hello,
I got error in this line :
$.get("http://www.raymondcamden.co...", {}, function(res) {
error msg: undefined $
I removed it then I got undefined "get"
who can I solve that?
If $ is undefined it means jQuery didn't load. Double check your script tag for it.
yes I fixed it, but I got this error :
FileTransfer is not defined
this error in this line: var ft = new FileTransfer();
Do you have any idea?
You need to add the FileTransfer plugin.
Yes, you are right, but the Error I got now:
07-12 23:56:40.180: E/(398): unsupported multiclient unsolicited response code 1009
07-12 23:56:41.870: E/FileTransfer(13259): {"target":"\/\/Android\/data\/com.camden.imagedownloaddemo\/cfguy.png","http_status":200,"code":1,"source":"http:\/\/images.wisegeek.com\/young-calico-cat.jpg","exception":"\/Android\/data\/com.camden.imagedownloaddemo\/cfguy.png: open failed: ENOENT (No such file or directory)"}
Can you share what line this error is thrown on?
AI think this is the line:
ft.download("http://www.raymondcamden.co..." + escape(res[i]), dlPath, function(){
in the target directory
Not sure. The error message above mentions a different URL. Um, I'd have to dig into your app myself to help more. Sorry, I can't do that right now.
Hii, i tried your code but it's only calling the init method and not the other. Please help.
Is there any way to download files via a POST request? I.e., specify the URL and certain parameters to pick the file, and then go down the usual download pathway. Thanks,
@Akashdeep: If onDeviceReady is not firing, ensure you are using cordova.js (or phonegap.js) in your HTML. Also - do remote debugging to see if you have some other error.
@Scott: From what I see of the docs it does NOT look possible. In theory you could do a POST with XHR and save the bits using the FIleSystem API.
The problem is that they are too large to store in memory (50 MB) as an AJAX call would require. I was hoping to try this to see if this provided a buffered approach.
I just checked the code (well the Java code) and it is definitely set to GET w/ no way around it. Best I can suggest is filing an issue for it.
Hii i was calling the script twice that was creating the error. It's running now bt the image are not getting replace by the new one.. any idea on that. I tried your URL it download the images but didnt replace them plus they are not getting shown in the img src
@Akashdeep: I'd check with remote debugging to see if you can figure it out. I really can't tell from here.
@raymond thank you for responding to the query. Just one last doubt. When i am downloading the pic i get the ERROR like {"code":1, "Source": source url; "target": target url, http status :null, body:null}. I want to know if you have used any other extra plugins. Because the folder are getting created but the file not getting replace. And do we need file in folder before we download. Please help in this. Thank you i advance. If you time we can talk via skype that would be a real help full
Hi Raymond, nice tutorial , it's been really helpfull for me, but I'm having the same problem that Akashdeep.
@Akashdeep I've fixed it with a couple of changes to the code here's a Pastebin of the code:
http://pastebin.com/hc6XpHgz , hope it helps you!
@Rolando i was able solve the problem in an other way. I googled a lot and found that the code written by the Raymond is for rooted device and for the device that are not rooted can't used the path define in the code. I will soon paste the code wid some edits. Thank you @rolando :D
Glad you guys got it - was out of town.
Hi Ray..
Where i can find the code for above to download.
Thanks
There isn't a separate download. All of the important code is in the blog entry.
Hello is this thread still active! i need help with my file download script it is throwing a java FileNotFound exception the code is -> http://pastebin.com/fPZTB2i2
Hello Ray,
Is it possible to do a file transfer it via USB? Nonetwork or any other form. Just connecting the phone (iOS/Android) and copy files from PC -> Mobile and Mobile -> PC
Thanks.
Hmm - I don't know honestly. I'd imagine there are some pretty strict security concerns there - you don't want a random app just getting full access to your file system.
Hi Raymond,
I recieve the image as Binary String. How can I store this in sqlite, the images are about 5 mb size.
Don't. You can, if you convert to Base64, but use the file system for images.