While working on my previous article, an idea occurred to me. I should write an independent article covering Ionic Framework and Cordova Native Audio plugin.
 
This time I will not use ngCordova collection. For some reason, I can’t make it work with the original plugin. It’s like ngCordova Native Audio wrapper is using a different file location path, I simply can’t explain it.
 
To make this tutorial a little bit challenging, we’ll create a simple audio player.
 
 

Note: If this tutorial was helpful, need further clarification, something is not working or do you have a request for another Ionic post? Furthermore, if you don't like something about this blog, if something is bugging you, don't like how I'm doing stuff here, again leave me a comment below. I'm here to help you, I expect the same from you. Feel free to comment below, subscribe to my blog, mail me to dragan.gaic@gmail.com, or follow and mention me on twitter (@gajotres). Thanks and have a nice day!

PS. If you want my help, if possible (even if it takes you some time to do that), create a working example I can play with. Use Plunker for AngularJS based questions or jsFiddle for jQuery/jQuery Mobile based questions.


 

Table of Contents

 
 
Click here if you want to see other tutorials, or articles about the Ionic framework (themes, templates, plugins, tutorials)
 

Preparation

 
This tutorial requires a preconfigured environment. Skip this step if you already have this covered.
 
  • Android Environment (or iOS if you’re working on a MacOS)
  • nodeJS
  • Ionic
  • Cordova
If you don’t have previous Ionic Framework experience, find more information here: Ionic Framework | Installation Guide.
 

1. Update Ionic & Cordova

 
Before we can start, make sure you have the latest nodeJS installation, without it, you’ll not be able to install Ionic and Cordova properly.
 
If everything went well with nodeJS, let’s continue with Ionic and Cordova:
 
npm update -g cordova ionic
 

2. Create a New Project

 
ionic start IonicNativeAudioDemo blank
cd IonicNativeAudioDemo
 
Warning: Since some of you never worked with Ionic CLI. From this point and further, every time I tell you to execute something, do that inside a project folder.
 
This example requires Android platform:
 
ionic platform add android
 
For MacOS users, do it like this:
 
ionic platform add ios
 

4. Install Cordova Native Audio plugin

 
Add these:
 
cordova plugin add cordova-plugin-nativeaudio
cordova plugin add cordova-plugin-whitelist
 
If you’re using Cordova 4.0 or higher, you will need to install Whitelist plugin. Without it you’ll receive “Application Error: There was a network error.” error.
 
GitHub - Native Audio
 
 

Development

 
At this point, you should have everything set up and ready, we can start working on our example.
 
Open index.html file, add a controller to ion-pane directive:
 
  <ion-pane ng-controller="AudioController">
      <ion-header-bar class="bar-stable">
        <h1 class="title">Native Audio Example</h1>
      </ion-header-bar>
      <ion-content>
      </ion-content>
   </ion-pane>
 
Initialize AudioController controller in a app.js file:
 
app.controller('AudioController', function($scope) {

});
 
If you’re using Cordova 4+, you will need to check if there’s a Whitelist plugin installed with your project. If you have it, add this security meta tag to your index.html HEAD content:
 
<meta http-equiv="Content-Security-Policy" content="default-src *; script-src 'self' 'unsafe-inline' 'unsafe-eval' *; style-src  'self' 'unsafe-inline' *">
 
Without it your application will throw an error during the app initialization, after that it will continually throwing no security meta-tag found. While not a blocking point, constant console log warnings will make it hard to do any debugging.
 
Native Audio plugin require Cordova or Ionic ready event, so don’t forget it:
 
$ionicPlatform.ready(function() {
   // Rest of the code
});
 
To make this as easy as possible, I’ve built a JSON file holding application audio data. If you want to test this example using these files, you can find everything on the next page.
 
JSON example:
 
  var audio = [{
    id: 1,
    key: 'master',
    title: "The Master",
    track: 'audio/The_Master.mp3',
    genre: "This will be card Description"
  }, {
    id: 2,
    key: 'give',
    title: "Give",
    track: 'audio/Give.mp3',
    genre: "Alternative & Punk | Bright"
  }, {
    id: 3,
    key: 'morning',
    title: "Morning Stroll",
    track: 'audio/Morning_Stroll.mp3',
    genre: "Classical | Happy"
  }, ];
 
