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.
![Nowy projekt z jquery mobile](/arts/105/audio_player_new_project.png)
<!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.
![Simple Audio Player w emulatorze](/arts/105/simple_audio_player.png)
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".
![DDMS File Explorer](/arts/105/ddms_fileexplorer.png)