Ionic Framework, Cordova and File API – A Media Player App9 min read

Yves Bamani requested a post to build a media player app using Ionic Framework and Cordova. The mediaPlayer app will show a player interface and a couple of buttons. The user can browse through the filesystem and pick a file to play. The initial request was to play both Audio and Video files inline. But I was only able to get the Audio files to play inline where as the Video will be launched in the device default video player.

Here is a quick demo of the app

Screenshot_2015-03-30-10-53-15 Screenshot_2015-03-30-10-53-24 Screenshot_2015-03-30-10-53-54

Yves also requested for the app to be built using ngCordova. But there are a couple of features in $cordovaMedia like getDuration(media)  and  getCurrentPosition(), which are not working yet. And the $cordovaFile does not have a method to recursively get all the folders in a directory, so I am going to use Cordova API as is and build this app.

You can find the completed here.

So, let us get started.

Prerequisites

You need to have the knowledge of the following to get a better understanding of the code below.

Application Design

The application is pretty simple. When the user launches the app, we show a file browser, where the user can browse through his/her device. Then they can select an audio or video file to play.

We will be using a side menu template, where the player is a instance of  $ionicModal. This modal lives in the background. As mentioned earlier, we will be using the Media API from cordova to manage the audio files and a Video player Cordova plugin by Dawson Loudon named VideoPlayer inspired by Simon MacDonald’s VideoPlayer. All this plugin does is create a new Video Intent and launch it.

I am still looking for a consistent solution on how to implement inline videos. If you do know one, please drop a comment.

I have tested this app on an Android and not on iOS.

Develop the App

Create a new folder named mediaPlayerApp. Open a new terminal/prompt here. We will scaffold the side menu template and then clean it up as per our needs. Run,

ionic start mediaPlayerApp sidemenu

Once the scaffolding is completed, you can CD into the mediaPlayerApp folder and run

ionic serve

and you should see the side menu app in your browser.

The first thing we are going to do is update index.html. Open www/index.html in your favorite editor and update it as below

We have referred the audio service JS code that consist of the logic to deal with the Media API and the controllers file which consist of the controller logic.

Next, open www/templates/menu.html. We will update this file with fewer menu items

We have removed all the old menu items and added 2 new. One to show the player, and one to browse the device.

Now, we will clean up and rename the required files inside www/templates folder

  • Rename login.html to player.html
  • Delete playlist.html
  • Delete playlists.html
  • Delete search.html

Open www/templates/player.html and update it as below

This template will be shown when we init the Ionic Modal. This Modal will always be in the background while the app is running.

This template is the base for showing the audio player. Line 18 consists of the logic to show the seek bar. Line 22 shows the play button, when we have paused the video using the button on line 25. We can also stop the media play back completely using the Stop button.

As you can see from the directives on these buttons, they are subjected to visibility based on the state of the audio file.

Next, open www/templates/browse.html and update it as below

This is a very simple template drive by the files[]  from scope. When the user launches the browse page, we will query the file system and show the root files. Once the user clicks on a particular folder, we query the file system API passing in the current folder as the root and fetch its children.

And when a user selects a file, we check if it is of the type audio or video and then play it. Else we will show a message that we cannot play the selected file.

This completes all our templates. We will now work with the Audio Service. Open www/js folder and create a new file named audio.service.js and update it as below.

Things to notice

Line 1 : We have created a new module named starter.services and added the  AudioSvc to that.

Line 8 : Defines the play audio method, which plays the given src using the Cordova’s Media API.

Line 18 : We create a setInterval for every seconds to execute  getCurrentPosition() and trigger the callback. This way we update the seek bar with the total time and time left.

Line 46 : The logic for resume audio

Line 52 : The logic for pause audio

Line 58 : The logic for stop audio

We will be injecting this service as a dependency in our controller, where we will manage the above API based on the user interactions.

Next, we will update www/js/app.js as below

Things to notice

Line 1 : We create a module named starter and inject ionicstarter.controllers and starter.services as dependencies.

Line 4 : Inside the  $ionicPlatform.ready() we config the keyboard and status bar.

Line 12, 20, 26 : We are building an API to work with the  $ionicLoading  API.

Line 32 : We config the router

Finally, the controllers. Open www/js/controller/js and update it as below

Things to notice

Line 13 : When the app launches, the BrowseCtrl is invoked. Here, we initialize the player as a modal from the template.

Line 19, 23 : We have created 2 methods on  $rootScope that can show and hide the player. This will be used across the app. Take a look at line 5.

Line 27 : The File System traversing starts from here. We wait for the device to be ready.

Line 30 : We call  requestFileSystem() on the window and get the contents of the root directory.

Line 35 : We read all the entries present in the root folder and  call  processEntries() to build an Array of files system items.

Line 156 : Here we get all the entries and a reference Array. We iterate through each item and build an object, which consists of essential information while rendering. This same method will be invoked when ever we are reading entries from the file system and building a UI.

Line 38 : We assign the file info array to  $scope.files. This updates the browse.html template to reflect the files in the root.

Line 49 : Will get invoked when any file or folder name is clicked.

Line 51 : If the selected item is a folder, we check if the item is a navigation item. Navigation items are used to move to folder one level up, which we create for the user to navigate. Based on this condition, we call  processFile() with a URL

Line 115 : Here, we resolve the current URL, and then get the children (files/folders) inside that path and then update  $scope.files.

Line 125 : If the folder is not the root folder and it has children, we append a new  .. One level up item to the top of the list, using which the user can navigate to the parent folder. You can see the same in the demo video. This way, we can recursively show the file system to the user.

Line 57 : If the clicked item is a file, we check it is an Audio file or Video file. If it is a Video file, we will invoke the  VideoPlayer.play() passing in the media URL. We install the Video player plugin next.

Line 63 : If it is an audio file, we will work with the  AudioSvc  service and manage the player.

The file looks pretty complicated but the logic is pretty simple.

Install Cordova Plugins

To run the app, we need 3 plugins.

  1. com.ionic.keyboard
  2. org.apache.cordova.file
  3. org.apache.cordova.media
  4. com.dawsonloudon.videoplayer

To install the plugins run

cordova plugin add com.ionic.keyboard

cordova plugin add org.apache.cordova.file

cordova plugin add org.apache.cordova.media

cordova plugin add https://github.com/dawsonloudon/VideoPlayer.git

Run the App

We need to run the app on a device to test it. First, we will add a platform. Run,

ionic platform add android

And then to the run  the app on a device execute

ionic run

And you should be able to check out the below

 

Hope this post gave you an idea on how to work with File System, Audio and Video APIs.


Thanks for reading! Do comment.
@arvindr21