We’ll use this data to create our player UI:
 
 <div class="list card" ng-repeat="audio in audioTracks">

  <div class="item item-avatar">
	<img src="http://findicons.com/files/icons/2711/free_icons_for_windows8_metro/512/audio_wave.png">
	<h2>{{audio.title}}</h2>
	<p>{{audio.genre}}</p>
  </div>

  <div class="item tabs tabs-secondary tabs-icon-left">
	<a class="tab-item" href="#" ng-click="playTrack(audio.track, audio.key)">
	  <i class="icon ion-ios-play"></i>
	  Play
	</a>
	<a class="tab-item" href="#" ng-click="stopTrack(audio.key)">
	  <i class="icon ion-android-checkbox-blank"></i>
	  Stop
	</a>
  </div>

</div>
 
Every audio track will have a separate card element, and each card element will have a basic track info, play, and stop button. It will look like this:
 
 
 
Application will use these two functions for play and stop buttons:
 
$scope.playTrack = function(track, key) {
  // Preload an audio track before we play it
  window.plugins.NativeAudio.preloadComplex(key, track, 1, 1, 0, function(msg) {
	// If this is not a first playback stop and unload previous audio track
	if ($scope.player.key.length > 0) {
	  window.plugins.NativeAudio.stop($scope.player.key); // Stop audio track
	  window.plugins.NativeAudio.unload($scope.player.key); // Unload audio track
	}

	window.plugins.NativeAudio.play(key); // Play audio track
	$scope.player.key = key; // Set a current audio track so we can close it if needed 
  }, function(msg) {
	console.log('error: ' + msg); // Loading error
  });
};

$scope.stopTrack = function() {
	// If this is not a first playback stop and unload previous audio track
	if ($scope.player.key.length > 0) {
	  window.plugins.NativeAudio.stop($scope.player.key); // Stop audio track
	  window.plugins.NativeAudio.unload($scope.player.key); // Unload audio track
	  $scope.player.key = ''; // Remove a current track on unload, it will break an app if we try to unload it again in playTrack function
	}
};
 
If you for some reason need to play a much shorter nonlooping audio track (up to 10 sec) it’s better to use preloadSimple method:
 
preloadSimple: function ( id, assetPath, function(msg) {
   console.log('status: ' + msg);
}, function(msg) {
   console.log('error: ' + msg); // Loading error
});
 
Last but not least, no matter what preloading method is used don’t forget to unload it after it’s no longer needed.
 

Example

 
This is what our application looks like:
 

HTML

Application main page.
 
<!DOCTYPE html>
<html ng-app="starter">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="Content-Security-Policy" content="default-src *; script-src 'self' 'unsafe-inline' 'unsafe-eval' *; style-src  'self' 'unsafe-inline' *"> 
    <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width">
    <title></title>

    <link href="lib/ionic/css/ionic.css" rel="stylesheet">

    <link href="css/style.css" rel="stylesheet">

    <!-- ionic/angularjs js -->
    <script src="lib/ionic/js/ionic.bundle.js"></script>
  
    <!-- cordova script (this will be a 404 during development) -->
    <script src="cordova.js"></script>

    <!-- your app's js -->
    <script src="js/app.js"></script>
  </head>
  <body ng-controller="AudioController">

    <ion-pane>
      <ion-header-bar class="bar-stable">
        <h1 class="title">Native Audio Example</h1>
      </ion-header-bar>
      <ion-content>
		 <div class="list card" ng-repeat="audio in audioTracks">

		  <div class="item item-avatar">
		    <img src="http://findicons.com/files/icons/2711/free_icons_for_windows8_metro/512/audio_wave.png">
		    <h2>{{audio.title}}</h2>
		    <p>{{audio.genre}}</p>
		  </div>

		  <div class="item tabs tabs-secondary tabs-icon-left">
		    <a class="tab-item" href="#" ng-click="playTrack(audio.track, audio.key)">
		      <i class="icon ion-ios-play"></i>
		      Play
		    </a>
		    <a class="tab-item" href="#" ng-click="stopTrack()">
		      <i class="icon ion-android-checkbox-blank"></i>
		      Stop
		    </a>
		  </div>

		</div>
      </ion-content>    
    </ion-pane>
  </body>
</html>
 

JavaScript

Application JavaScript file.
 
var app = angular.module('starter', ['ionic']);

app.run(function($ionicPlatform) {
  $ionicPlatform.ready(function() {
    if (window.cordova && window.cordova.plugins.Keyboard) {
      cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
    }
    if (window.StatusBar) {
      StatusBar.styleDefault();
    }
  });
});

app.controller('AudioController', function($scope, $ionicPlatform) {

  var audio = [{
    id: 1,
    key: 'master',
    title: "The Master",
    track: 'audio/The_Master.mp3',
    genre: "This will be card Description"
  }, {
    id: 2,
    key: 'give',
    title: "Give",
    track: 'audio/Give.mp3',
    genre: "Alternative & Punk | Bright"
  }, {
    id: 3,
    key: 'morning',
    title: "Morning Stroll",
    track: 'audio/Morning_Stroll.mp3',
    genre: "Classical | Happy"
  }, ];

  $scope.audioTracks = Array.prototype.slice.call(audio, 0);

  $scope.player = {
    key: '' // Holds a last active track
  }

  $ionicPlatform.ready(function() {

    $scope.playTrack = function(track, key) {
      // Preload an audio track before we play it
      window.plugins.NativeAudio.preloadComplex(key, track, 1, 1, 0, function(msg) {
        // If this is not a first playback stop and unload previous audio track
        if ($scope.player.key.length > 0) {
          window.plugins.NativeAudio.stop($scope.player.key); // Stop audio track
          window.plugins.NativeAudio.unload($scope.player.key); // Unload audio track
        }

        window.plugins.NativeAudio.play(key); // Play audio track
        $scope.player.key = key; // Set a current audio track so we can close it if needed 
      }, function(msg) {
        console.log('error: ' + msg); // Loading error
      });
    };

    $scope.stopTrack = function() {
        // If this is not a first playback stop and unload previous audio track
        if ($scope.player.key.length > 0) {
          window.plugins.NativeAudio.stop($scope.player.key); // Stop audio track
          window.plugins.NativeAudio.unload($scope.player.key); // Unload audio track
          $scope.player.key = ''; // Remove a current track on unload, it will break an app if we try to unload it again in playTrack function
        }
    };
  });
});
 
Continue to the next page

  • Matt Ezell

    Great write up (as always)!

    Thanks for providing these examples for us! I’ve made a habit to visit regularly to see what you’re writing about! Your site is a very valuable resource for Ionic Framework developers!

    Keep up the great work!

    • Thank you very much 🙂 Do you maybe have a topic you would like to read about?

  • Marshallvatian

    i have problem here,,there is no output sound when i click the play button. It just like when i click blank (#) html link without some address. it not do anything.

    • psychedelik

      same issue here.

    • Sorry, but I don’t know how to help you with your problem. My advice, go to the official plugin GitHub repo and open a ticket.

    • Stevie Starosciak

      After messing with this on both Android and iOS, are you currently trying to test this on iOS 9? Because apparently there is a bug on iOS 9 that has some issues with playing back audio on the device, both in the iOS emulator and on the iOS device, I’ve been testing this on iPhone 6s plus. I still haven’t figured this one yet, but I did want to make this known.

  • Adi

    When clicking on play it shows ‘NativeAudio’ of undefined at Scope.$scope.playTrack

    • Make sure plugin is installed correctly. If it is installed, remove it and add it again.

  • montjoile

    is it necessary to unload every sound after played? shounldn’t afect that to the memory if the user listens same song various times?

    • You don’ need to unload them. I did that just to prove how important is to manage active memory.

  • mrkazep

    how i play every song without array….thank’s for your answer

    • Every song in what context? No matter which audio player you want to use it still needs a playlist array.

      • mrkazep

        thank’s for your answer…i want..every track/song have image..how do i do?

  • Saverio Grisorio

    Hi, how can you pause and restart the execution? Many thanks

    • You would need to find another plugin, this one does not support pausing and restarting.

  • Màrwen Ketata

    this code not working

    • Pragadees

      you want to create a sperate folder as audio and add some .mp3 file

  • Pragadees

    hi Gajotres,
    its working nice…
    plz one help…
    how to find the audio is completed?

  • amir baqdadi

    hi Thanks ,
    how to create download link for it ?

  • Bla

    should this be run in emulator only?

  • Nguyen Di

    Nice tutorial and very nice music. Thanks so much!

  • GreenDome

    Justing wondering if this plugin (cordova-plugin-nativeaudio) can be used for streaming live audio instead of local media files?

  • Sudimampir News

    Kok dijalankan di emulator dan handphone Android tidak berjalan dengan baik?

  • adedeji92

    Can we have a way to add music controller(Like next, previous and play/pause) in the notification bar. any help? Attached image is an example https://uploads.disquscdn.com/images/3c7e63b8f43fa29d70b0e455dabc1215f9327d5c88c92b8c2c5e762eac1f047c.png