Over a million developers have joined DZone.

Cordova/Ionic Sample App: My Sound Board

DZone's Guide to

Cordova/Ionic Sample App: My Sound Board

Use Apache Cordova and the Ionic Framework to create an Android or iOS sound board app that can record and play back audio.

· Mobile Zone
Free Resource

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

Today’s demo is something I started working on Sunday “for fun,” but when it turned into an unholy mess (see Recording and saving audio in Cordova applications), it took me a bit longer to wrap than I expected. The idea was simple. “Sound Boards” are apps that contain a collection of sounds, typically related to a movie or TV show. My coworker Andy built a cool sound board themed around Halloween a few years back: Halloween Fun with PhoneGap. I wanted to build a sound board too, but instead of shipping it with a set of sounds, I wanted it to be completely customized. The idea being you could record your own sounds. In a fit of extreme creativity, I called it – “My Sound Board.”

Let me share some of the screens behind the app and then I’ll dive into the code. On launch, the app will present you with a list of sounds you currently have or prompt you to record a new one.


Clicking record brings you to a new UI:


On this screen you can record a sound, play it back to test, and name it. The recording interface will be device specific on Android, but on iOS it is a standard UI created by the Media Capture plugin itself. Here it is on my HTC M8.


And here it is on an iPhone.


Once you’ve saved a few sounds, you can see the list grow.


I then used a cool Ionic feature that makes it easy to add delete buttons to a list. If you swipe right, you get a button:


All I had to do then was wire up the logic to handle deleting. So – about that code – let’s take a look. I won’t cover the workaround I mentioned in this weeks blog post, but I strongly suggest reading it. I’ll begin with the controller code for the home page:

.controller('HomeCtrl', function($scope, Sounds, $ionicPlatform) {

var getSounds = function() {
console.log('getSounds called');
Sounds.get().then(function(sounds) {
$scope.sounds = sounds;

$scope.$on('$ionicView.enter', function(){

$scope.play = function(x) {
console.log('play', x);

$scope.delete = function(x) {
console.log('delete', x);
Sounds.get().then(function(sounds) {
var toDie = sounds[x];
window.resolveLocalFileSystemURL(toDie.file, function(fe) {
fe.remove(function() {
Sounds.delete(x).then(function() {
}, function(err) {
console.log("err cleaning up file", err);

$scope.cordova = {loaded:false};
$ionicPlatform.ready(function() {
$scope.$apply(function() {
$scope.cordova.loaded = true;


There’s nothing really interesting here except for the $ionicView.enter handler. That’s how I handle getting my sounds every time you hit the home page. Technically, that is a bit wasteful. I should only care when I modify my sounds. But this was simpler, and as it stands, if you aren’t recording and leaving the home page, then there is no real performance issue. Note that delete is a bit complete. I decided that my Sound service would not worry about files. My RecordCtrl for example handles the file copying that I mentioned in the earlier post. So when I delete, I have to kill the file myself, and then tell the service.

Ok, let’s look at the view.

<ion-view view-title="My Sound Board">

  <ion-content class="padding">

    <div ng-if="sounds.length > 0">
<ion-list show-delete="false" can-swipe="true">
<ion-item ng-repeat="sound in sounds" ng-click="play($index)">

<ion-option-button class="button-assertive" ng-click="delete($index)">

<div ng-if="sounds.length < 1">
No sounds yet. Why not record a new one?

    <a href="#/new" class="button button-balanced button-block" ng-show="cordova.loaded">
      Record New Sound



Right away, I can say I don’t like the two divs there. I have to think Angular has a way of doing an ELSE type condition. Can anyone suggest an improvement? I absolutely love how Ionic adds the “swipe to show button” logic. I literally just used can-swipe and then defined a button.

Now let’s look at the service.

angular.module('mysoundboard.services', [])

.factory('Sounds', function($q) {

var deleteSound = function(x) {
console.log("calling deleteSound");
var deferred = $q.defer();
getSounds().then(function(sounds) {
localStorage.mysoundboard = JSON.stringify(sounds);

return deferred.promise;


var getSounds = function() {
var deferred = $q.defer();
var sounds = [];

if(localStorage.mysoundboard) {
sounds = JSON.parse(localStorage.mysoundboard);

return deferred.promise;

var playSound = function(x) {
getSounds().then(function(sounds) {
var sound = sounds[x];

Ok, so on Android, we just work.
On iOS, we need to rewrite to ../Library/NoCloud/FILE'
var mediaUrl = sound.file;
if(device.platform.indexOf("iOS") >= 0) {
mediaUrl = "../Library/NoCloud/" + mediaUrl.split("/").pop();
var media = new Media(mediaUrl, function(e) {
}, function(err) {
console.log("media err", err);

var saveSound = function(s) {
console.log("calling saveSound");
var deferred = $q.defer();
getSounds().then(function(sounds) {
localStorage.mysoundboard = JSON.stringify(sounds);

return deferred.promise;

return {

I decided to use LocalStorage for my persistence. Normally I recommend against LocalStorage when working with user generated content like this. But I decided that since the user data would be fairly small (a short array), then it was safe. The ease of use of LocalStorage is what sealed the deal. I felt kind of bad using outside stuff like LocalStorage and the Media plugin, but I got over it.

And that’s pretty much it. Here is a video with some sounds I recorded of my kids. The whole reason I even thought of this app was that one of my boys wanted to record his younger sisters being silly, so naturally I made use of them.

Finally, you can find the complete source code for this application here: https://github.com/cfjedimaster/Cordova-Examples/tree/master/mysoundboard. I need to add a readme to the folder, and I promise I’ll get to that. Eventually.

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

mobile ,apache cordova ,ionic framework

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

Opinions expressed by DZone contributors are their own.


Dev Resources & Solutions Straight to Your Inbox

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.


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

{{ parent.tldr }}

{{ parent.urlSource.name }}