Over a million developers have joined DZone.

Using the Progress event in PhoneGap file transfers

DZone's Guide to

Using the Progress event in PhoneGap file transfers

· Mobile Zone
Free Resource

Get gorgeous, multi-touch charts for your iOS application with just a few lines of code.

Earlier today I was happy to hear that PhoneGap 2.7 was released. While perusing the changelist, I thought I read that progress events for file transfers were added in this release. However, I was wrong. FileTransfer has supported a progress event for a few months now. But since I figured this out while halfway through a demo, I figured I'd finish it up anyway and share it on my blog.

As you can imagine, the onprogress event is a property of the FileTransfer object. It is passed a progressEvent that is - unfortunately - not documented as far as I can see. The code example though gives you enough information I think to deal with it:

fileTransfer.onprogress = function(progressEvent) {
    if (progressEvent.lengthComputable) {
      loadingStatus.setPercentage(progressEvent.loaded / progressEvent.total);
    } else {

So from what I can see - you get a property that determines if the total size is known, and if so, you can get a percentage by using it with the loaded property. Otherwise you're just guessing at the time left, but at least you know something is going on.

For my demo, I thought I'd build a simple MP3 downloader/player. I googled for 'free open source music' and came across this incredible MP3 by Kansas Joe McCoy and Memphis Minnie: When the Levee Breaks. Go ahead and listen to it. As much as I love indie music and trance, the sound of old recordings like this is like pure gold to the ears.

Anyway - I began by creating an incredible simple web page. It lists the name of the artists and the song along with a picture. I've included a button that will trigger the download. Also make note of the status div I'll be using for - you guessed it - progress events.

<!DOCTYPE html>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
        <meta name = "format-detection" content = "telephone=no"/>
        <meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width" />
        <link rel="stylesheet" type="text/css" href="css/index.css" />
        <title>FileTransfer Test</title>

        <div id="content">
            Kansas Joe McCoy and Memphis Minnie – "When The Levee Breaks"

  		<img src="img/KansasJoeAndMemphisMinnie.jpg">
            <button id="startDl" disabled>Click to Download and Play</button>
	<div id="status"></div>
        <script type="text/javascript" src="cordova.js"></script>
        <script type="text/javascript" src="js/index.js"></script>

Here's a screen shot of it in action.

Ok, now let's take a look at the code.

document.addEventListener('deviceready', deviceready, false);

var buttomDom;
var statusDom;
var fileSystem;

function deviceready() {
    console.log('dv ready');
	//step one is to request a file system	
	window.requestFileSystem(LocalFileSystem.TEMPORARY, 0, 
		function(fs) {
			fileSystem = fs;
			buttonDom = document.querySelector('#startDl');
			buttonDom.addEventListener('touchend', startDl, false);
			statusDom = document.querySelector('#status');
		}, function(e) {
			alert('failed to get fs');

function startDl() {
    var ft = new FileTransfer();
    var uri = encodeURI("http://archive.org/download/Kansas_Joe_Memphis_Minnie-When_Levee_Breaks/Kansas_Joe_and_Memphis_Minnie-When_the_Levee_Breaks.mp3");

	var downloadPath = fileSystem.root.fullPath + "/download.mp3";

	ft.onprogress = function(progressEvent) {
		if (progressEvent.lengthComputable) {
			var perc = Math.floor(progressEvent.loaded / progressEvent.total * 100);
			statusDom.innerHTML = perc + "% loaded...";
		} else {
			if(statusDom.innerHTML == "") {
				statusDom.innerHTML = "Loading";
			} else {
				statusDom.innerHTML += ".";
	ft.download(uri, downloadPath, 
	function(entry) {
		statusDom.innerHTML = "";
		var media = new Media(entry.fullPath, null, function(e) { alert(JSON.stringify(e));});
	function(error) {
		alert('Crap something went wrong...');	

Starting from the top, the first thing that may interest you is the file system request. I ask for the temporary file system so I have a place to store the mp3. Once I've got a hook to the file system I then enable the button in my web page and start listening for a touch event.

The function that handles the download, startDl, creates the FileTransfer object and points it to the remote MP3. I've used almost the exact same onprogress event as demonstrated in the PhoneGap docs. I changed it to write out a percentage when possible and in other cases, simply append dots to the end of a string. That way people know something is still being transferred.

The final portion simply handles the media portion. I didn't bother adding any real controls so it just begins to play the track and that's it. (To be clear, this wouldn't be hard to add, just check the Media API for more information.)

Watch the video below to see it in action:

As a last tip, note that the docs for Media seem to imply the you need a URI, not a file path. On iOS it seems to require a path, not a URI. Thanks to Simon MacDonald for helping me with this.


.Net developers: use Highcharts, the industry's leading interactive charting library, without writing a single line of JavaScript.


Published at DZone with permission of Raymond Camden, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}