Статьи

Использование события Progress в передаче файлов PhoneGap

Ранее сегодня я был рад услышать, что PhoneGap 2.7 был выпущен. Просматривая список изменений, я подумал, что прочитал, что в этом выпуске были добавлены события прогресса для передачи файлов. Однако я был не прав. FileTransfer поддерживает событие прогресса уже несколько месяцев. Но так как я понял это в середине демонстрации, я решил все же закончить и поделиться им в своем блоге.

Как вы можете себе представить, событие onprogress является свойством объекта FileTransfer. Передача progressEvent, который, к сожалению, не задокументирован, насколько я вижу. Хотя пример кода дает вам достаточно информации, я думаю, чтобы иметь дело с этим:

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

Итак, из того, что я вижу, вы получаете свойство, которое определяет, известен ли общий размер, и, если это так, вы можете получить процент, используя его с загруженным свойством. В противном случае вы просто догадываетесь в оставшееся время, но, по крайней мере, вы знаете, что что- то происходит.

Для моей демонстрации я подумал, что я бы собрал простой MP3 загрузчик / плеер. Я погуглил «бесплатную музыку с открытым исходным кодом» и натолкнулся на этот невероятный MP3, созданный Канзасом Джо Маккой и Мемфисом Минни: Когда разрывается дамба . Иди и послушай это. Как бы я ни любил инди-музыку и транс, звучание таких старых записей похоже на чистое золото для ушей.

Во всяком случае — я начал с создания невероятно простой веб-страницы. В нем перечислены имена артистов и песни вместе с картиной. Я включил кнопку, которая будет запускать загрузку. Также запишите статус div, который я буду использовать для — как вы уже догадались — событий прогресса.

<!DOCTYPE html>
<html>
    <head>
        <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>
    </head>
    <body>

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

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

Вот снимок экрана в действии.

Хорошо, теперь давайте посмотрим на код.

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);
			buttonDom.removeAttribute("disabled");
	
			statusDom = document.querySelector('#status');
		}, function(e) {
			alert('failed to get fs');
			alert(JSON.stringify(e));
		});
}

function startDl() {
    buttonDom.setAttribute("disabled","disabled");
	
    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));});
		media.play();
		
	}, 
	function(error) {
		alert('Crap something went wrong...');	
	});
		
	
}

Начиная сверху, первое, что может вас заинтересовать, — это запрос файловой системы. Я прошу временную файловую систему, чтобы у меня было место для хранения mp3. После того как я получил доступ к файловой системе, я включаю кнопку на своей веб-странице и начинаю прослушивать сенсорное событие.

Функция, которая обрабатывает загрузку startDl, создает объект FileTransfer и указывает его на удаленный MP3. Я использовал почти то же событие onprogress, которое продемонстрировано в документах PhoneGap. Я изменил его, чтобы выписать процент, когда это возможно, а в других случаях просто добавляю точки в конец строки. Таким образом, люди знают, что что-то все еще передается.

Последняя часть просто обрабатывает медиа часть. Я не удосужился добавить какие-либо реальные элементы управления, так что он просто начинает играть трек и все. (Чтобы было ясно, добавить это не сложно, просто проверьте Media API для получения дополнительной информации.)

Посмотрите видео ниже, чтобы увидеть его в действии:

В качестве последнего совета обратите внимание, что документы для Media, похоже, подразумевают, что вам нужен URI, а не путь к файлу. На iOS, кажется, требуется путь, а не URI. Спасибо Саймону Макдональду за помощь в этом.