Program odtwarzający audio w Phonegap
W tutorialu stworzymy prosty odtwarzacz audio. Wykorzystam tym razem jQuery Mobile, aby nie zaprzątać sobie głowy interfejsem użytkownika. Będziemy wykorzystywać obiekt Media oraz w późniejszym etapie również File.
Do wygenerowanego kodu dodajemy linie załączające jquery mobile. Samo jquery mobile powinno zostać automatycznie umieszczone w katalogu
assets/www/jquery.mobile projektu. Usuwamy też wygenerowany kod z ostatniego znacznika script i z sekcji body. Tworzymy i załączamy do strony
nowy plik player.js, w którym znajdować się będzie cała logika aplikacji.
<!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>Simple Audio Player</title>
<link rel="stylesheet" href="jquery.mobile/jquery.mobile-1.1.0.css" type="text/css">
<script type="text/javascript" src="jquery.mobile/jquery-1.7.2.min"></script>
<script type="text/javascript" src="jquery.mobile/jquery.mobile-1.1.0.js"></script>
<script type="text/javascript" charset="utf-8" src="cordova.js"></script>
<script type="text/javascript" charset="utf-8" src="player.js"></script>
</head>
<body>
</body>
</html>
Kod html, którego będziemy używać wygląda następująco. Po więcej informacji na temat użytej składni odsyłam na stronę jQuery Mobile.
<body>
<div data-role="page" id="page">
<div data-role="header" data-nobackbtn="true">
<h1>Simple Audio Player</h1>
</div>
<div data-role="content" id="content-manual">
<div data-role="button" id="play">Play</div>
<div data-role="button" id="pause">Pause</div>
<div data-role="button" id="stop">Stop</div>
<div class="ui-grid-a">
<div class="ui-block-a">Current: <span id="position">0 sec</span></div>
<div class="ui-block-b">Total: <span id="duration">0</span> sec</div>
</div>
</div>
</div>
</body>
Javascript zawarty w pliku player.js jest zaczerpnięty z dokumentacji phonegap.
// Audio player
var audio_file = null;
var mediaTimer = null;
// duration of media
var dur = -1;
// need to know when paused or not
var is_paused = false;
//set audio position on page
function setAudioPosition(position) {
$("#position").html(position + " sec");
}
//onSuccess callback
function onSuccess() {
setAudioPosition(dur);
clearInterval(mediaTimer);
mediaTimer = null;
if(audio_file !== null) audio_file.release();
audio_file = null;
is_paused = false;
dur = -1;
}
//onError callback
function onError(error) {
alert('code: ' + error.code + '\n' + 'message: ' + error.message + '\n');
clearInterval(mediaTimer);
mediaTimer = null;
audio_file = null;
is_paused = false;
setAudioPosition("0");
}
function playAudio(src) {
if (audio_file === null) {
$("#dur").html("0");
$("#position").html("Loading...");
// Create Media object from src
audio_file = new Media(src, onSuccess, onError);
// Play audio
audio_file.play();
} else {
if (is_paused) {
is_paused = false;
audio_file.play();
}
}
// Update audio_file position every second
if (mediaTimer === null) {
mediaTimer = setInterval(function() {
audio_file.getCurrentPosition(
// success callback
function(position) {
if (position > -1) {
setAudioPosition(Math.round(position));
if (dur <= 0) {
dur = audio_file.getDuration();
if (dur > 0) {
dur = Math.round(dur);
$("#duration").html(dur);
}
}
}
},
// error callback
function(e) {
alert("Error getting pos=" + e);
}
);
}, 1000);
}
}
//Pause audio
function pauseAudio() {
if (is_paused) return;
if (audio_file) {
is_paused = true;
audio_file.pause();
}
}
//Stop audio
function stopAudio() {
if (audio_file) {
audio_file.stop();
audio_file.release();
audio_file = null;
}
if (mediaTimer) {
clearInterval(mediaTimer);
mediaTimer = null;
}
is_paused = false;
dur = 0;
}
$('#page').live('pageinit',function() {
$("#play").on('tap', function() {
var src = 'http://designconcept.webdev20.pl/arts/audiovisual_media_queries/music/fl1.mp3';
// local (on device): copy file to project's /assets folder:
//var src = '/android_asset/fl1.mp3';
playAudio(src);
});
$("#pause").on('tap', function() {
pauseAudio();
});
$("#stop").on('tap', function() {
stopAudio();
});
});
Rozbudujemy teraz odtwarzacz o listę plików muzycznych na urządzeniu. Po kliknięciu na nazwę pliku rozpocznie się odtwarzanie
wybranego utworu. Wykorzystamy do tego File.
Dodatkowy kod javascript w pliku to
var files_arr = [], extensions = ['.mp3', '.ogg', '.wav', '.m4a'];
function getFiles(path, recursive, level) {
if(level === undefined) {
level = 0;
}
var directoryEntry = new DirectoryEntry('', path);
if(!directoryEntry.isDirectory) {
return null;
}
var directoryReader = directoryEntry.createReader();
directoryReader.readEntries(
function(entries) {
var ext;
for(var i = 0; i < entries.length; i++) {
if(entries[i].name === '.')
continue;
ext = entries[i].name.substring(entries[i].name.lastIndexOf('.'));
if(entries[i].isDirectory === true && recursive === true)
getFiles(entries[i].fullPath, recursive, ++level);
else if(entries[i].isFile === true && $.inArray(ext, extensions) >= 0)
{
app_name = entries[i].name;
app_fullpath = entries[i].fullPath;
files_arr.push({'app_name':app_name, 'app_fullpath':app_fullpath});
}
}
},
function(error) {
console.log('Unable to read the directory. Error code: ' + error.code);
}
);
}
function fileslist() {
window.requestFileSystem(
LocalFileSystem.PERSISTENT,
0,
function(fileSystem){
var root = fileSystem.root;
files_arr = [];
getFiles(root.fullPath, true);
},
function(error){
alert('File System Error: ' + error.code);
}
);
}
//Wait for device API libraries to load
document.addEventListener("deviceready", onDeviceReady, false);
// device APIs are available
function onDeviceReady() {
fileslist();
var $ul = $('#files');
for(var i=0; i<files_arr.length;i++) {
$ul.append('<li><a href="#" data-src="'+files_arr[i].app_fullpath+'">'+files_arr[i].app_name+'</a></li>');
}
$('#files').listview('refresh');
$('#files li a').on('click', function() {
playAudio($(this).data('src'));
return false;
});
}
Natomiast w pliku index.html wystarczy dopisać do diva o id content:
<ul id="files" data-role="listview" data-inset="true"> </ul>W liście tej będziemy wyświetlać nazwy plików muzycznych z urządzenia. Ważne jest aby wszelkie działania wykonywać jeśli api są już załadowane i urządzenie jest gotowe czyli w zdarzeniu deviceready. Funkcja getFiles rekursywnie przechodzi przez podkatalogi podanej ścieżki i zapisuje nazwy oraz ścieżki do plików muzycznych w tablicy. Po zapisaniu wszystkich plików dodajemy je do naszej listy ul i ją odświeżamy. Ponadto do każdego elementu a listy dodajemy zdarzenie click wywołujące odtwarzanie utworu dla określonej ścieżki. Pliki index.html i player.js można pobrać stąd.
Dodatkowe wskazówki i materiały:Debugowanie aplikacji
Jeśli chcemy testować działania na systemie plików na emulatorze musimy wgrać jakieś pliki do katalogu storage/sdcard emulatora. W tym celu należy uruchomić emulator. Przejść na perspektywę DDMS w Eclipse (Window > Open Perspective > DDMS). Potem wejść na zakładkę File Explorer i dodać do katalogu storage/sdcard jakieś pliki z dysku. W tym celu zaznaczamy katalog sdcard i klikamy ikonę "Push a file onto the device".
Jeśli chcesz dowiedzieć się więcej na temat Phonegap i Androida polecam zapoznanie się z ebookiem Phonegap dla Androida od podstaw.
