You don't need to use platform-specific technologies to develop powerful and engaging apps. This series will teach you how to create a hybrid app - specifically an audio player - using web technologies and frameworks like jQuery Mobile and Cordova (also known as PhoneGap). The first framework will be used to create the interface, while several of the APIs of the second, like Media and File, will be used to develop the business logic.
The Project Features
The app we'll start developing in a few moments will be a basic audio player called Audero Audio Player. It will have minimal utility requirements. This app will search through the file system and collect any audio files, which the user can then listen to. The app will collect files with any of the following extensions: .mp3, .wav, .m4a. Keep in mind that the formats supported depend heavily upon the platform from which you run the application, so choose formats that work in many platforms.
Audero Audio Player also enables the user to update the list at any time to include other files that they may have downloaded after running the operation for the first time. The user can also remove any unwanted audio from the list by clicking the icon on the right side of the audio's name. The list is ordered alphabetically with letter dividers to organize and group list items. The list has a search box to filter the files as well.
You can see the described page by looking at the screenshot below:
Once the user chooses a file, the player's controller will then be shown. The controller shows the file name, location path, playing time and duration. It includes buttons for play/pause, stop, and a slider to move the audio back and forth.
You can see the look and feel of the player in the photo below:
The following list will give you a detailed understanding of what we'll be utilizing:
- HTML: It will be used to create the markup of the pages. When appropriate, I will use some of the new HTML5 tags.
- CSS: Most of the CSS enhancements will be done by jQuery Mobile, so I will only be using a few lines of custom CSS code. It's mainly used for the player itself.
- jQuery: I will use jQuery mainly to select elements and attach event handlers.
- jQuery Mobile: It will be used to enhance the application interface and optimize it for mobile devices. Some of the widgets used include Listview, Dialog, and Slider. I will also put some buttons inside the header and footer of the pages to build a simple toolbar. The version used is 1.3.0.
- Cordova (PhoneGap): Cordova will be used to wrap the files so you can compile them as if you built a native app. To build Audero Audio Player we'll take advantage of several of the APIs offered by the framework, such as Storage, InAppBrowser, Notification, File and Media. The version used is 2.3.0.
In addition to the above list, I'll use also these Cordova APIs:
- File API: An
API to read, write and navigate file system hierarchies, itprovides a set of objects to work with files and directories. For example, we'll use the
DirectoryReaderobject to navigate the file system, using its method
readEntries(), and search the sounds. We'll also use the
LocalFileSystemobject to obtain the root file systems of the device using its
requestFileSystem()method. You can find more information in the File API official doc.
- InAppBrowser API: It's
a web-browser shown in your app when you use the. It isn't much more than that but, as you'll discover later in this article, managing external links properly with this API is of vital importance. If you want to read more about the methods offered by this API, you can take a look at the InAppBrowser official doc.
- Storage API: This API provides access to the device's storage options. We'll specifically be using the Cordova implementation of the Web Storage API and its methods to store and load the list of the audio files. In case you need an in-depth explanation, refer to the Local Storage API doc.
- Media API:
The Media object provides the ability to record and play back audio files on a device.This is a key API for our player and we'll use almost all of its methods. For example, we'll use the
play()method to play the sounds, the
stop()method to stop playing the audio, and the
getDuration()method to retrieve the duration of the current processed file. More on this topic can be found in the Media API docs.
- Notification API: It allows you to notify the user with visual and audible notifications. We'll use its
alert()method to notify the user in case of errors. For a more in-depth overview on this API, read the Notification API docs.
The Project's Structure
Now that you have set up the framework, you can proceed to the next step. In the root of the project folder, we'll create the HTML files, and place the default application's icon, the Adobe PhoneGap Build configuration file, and the default splash screen. In this tutorial we'll also create the following files:
- index.html: This is the entry point of the application and where we will put the links to the libraries used, inside the
- files-list.html: This is the page where you'll have a list of the sounds stored on your device, grouped as I explained back in the introduction of this article. As you'll see later, you'll also have a little toolbar that allows you to go back to the homepage (the button in the upper-left corner) and to refresh the sounds list (the button in the upper-right corner).
- player.html: This simply contains the markup of the audio player.
- aurelio.html: This is the app credits page; it contains information about the app's author.
- style.css: This file contains the few custom lines of CSS used by the app, which are mainly used to style the player buttons.
- jquery.mobile.config.js: This will contain our custom configuration for the jQuery Mobile framework.
- appFile.js: This file contains the class called
AppFilethat we'll use to manage the sounds. It acts as an interface for the files table of our database. This class also allows us to retrieve and edit audio information in addition to allowing us to add and delete files from the stored list.
- player.js: The file including the class, called
Player, that manages the player and resets the player interface.
- utility.js: This is just a couple of utility functions used by our project, which I'll explain further in the next article of the series.
- application.js: This is like a glue that merges all of the pieces of our project together. This class is responsible for initializing the behavior of the pages described before attaching events using the classes seen thus far.
- config.xml: This XML file will have the metadata of the application and will be used by the Adobe cloud service to store settings like the app version number and its description.
This is a lot of stuff to create, but I promise you'll have a good time with this project. As a final note, in addition to the listed files, Audero Audio Player will include some additional images - like the play/pause and stop buttons - that will be placed in the "images" folder.
index.html. This page, apart from being the application's title and description, has a button to access the sounds list. It also includes a footer with a button to access author info.
The full source of the homepage is shown below:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Audero Audio Player</title> <link rel="stylesheet" href="css/jquery.mobile-1.3.0.min.css" type="text/css" media="all" /> <link rel="stylesheet" href="css/style.css" type="text/css" media="all" /> <script src="js/jquery-1.8.3.min.js"></script> <script src="js/jquery.mobile.config.js"></script> <script src="js/jquery.mobile-1.3.0.min.js"></script> <script src="cordova.js"></script> <script src="js/appFile.js"></script> <script src="js/application.js"></script> <script src="js/utility.js"></script> <script src="js/player.js"></script> <script> $(document).on('pagebeforecreate orientationchange', Application.updateIcons); $(document).one('deviceready', Application.initApplication); </script> </head> <body> <div id="home-page" data-role="page"> <header data-role="header"> <h1>Audero Audio Player</h1> </header> <div data-role="content"> <p id="app-description"> Audero Audio Player is a basic audio player that searches the file system of a device, collects the audio files found and then allows the user to listen them. This app also enables the user to update the list at any time to include files that might have been downloaded after running the operation for the first time. You can also remove any unwanted audio - for example, sounds used as notifications in other applications - by clicking an icon on the right side of the song name. The sound list is ordered alphabetically with letter dividers to organize and group list items, and it has a search box to filter files. You can see the described page by looking at the screenshot below. </p> <a href="files-list.html" data-role="button">File List</a> </div> <footer data-role="footer"> <h3 id="copyright-title">Created by Aurelio De Rosa</h3> <a id="credits-button" href="aurelio.html" data-icon="info" data-iconpos="notext" class="ui-btn-right">Credits</a> </footer> </div> </body> </html>
As you'll see in the next section, the buttons inside the
<header> and the
<footer> tags, use the attribute
data-iconpos="notext". This attribute is very important for achieving the effect I want: a responsive layout. The cited attribute tells jQuery Mobile to hide the link text, which is very useful in saving space for smaller screens. In the next section, I will demonstrate how to attach a handler to the
pagebeforecreate and the
orientationchange events so that we can test for the screen size. If a large enough screen is found, the attribute will be removed and the text will be shown. In this case, "large enough" means the screen's width is larger than 480 pixels.
<body>. Disregard this for the moment; we'll delve into their meaning later.
This screenshot will give you an example of what the page will look like:
The List Page
This small page, called
files-list.html, has a couple of interesting widgets like the autodivider and the search box. Those widgets are created for you by jQuery Mobile simply by adding a couple of attributes to the
<ul id="files-list"> tag:
data-filter="true". You have already seen how this page appears in a previous section, and you should have noted that each list item has a big "X" on the right side. This is the button that allows the user to delete the file from the list and the database. These two items are a standard effect achieved using jQuery Mobile. You can read more about them by looking at the official documentation page.
The last piece of code worth discussing is the
Now that you are fully aware of this page's key points, I can list the full source:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1"> </head> <body> <div id="files-list-page" data-role="page"> <header data-role="header"> <a href="#" data-icon="back" data-iconpos="notext" data-rel="back" title="Go back">Back</a> <h1>Media List</h1> <a href="#" id="update-button" data-icon="refresh" data-iconpos="notext">Update List</a> </header> <div data-role="content"> <ul id="files-list" data-role="listview" data-autodividers="true" data-filter="true" data-split-icon="delete"> </ul> </div> <footer data-role="footer"> <h3 id="copyright-title">Created by Aurelio De Rosa</h3> <a id="credits-button" href="aurelio.html" data-icon="info" data-iconpos="notext" class="ui-btn-right">Credits</a> </footer> <div id="waiting-popup" data-role="popup" data-position-to="window" data-dismissible="false"> <header data-role="header"> <h1>Updating</h1> </header> <div data-role="content"> <p>Searching audio files, please wait...</p> </div> </div> </div> </body> </html>
The Player Page
The player page (
player.html) doesn't have many exciting facts to point out. It's a set of labels and links with events attached to manage the sound. The only element worth mentioning is the slider used to move the audio forward and backward, created using the jQuery Mobile slider widget.
You can see the code of the page below:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1"> </head> <body> <div id="player-page" data-role="page"> <header data-role="header"> <a href="#" data-icon="back" data-iconpos="notext" data-rel="back" title="Go back">Back</a> <h1>Player</h1> </header> <div data-role="content"> <div id="player"> <div id="media-info"> <p>You're listening to: <span id="media-name"></span></p> <p>Located at: <span id="media-path"></span></p> <div> Played: <label id="media-played">-</label> of <label id="media-duration">-</label> <input type="range" name="time-slider" id="time-slider" value="0" min="0" max="100" data-highlight="true" /> </div> </div> <a href="#" id="player-play" title="Play / Pause"></a> <a href="#" id="player-stop" title="Stop"></a> </div> </div> <footer data-role="footer"> <h3 id="copyright-title">Created by Aurelio De Rosa</h3> <a id="credits-button" href="aurelio.html" data-icon="info" data-iconpos="notext" class="ui-btn-right">Credits</a> </footer> </div> </body> </html>
The Credits Page
aurelio.html is surely the least important one, and it's also very simple. Nonetheless I want to mention two things. The first is the use of two new HTML5 tags,
represents a unit of content, with an optional caption that is self-contained. The caption described is provided using the element
represents a component of a page that consists of a self-contained composition in a document, page, application, or site.
The second is the use of the attribute
target="_blank" which is applied to all of the contact listing links on the page. This attribute is very common. However, in our player, we'll use it to attach a handler to all of the external links, as you'll learn in the next part of this series.
The whole code of
aurelio.html is shown below: