Play Music in Ionic Capacitor apps
Tags: ionic, capacitor, music
Published: 2020-03-28 12:40:27

<main role="main"><article class=" u-minHeight100vhOffset65 u-overflowHidden postArticle postArticle--full is-supplementalPostContentLoaded is-withAccentColors" lang="en" ><div class="postArticle-content js-postField js-notesSource editable" id="editor_6" g_editable="true" role="textbox" contenteditable="true" data-default-value="Title
Tell your story…" spellcheck="false"><section name="4cf6" class="section section--body section--first"><div class="section-divider"><hr class="section-divider"></div><div class="section-content"><div class="section-inner sectionLayout--insetColumn"><p name="4d1e" class="graf graf--p graf-after--figure">In this post, you will learn how to play music in your Capacitor Ionic Angular app, be it for a music player or just for a notification. Capacitor is the latest buzz in hybrid app world. It is created to be a replacement and an improvement over Cordova.</p><p name="7d84" class="graf graf--p graf-after--p">In this post, you will learn</p><ul class="postList"><li name="d949" class="graf graf--li graf-after--p">How to play music and sound files in Ionic 4 apps&#8202;—&#8202;both from local files and web urls</li><li name="f28d" class="graf graf--li graf-after--li">How to use music controls like next, previous, pause etc.</li></ul><blockquote name="badb" class="graf graf--blockquote graf-after--li"><strong class="markup--strong markup--blockquote-strong">This demonstration is supported by </strong><a href="https://store.enappd.com/product/ionic-4-spotify-app-starter/"  class="markup--anchor markup--blockquote-anchor" rel="noopener"    target="_blank"><strong class="markup--strong markup--blockquote-strong">Ionic 4 Spotify Starter</strong></a><strong class="markup--strong markup--blockquote-strong"> from Enappd. Complete source code of this tutorial is available here&#8202;—&#8202;</strong><a href="https://github.com/enappd/ionic-4-music"  class="markup--anchor markup--blockquote-anchor" rel="noopener"    target="_blank"><strong class="markup--strong markup--blockquote-strong">Ionic-4-music</strong></a><strong class="markup--strong markup--blockquote-strong"> (capacitor branch)</strong></blockquote><p name="c8b8" class="graf graf--p graf-after--blockquote">If you are looking for Music functionality in <strong class="markup--strong markup--p-strong">Ionic 4 Angular Cordova</strong> apps, please check <a href="https://enappd.com/blog/spotify-like-music-in-ionic-4-apps/48"  class="markup--anchor markup--p-anchor" rel="noopener"    target="_blank">this blog</a></p><p name="aac2" class="graf graf--p graf-after--p">Let’s see a brief intro to each of the included frameworks:</p><ol class="postList"><li name="0ad7" class="graf graf--li graf-after--p">Ionic</li><li name="71d0" class="graf graf--li graf-after--li">Capacitor</li></ol><h3 name="244d" class="graf graf--h3 graf-after--li">What is&nbsp;Ionic?</h3><p name="941f" class="graf graf--p graf-after--h3 is-selected">You probably already know about Ionic, but I’m putting it here just for the sake of beginners. <strong class="markup--strong markup--p-strong">Ionic</strong> is a hybrid mobile app development SDK. It provides tools and services for developing hybrid mobile apps using Web technologies like CSS, HTML5, and Sass. Apps can be built with these Web technologies and then distributed through native app stores. These apps can be installed on devices by leveraging <a href="https://cordova.apache.org/"  class="markup--anchor markup--p-anchor" rel="noopener"    target="_blank">Cordova</a> or Capacitor environment.</p><p name="010c" class="graf graf--p graf-after--p">So, in other words&#8202;—&#8202;If you create Native apps in Android, you code in Java. If you create Native apps in iOS, you code in Obj-C or Swift. Both of these are powerful but complex languages. <strong class="markup--strong markup--p-strong">With Cordova (and Ionic) you can write a single piece of code for your app that can run on both iOS and Android </strong>(and windows!), that too with the simplicity of HTML, CSS, and JS.</p><p name="0f04" class="graf graf--p graf-after--p">It is important to note the contribution of Cordova in this. Ionic is only a UI wrapper made up of HTML, CSS and JS. So, by default, Ionic cannot run as an app in an iOS or Android device. Cordova is the build environment that containerizes (sort of) this Ionic web app and converts it into a device installable app, along with providing this app access to native APIs like Camera etc.</p><h3 name="a431" class="graf graf--h3 graf-after--p">What is Capacitor&nbsp;?</h3><p name="8090" class="graf graf--p graf-after--h3">Cordova helps build Ionic web app into a device installable app. But there are some limitations of Cordova, which Capacitor tries to overcome with a new App workflow.</p><p name="f84c" class="graf graf--p graf-after--p">Capacitor is a cross-platform app runtime that makes it easy to build web apps that run natively on iOS, Android, Electron, <em class="markup--em markup--p-em">and</em> the web. Ionic people call these apps “Native Progressive Web Apps” and they represent the next evolution beyond Hybrid apps.</p><blockquote name="6299" class="graf graf--blockquote graf-after--p"><strong class="markup--strong markup--blockquote-strong">Capacitor is very similar to Cordova, but with some key differences in the app workflow</strong></blockquote><p name="e43f" class="graf graf--p graf-after--blockquote">Here are the differences between Cordova and Capacitor</p><ol class="postList"><li name="21a5" class="graf graf--li graf-after--p">Capacitor considers each platform project a <em class="markup--em markup--li-em">source asset</em> instead of a <em class="markup--em markup--li-em">build time asset</em>. That means, Capacitor wants you to keep the platform source code in the repository, unlike Cordova which always assumes that you will generate the platform code on build time</li><li name="68ee" class="graf graf--li graf-after--li">Because of the above, Capacitor does not use <code class="markup--code markup--li-code">config.xml</code> or a similar custom configuration for platform settings. Instead, configuration changes are made by editing <code class="markup--code markup--li-code">AndroidManifest.xml</code> for Android and <code class="markup--code markup--li-code">Info.plist</code> for Xcode</li><li name="d63a" class="graf graf--li graf-after--li">Capacitor does not “run on device” or emulate through the command line. Instead, such operations occur through the platform-specific IDE. So you cannot run an Ionic-capacitor app using a command like <code class="markup--code markup--li-code">ionic run ios</code>&nbsp;. You will have to run iOS apps using Xcode, and Android apps using Android studio</li><li name="3ecd" class="graf graf--li graf-after--li">Since platform code is not a <em class="markup--em markup--li-em">source asset, </em>you can directly change the native code using Xcode or Android Studio. This give more flexibility to developers</li></ol><p name="752e" class="graf graf--p graf-after--li">In essence, Capacitor is like a fresh, more flexible version of Corodva.</p><h4 name="cf20" class="graf graf--h4 graf-after--p">Plugins in Capacitor</h4><p name="dc8c" class="graf graf--p graf-after--h4">Cordova and <a href="https://ionicframework.com/docs/native"  class="markup--anchor markup--p-anchor" rel="noopener"    target="_blank">Ionic Native</a> plugins can be used in Capacitor environment. In this post also, we will use <a href="https://github.com/apache/cordova-plugin-media"  class="markup--anchor markup--p-anchor" rel="noopener"    target="_blank">Cordova-plugin-media</a> to play music in Capacitor environment, which is wrapped by Ionic Native plugin as well.</p><p name="554e" class="graf graf--p graf-after--p">However, there are certain Cordova plugins which are known to be <a href="https://capacitor.ionicframework.com/docs/cordova/known-incompatible-plugins/"  class="markup--anchor markup--p-anchor" rel="noopener"    target="_blank">incompatible with Capacitor.</a></p><p name="2367" class="graf graf--p graf-after--p">Other than that, Capacitor also doesn’t support plugin installation with variables. Those changes have to be done manually in the native code.</p><h3 name="1815" class="graf graf--h3 graf-after--p">Where is music required in apps&nbsp;?</h3><p name="3b5b" class="graf graf--p graf-after--h3">Well&nbsp;! that’s a stupid question I know. Music is everywhere in today’s apps. Spotify, Youtube Music, Wynk, Gaana, etc. Other than the music streaming apps themselves, there are tonnes of other usages of music/sound in apps.</p><ul class="postList"><li name="3cb0" class="graf graf--li graf-after--p">You definitely need sounds in a game app</li><li name="9f39" class="graf graf--li graf-after--li">You can play sounds when user does a specific activity in the app e.g. wins a coupon&nbsp;!</li><li name="f7ed" class="graf graf--li graf-after--li">Sounds can be played for push notifications, the ones which are silently pushed in a foreground app</li><li name="54b2" class="graf graf--li graf-after--li">Chat messages can make a sound&nbsp;! Whatsapp does that</li><li name="cb47" class="graf graf--li graf-after--li">…… and many more such examples</li></ul><p name="c9d8" class="graf graf--p graf-after--li">Basically music / sounds make your app more lively, more exciting. Of course you would want to avoid sounds in a professional app like LinkedIn, because people use that at work as well 😄</p><h3 name="0ee8" class="graf graf--h3 graf-after--p">Structure of&nbsp;Post</h3><p name="4e4f" class="graf graf--p graf-after--h3">We’ll follow a stepped approach to create a Music player app in this Ionic 4 Capacitor App. Following are the steps</p><ul class="postList"><li name="b073" class="graf graf--li graf-after--p">Step 1&#8202;—&#8202;Create a basic <strong class="markup--strong markup--li-strong">Ionic 4 Angular</strong> app</li><li name="93d1" class="graf graf--li graf-after--li">Step 2&#8202;—&#8202;Setup Music plugin</li><li name="a19a" class="graf graf--li graf-after--li">Step 3&#8202;—&#8202;Understand and implement Music plugin Features</li><li name="5627" class="graf graf--li graf-after--li">Step 4&#8202;—&#8202;Integrate Capacitor in the app</li><li name="3817" class="graf graf--li graf-after--li">Step 5— Test on Android</li></ul><p name="e399" class="graf graf--p graf-after--li">So let’s dive right in&nbsp;!</p><h3 name="109f" class="graf graf--h3 graf-after--p">Step 1&#8202;—&#8202;Create a basic Ionic 4&nbsp;app</h3><blockquote name="ff84" class="graf graf--blockquote graf-after--h3">I have covered this topic in detail in <a href="https://enappd.com/blog/how-to-create-an-ionic-4-app-for-beginners/13/"  class="markup--anchor markup--blockquote-anchor" rel="noopener nofollow noopener noopener noopener noopener"    target="_blank">this blog</a>.</blockquote><p name="ac57" class="graf graf--p graf-after--blockquote">In short, the steps you need to take here are</p><ul class="postList"><li name="1e8a" class="graf graf--li graf-after--p">Make sure you have node installed in the system (V10.0.0 at the time of this blog post)</li><li name="1ae0" class="graf graf--li graf-after--li">Install <strong class="markup--strong markup--li-strong">ionic cli </strong>using npm (my Ionic version is 4.6.0 )</li><li name="508a" class="graf graf--li graf-after--li">Create an Ionic app using <code class="markup--code markup--li-code">ionic start</code></li></ul><p name="afc5" class="graf graf--p graf-after--li">You can create a <code class="markup--code markup--p-code">blank</code> starter for the sake of this tutorial. On running <code class="markup--code markup--p-code">ionic start ionic-4-music blank</code>&nbsp;, node modules will be installed. Once the installation is done, run your app on browser using</p><pre name="f473" class="graf graf--pre graf-after--p">$ ionic serve</pre><p name="5a2e" class="graf graf--p graf-after--pre">Make slight modifications to the home page as you like. My app’s home page looks like this</p><figure tabindex="0" contenteditable="false" name="b811" class="graf graf--figure graf-after--p"><div class="aspectRatioPlaceholder is-locked" style="max-width: 700px; max-height: 350px;"><div class="aspectRatioPlaceholder-fill" style="padding-bottom: 50%;"></div><img class="graf-image" data-image-id="1*WoO1vuWI4F_qhSQh7xiQ8w.jpeg" data-width="1000" data-height="500" alt="Home page for ionic-4-music app in Capacitor" src="https://cdn-images-1.medium.com/max/800/1*WoO1vuWI4F_qhSQh7xiQ8w.jpeg"><div class="crosshair u-ignoreBlock"></div></div><br/><figcaption class="imageCaption" contenteditable="true" data-default-value="Type caption for image (optional)">Home page for ionic-4-music app in Capacitor</figcaption></figure><p name="e850" class="graf graf--p graf-after--figure">I actually borrowed the homepage UI from Enappd’s <a href="https://store.enappd.com/product/ionic-4-spotify-app-starter/"  class="markup--anchor markup--p-anchor" rel="noopener"    target="_blank">Ionic 4 Spotify starter</a>, just to give you a glimpse of the UI and features.</p><h3 name="3104" class="graf graf--h3 graf-after--p">Step 2&#8202;—&#8202;Setup Music&nbsp;plugin</h3><p name="4cd3" class="graf graf--p graf-after--h3">We are going to use an Ionic Native plugin (which is essentially wrapping a Cordova plugin)&#8202;—&#8202;<a href="https://github.com/apache/cordova-plugin-media"  class="markup--anchor markup--p-anchor" rel="noopener"    target="_blank">Cordova Plugin Media</a>. This plugin has basic music playback functionalities, along with recording capabilities. But we’ll not go into recording features for now.</p><p name="48bd" class="graf graf--p graf-after--p">Once your basic app is ready, install the plugin using following commands</p><pre name="18b6" class="graf graf--pre graf-after--p">$ ionic cordova plugin add cordova-plugin-media<br>$ npm install @ionic-native/media</pre><p name="05f3" class="graf graf--p graf-after--pre">With this, the plugin is installed, no extra settings. Now you have to import the plugin in <code class="markup--code markup--p-code">app.module.ts</code> and your homepage i.e. <code class="markup--code markup--p-code">home.page.ts</code></p><figure tabindex="0" contenteditable="false" name="2696" class="graf graf--figure graf-after--p"><div class="aspectRatioPlaceholder is-locked" style="max-width: 700px; max-height: 443px;"><div class="aspectRatioPlaceholder-fill" style="padding-bottom: 63.3%;"></div><img class="graf-image" data-image-id="1*celsXfAdId0Bvlfk7ZfrlQ.png" data-width="903" data-height="572" src="https://cdn-images-1.medium.com/max/800/1*celsXfAdId0Bvlfk7ZfrlQ.png"><div class="crosshair u-ignoreBlock"></div></div><br/><figcaption class="imageCaption" contenteditable="true" data-default-value="Type caption for image (optional)">Import music plugin in app.module.ts</figcaption></figure><p name="e8af" class="graf graf--p graf-after--figure">Similarly import the plugin in <code class="markup--code markup--p-code">home.page.ts</code> and declare it in constructor as</p><pre name="0c4e" class="graf graf--pre graf-after--p">constructor(public platform: Platform, private media: Media) {}</pre><h3 name="74eb" class="graf graf--h3 graf-after--pre">Step 3&#8202;—&#8202;Various Music plugin&nbsp;Features</h3><p name="879e" class="graf graf--p graf-after--h3">Now that he plugin is installed and imported correctly, we move on to integrate its methods. Let’s have a look at different methods the plugin supports</p><blockquote name="f60e" class="graf graf--blockquote graf-after--p"><strong class="markup--strong markup--blockquote-strong">Complete source code of this tutorial is available here&#8202;—&#8202;</strong><a href="https://github.com/enappd/ionic-4-music"  class="markup--anchor markup--blockquote-anchor" rel="noopener"    target="_blank"><strong class="markup--strong markup--blockquote-strong">Ionic-4-music</strong></a><strong class="markup--strong markup--blockquote-strong"> (capacitor branch)</strong></blockquote><h4 name="d72c" class="graf graf--h4 graf-after--blockquote">Create Media</h4><p name="f7c7" class="graf graf--p graf-after--h4">This is the basic routine the plugin needs to perform in order to import the song/audio file into the app. There are two ways to provide music file to the plugin</p><ul class="postList"><li name="b7fa" class="graf graf--li graf-after--p">From a local url</li><li name="d752" class="graf graf--li graf-after--li">From a web url</li></ul><p name="b30c" class="graf graf--p graf-after--li"><strong class="markup--strong markup--p-strong">From Local url&#8202;—&#8202;</strong>For demo purpose, I will use a local asset file. I have this file directly in <code class="markup--code markup--p-code">assets</code> folder.</p><figure tabindex="0" contenteditable="false" name="e24d" class="graf graf--figure graf-after--p"><div class="aspectRatioPlaceholder is-locked" style="max-width: 296px; max-height: 199px;"><div class="aspectRatioPlaceholder-fill" style="padding-bottom: 67.2%;"></div><img class="graf-image" data-image-id="1*EKrvsFH4QV6jkkBI8zl8Gw.png" data-width="296" data-height="199" alt="Local asset file for music playback" src="https://cdn-images-1.medium.com/max/800/1*EKrvsFH4QV6jkkBI8zl8Gw.png"><div class="crosshair u-ignoreBlock"></div></div><br/><figcaption class="imageCaption" contenteditable="true" data-default-value="Type caption for image (optional)">Local asset file for music&nbsp;playback</figcaption></figure><p name="9b65" class="graf graf--p graf-after--figure">In Android devices, you need to format the music file url like this<code class="markup--code markup--p-code">/android_asset/public/assets/file.mp3</code>&nbsp;.</p><p name="dd11" class="graf graf--p graf-after--p"><strong class="markup--strong markup--p-strong">From Web url&#8202;—&#8202;</strong>You can also input a web url directly. Here’s a URL for the song you can use (Please check if the URL still exists, otherwise use any other mp3 URL)</p><pre name="f3db" class="graf graf--pre graf-after--p"><a href="http://fabienne.sigonney.free.fr/tranquilit/Eagles"  class="markup--anchor markup--pre-anchor" rel="nofollow noopener noopener noopener noopener" target="_blank">http://fabienne.sigonney.free.fr/tranquilit/Eagles</a> - Hotel California (Acoustic).mp3</pre><p name="ec9a" class="graf graf--p graf-after--pre">To create a playable media, you need to assign the media file to a variable via the <code class="markup--code markup--p-code">create</code> method of the plugin</p><pre name="9b84" class="graf graf--pre graf-after--p">this.curr_playing_file = this.media.create("YOUR_FILE_URL");</pre><p name="0d44" class="graf graf--p graf-after--pre">Now, <code class="markup--code markup--p-code">this.curr_playing_file</code> can be used throughout the page to play / pause/ stop the song etc.</p><h4 name="dfb3" class="graf graf--h4 graf-after--p">Play /&nbsp;pause</h4><p name="d53c" class="graf graf--p graf-after--h4">The most basic function of a music player. The plugin allows you to play or pause a “created” media. The method could not have been simpler 😄</p><pre name="f929" class="graf graf--pre graf-after--p">this.curr_playing_file.play();</pre><p name="d29c" class="graf graf--p graf-after--pre">Note&#8202;—&#8202;The plugin take a little time to load the media. Make sure you are not calling <code class="markup--code markup--p-code">play()</code> on an uncreated media variable.</p><p name="6830" class="graf graf--p graf-after--p">Also, <strong class="markup--strong markup--p-strong">Paused</strong> media plays from the same place it was paused.</p><h4 name="1e9e" class="graf graf--h4 graf-after--p">getDuration</h4><p name="fdd4" class="graf graf--p graf-after--h4">This method is used to get the total length of the audio file, so you can display the time in your app (as I’ve shown in the screens above). You can get the duration by calling</p><pre name="cb4c" class="graf graf--pre graf-after--p">this.curr_playing_file.getDuration();</pre><p name="06cc" class="graf graf--p graf-after--pre"><strong class="markup--strong markup--p-strong">But</strong>, getting duration in the plugin is a little tricky (or I would say hacky). The plugin doesn’t give away duration directly at the first call. There are two things to note</p><ol class="postList"><li name="001c" class="graf graf--li graf-after--p">If <code class="markup--code markup--li-code">getDuration()</code> is called right after media is created, the duration returned will be -1</li><li name="ed7d" class="graf graf--li graf-after--li">If <code class="markup--code markup--li-code">getDuration()</code> is called without playing the media file even once, the duration returned will still be -1. To avoid this, the hack we use is&nbsp;:</li></ol><ul class="postList"><li name="66bd" class="graf graf--li graf-after--li">Create the media file as usual</li><li name="92f2" class="graf graf--li graf-after--li">Play the media file, but keep the volume to <code class="markup--code markup--li-code">0</code> by calling <code class="markup--code markup--li-code">this.curr_playing_file.setVolume(0.0)</code></li><li name="4958" class="graf graf--li graf-after--li">Call <code class="markup--code markup--li-code">getDuration()</code> in a loop (sadly, yes) until you find a seemingly valid value of duration for the song. Following is my code to get the duration</li></ul><figure tabindex="0" contenteditable="false" name="7a33" class="graf graf--figure graf--iframe graf-after--li"><div class="aspectRatioPlaceholder is-locked"><div class="aspectRatioPlaceholder-fill" style="padding-bottom: 35.699999999999996%;"></div><div class="iframeContainer">{% gist https://gist.github.com/enappd/8af0aa7f07c34a83fe7aea06aa3374c5.js %}</div></div><figcaption class="imageCaption" contenteditable="true" data-default-value="Type caption for embed (optional)">Get duration of the song with this Hacky method</figcaption></figure><p name="e233" class="graf graf--p graf-after--figure">Getting duration takes some time. Hence, as a UX feature you can keep the <strong class="markup--strong markup--p-strong">Play</strong> button disabled till the duration is obtained. And show a nice little loader somewhere to let the user know what is happening.</p><p name="572e" class="graf graf--p graf-after--p"><strong class="markup--strong markup--p-strong">Note</strong>&#8202;—&#8202;Do not forget to <code class="markup--code markup--p-code">clearInterval</code> once the duration is obtained. Otherwise the loop will continue forever.</p><h4 name="2ee0" class="graf graf--h4 graf-after--p">GetCurrentPosition</h4><p name="8db9" class="graf graf--p graf-after--h4"><code class="markup--code markup--p-code">getCurrentPosition</code> is pretty self explanatory. It tells you the current position of song, in seconds. Again, this has a <em class="markup--em markup--p-em">hacky</em> implementation. I hope as the plugin improves, this method would improve to have a non-hacky solution.</p><figure tabindex="0" contenteditable="false" name="4dfe" class="graf graf--figure graf--iframe graf-after--p"><div class="aspectRatioPlaceholder is-locked"><div class="aspectRatioPlaceholder-fill" style="padding-bottom: 35.699999999999996%;"></div><div class="iframeContainer">{% gist https://gist.github.com/enappd/c15977b0ddd1dc103949aac541dad235.js %}</div></div><figcaption class="imageCaption" contenteditable="true" data-default-value="Type caption for embed (optional)">Get current position of song and update the variable to update the Seek Bar</figcaption></figure><p name="77f8" class="graf graf--p graf-after--figure">Notice the <code class="markup--code markup--p-code">toHHMMSS()</code> function I have used for converting seconds into a <code class="markup--code markup--p-code">mm:ss</code> format. This is what you would like to show to your users, instead of an integer value in seconds, as shown below.</p><figure tabindex="0" contenteditable="false" name="f98d" class="graf graf--figure graf-after--p"><div class="aspectRatioPlaceholder is-locked" style="max-width: 441px; max-height: 783px;"><div class="aspectRatioPlaceholder-fill" style="padding-bottom: 177.6%;"></div><img class="graf-image" data-image-id="1*gw2-dpnvqctEqt6nbJECwQ.png" data-width="441" data-height="783" src="https://cdn-images-1.medium.com/max/800/1*gw2-dpnvqctEqt6nbJECwQ.png"><div class="crosshair u-ignoreBlock"></div></div><br/><figcaption class="imageCaption" contenteditable="true" data-default-value="Type caption for image (optional)">Show the time values in mm:ss format for a good&nbsp;UX</figcaption></figure><h4 name="0b47" class="graf graf--h4 graf-after--figure">SeekTo</h4><p name="a16b" class="graf graf--p graf-after--h4">Because a great music player has the ability to jump to a particular time in the song, our plugin also has that capability. The <code class="markup--code markup--p-code">seekTo()</code> method allows users to jump to any moment in the song using the seekbar.</p><p name="29cd" class="graf graf--p graf-after--p">I have implemented the seek bar as an Ionic Range component, where the position of circle is controlled by the <code class="markup--code markup--p-code">ngModel</code>&nbsp;. We can update the <code class="markup--code markup--p-code">position</code> variable using the values from <code class="markup--code markup--p-code">getCurrentPosition()</code> method.</p><pre name="af86" class="graf graf--pre graf-after--p">&lt;ion-range min="0" max="`{{duration}}`" [(ngModel)]="position" color="light"&gt;&lt;/ion-range&gt;</pre><p name="913d" class="graf graf--p graf-after--pre">I have implemented a <strong class="markup--strong markup--p-strong">FastForward</strong> and a <strong class="markup--strong markup--p-strong">Rewind</strong> button to demonstrate this function. The associated code goes like this. E.g. Rewind button with call <code class="markup--code markup--p-code">controlSeconds('back')</code></p><figure tabindex="0" contenteditable="false" name="b3a4" class="graf graf--figure graf--iframe graf-after--p is-defaultValue"><div class="aspectRatioPlaceholder is-locked"><div class="aspectRatioPlaceholder-fill" style="padding-bottom: 35.699999999999996%;"></div><div class="iframeContainer">{% gist https://gist.github.com/enappd/b6e1263b43dbfb9eaa4b50c824790af7.js %}</div></div></figure><h4 name="82ff" class="graf graf--h4 graf-after--figure">Stop</h4><p name="34f9" class="graf graf--p graf-after--h4">When the song is over, we need to stop it. That’s why the plugin has this method to stop the audio playback. Notice that stopping the song does not release it from the memory in Android.</p><pre name="6d01" class="graf graf--pre graf-after--p">this.curr_playing_file.getDuration();</pre><h4 name="5fc7" class="graf graf--h4 graf-after--pre">Release</h4><p name="47df" class="graf graf--p graf-after--h4">Releases the underlying operating system’s audio resources. This is particularly important for Android since there are a finite amount of OpenCore instances for media playback. Applications should call the <code class="markup--code markup--p-code">release</code> function for any <code class="markup--code markup--p-code">Media</code>resource that is no longer needed.</p><h4 name="5482" class="graf graf--h4 graf-after--p">onStatusUpdate</h4><p name="2405" class="graf graf--p graf-after--h4">This is subscribe operation. With this, we can subscribe to the status of the song&#8202;—&#8202;whether it is playing, paused or stopped. This is useful when we want to change the play button to pause, and vice versa.</p><figure tabindex="0" contenteditable="false" name="a359" class="graf graf--figure graf--iframe graf-after--p"><div class="aspectRatioPlaceholder is-locked"><div class="aspectRatioPlaceholder-fill" style="padding-bottom: 35.699999999999996%;"></div><div class="iframeContainer">{% gist https://gist.github.com/enappd/ecfff40c9481d1980c785b5284e368c6.js %}</div></div><figcaption class="imageCaption" contenteditable="true" data-default-value="Type caption for embed (optional)">Get status of the song to change Play / Pause icons etc.</figcaption></figure><h3 name="85c4" class="graf graf--h3 graf-after--figure">Step 4&#8202;—&#8202;Integrate Capacitor in the&nbsp;app</h3><p name="6dc6" class="graf graf--p graf-after--h3">Capacitor can be attached to an existing Ionic app as well. To attach Capacitor to your existing Ionic app, run</p><pre name="e29e" class="graf graf--pre graf-after--p">$ <code class="markup--code markup--pre-code">ionic integrations enable capacitor</code></pre><p name="2503" class="graf graf--p graf-after--pre">This will attach Capacitor to your Ionic app. After this, you have to <code class="markup--code markup--p-code">init</code> the Capacitor app with</p><pre name="c8ac" class="graf graf--pre graf-after--p">$ npx cap init YOUR_APP_NAME YOUR_APP_ID</pre><p name="7269" class="graf graf--p graf-after--pre">You should already be having <code class="markup--code markup--p-code">YOUR_APP_NAME</code> and <code class="markup--code markup--p-code">YOUR_APP_ID</code> in <code class="markup--code markup--p-code">config.xml</code>&nbsp;. Use the same here, so that there is no mismatch or confusion.</p><h3 name="c7bc" class="graf graf--h3 graf-after--p">Step 5— Test on&nbsp;Android</h3><p name="9abb" class="graf graf--p graf-after--h3">Now that everything is ready, we need to build this app for Android. Why&nbsp;? Because Cordova plugins do not work on browser 😆. But the good thing is&nbsp;… Cordova plugins work with Capacitor 😎</p><p name="6245" class="graf graf--p graf-after--p">Before adding a platform to Capacitor, you need to <em class="markup--em markup--p-em">build</em> the app once. Build the app using</p><pre name="4d03" class="graf graf--pre graf-after--p"><code class="markup--code markup--pre-code">$ ionic build</code></pre><p name="ccd4" class="graf graf--p graf-after--pre">Now add Android platform (or iOS)</p><pre name="b984" class="graf graf--pre graf-after--p">$ npx cap add android</pre><p name="d07b" class="graf graf--p graf-after--pre graf--trailing">This should add Android platform to your project.</p></div></div></section><section name="828a" class="section section--body"><div class="section-divider"><hr class="section-divider"></div><div class="section-content"><div class="section-inner sectionLayout--insetColumn"><h4 name="518f" class="graf graf--h4 graf--leading">Troubleshoot Tip</h4><p name="3f6b" class="graf graf--p graf-after--h4">If you face an error saying</p><pre name="a611" class="graf graf--pre graf-after--p">Capacitor could not find the web assets directory "/Users/abhijeetrathore/ionic-4-music/www".</pre><p name="88c3" class="graf graf--p graf-after--pre graf--trailing">Check your <code class="markup--code markup--p-code">capacitor.config.json</code> file. Make sure the <code class="markup--code markup--p-code">webDir</code> field has a value of <code class="markup--code markup--p-code">www</code>&nbsp;. If not, change the <code class="markup--code markup--p-code">webDir</code> field to have the same value as the last parameter of the url showing up in the above error</p></div></div></section><section name="ecd8" class="section section--body section--last"><div class="section-divider"><hr class="section-divider"></div><div class="section-content"><div class="section-inner sectionLayout--insetColumn"><p name="6fce" class="graf graf--p graf--leading">Note, you cannot run the project directly on the phone using CLI in Capacitor. You will have to open the project in Android Studio and run using the Android Studio IDE. Open the project in Android Studio using</p><pre name="c540" class="graf graf--pre graf-after--p"><code class="markup--code markup--pre-code">$ npx cap open android</code></pre><p name="4db5" class="graf graf--p graf-after--pre">Now run the app in your device using Android Studio, and you get this&nbsp;! (Sample from my One Plus 6T, Android P)</p><blockquote name="152b" class="graf graf--blockquote graf-after--p">Note: After adding a platform, if you make any changes in the app, you need to run <code class="markup--code markup--blockquote-code"><em class="markup--em markup--blockquote-em">ionic build</em></code> and then <code class="markup--code markup--blockquote-code"><em class="markup--em markup--blockquote-em">npx cap sync</em></code> to reflect those changes in the native platform</blockquote><p name="7820" class="graf graf--p graf-after--blockquote">Once your app is up and running on the device, you can start testing all the functions. I have recorded a <a href="https://youtu.be/ZYhDC-QQZeA"  class="markup--anchor markup--p-anchor"    target="_blank">video</a> just in case you wanna see it in action!</p><p name="aead" class="graf graf--p graf--empty graf-after--p"  data-default-value="Paste a YouTube, Vine, Vimeo, or other video link, and press Enter"><br></p><p name="43f3" class="graf graf--p graf-after--p">And here you are, playing music in your own Ionic 4 Capacitor app 🎉 🎉</p><h3 name="c219" class="graf graf--h3 graf-after--p">Conclusion</h3><p name="16b0" class="graf graf--p graf-after--h3">In this post, we learned how to implement music player functionalities in a Capacitor Ionic 4 app, using a Cordova plugin. We learned how to use play, pause, seek, etc functionalities. You can now implement music playback in your Ionic 4 apps and create something exciting!</p><blockquote name="d3d0" class="graf graf--blockquote graf-after--p"><strong class="markup--strong markup--blockquote-strong">This demonstration is supported by </strong><a href="https://store.enappd.com/product/ionic-4-spotify-app-starter/"  class="markup--anchor markup--blockquote-anchor" rel="noopener"    target="_blank"><strong class="markup--strong markup--blockquote-strong">Ionic 4 Spotify Starter</strong></a><strong class="markup--strong markup--blockquote-strong"> from Enappd. Complete source code of this tutorial is available here&#8202;—&#8202;</strong><a href="https://github.com/enappd/ionic-4-music"  class="markup--anchor markup--blockquote-anchor" rel="noopener"    target="_blank"><strong class="markup--strong markup--blockquote-strong">Ionic-4-music</strong></a><strong class="markup--strong markup--blockquote-strong"> (capacitor branch)</strong></blockquote><h3 name="cb39" class="graf graf--h3 graf-after--blockquote">Next Steps</h3><p name="d7bd" class="graf graf--p graf-after--h3">Now that you have learned the implementation of Music playback in Ionic Capacitor app, you can also try following blogs for <strong class="markup--strong markup--p-strong">Ionic apps</strong></p><h4 name="ae21" class="graf graf--h4 graf-after--p">Ionic React</h4><ul class="postList"><li name="38a4" class="graf graf--li graf-after--h4"><a href="https://enappd.com/blog/how-to-make-ionic-apps-in-react-using-capacitor/26"  class="markup--anchor markup--li-anchor" rel="noopener"    target="_blank">How to make basic apps in ionic-react</a>-capacitor</li><li name="e379" class="graf graf--li graf-after--li"><a href="https://enappd.com/blog/camera-and-gallery-in-ionic-react-app-using-capacitor/110"  class="markup--anchor markup--li-anchor" rel="noopener"    target="_blank">Camera and Image gallery in Ionic-React-Capacitor</a></li><li name="22af" class="graf graf--li graf-after--li"><a href="https://enappd.com/blog/firebase-push-notification-in-ionic-react-capacitor/111"  class="markup--anchor markup--li-anchor" rel="noopener"    target="_blank">Push notification in Ionic-React-Capacitor apps</a></li><li name="af53" class="graf graf--li graf-after--li"><a href="https://enappd.com/blog/html5-games-in-ionic-capacitor-using-phaser/115"  class="markup--anchor markup--li-anchor" rel="noopener"    target="_blank">Create HTML5 games in Capacitor apps using Phaser</a></li><li name="03ce" class="graf graf--li graf-after--li"><a href="https://enappd.com/blog/icon-splash-in-ionic-react-capacitor-apps/114"  class="markup--anchor markup--li-anchor" rel="noopener"    target="_blank">Adding Icon and Splash in Ionic React Capacitor apps</a></li></ul><p name="e083" class="graf graf--p graf-after--li">If you need a base to start your next <strong class="markup--strong markup--p-strong">Ionic 4 React app</strong>, you can make your next awesome app using <a href="https://store.enappd.com/product/ionic-react-full-app-capacitor/"  class="markup--anchor markup--p-anchor" rel="noopener"    target="_blank">Ionic React Full App</a></p><figure tabindex="0" contenteditable="false" name="5cfa" class="graf graf--figure graf-after--p"><div class="aspectRatioPlaceholder is-locked" style="max-width: 600px; max-height: 600px;"><div class="aspectRatioPlaceholder-fill" style="padding-bottom: 100%;"></div><img class="graf-image" data-image-id="1*ofk4HAMnl1ZXyArf1TxZjQ.jpeg" data-width="600" data-height="600" alt="Ionic 4 React Full App with huge number of layouts and features" src="https://cdn-images-1.medium.com/max/800/1*ofk4HAMnl1ZXyArf1TxZjQ.jpeg"><div class="crosshair u-ignoreBlock"></div></div><br/><figcaption class="imageCaption" contenteditable="true" data-default-value="Type caption for image (optional)">Ionic 4 React Full App with huge number of layouts and&nbsp;features</figcaption></figure><h4 name="bd6f" class="graf graf--h4 graf-after--figure">Ionic Angular</h4><ul class="postList"><li name="39ea" class="graf graf--li graf-after--h4">Ionic 4 Payment Gateways&#8202;—&#8202;<a href="https://enappd.com/blog/ionic-4-stripe-payment-integration-with-firebase-for-apps-and-pwa/17"  class="markup--anchor markup--li-anchor" rel="noopener"    target="_blank">Stripe</a> | <a href="https://enappd.com/blog/ionic-4-paypal-payment-integration-for-apps-and-pwa/16"  class="markup--anchor markup--li-anchor" rel="noopener"    target="_blank">PayPal</a> | <a href="https://enappd.com/blog/how-to-integrate-apple-pay-in-ionic-4-apps/21"  class="markup--anchor markup--li-anchor" rel="noopener"    target="_blank">Apple Pay</a> | <a href="https://enappd.com/blog/how-to-integrate-razorpay-in-ionic-4-apps-and-pwa/20"  class="markup--anchor markup--li-anchor" rel="noopener"    target="_blank">RazorPay</a></li><li name="8665" class="graf graf--li graf-after--li">Ionic 4 Charts with&#8202;—&#8202;<a href="https://enappd.com/blog/ionic-4-charts-using-google-charts/66"  class="markup--anchor markup--li-anchor" rel="noopener"    target="_blank">Google Charts </a>| <a href="https://enappd.com/blog/adding-charts-in-ionic-4-apps-and-pwa-part-3/60"  class="markup--anchor markup--li-anchor" rel="noopener"    target="_blank">HighCharts</a> | <a href="https://enappd.com/blog/adding-charts-in-ionic-4-apps-and-pwa-part-2/54"  class="markup--anchor markup--li-anchor" rel="noopener"    target="_blank">d3.js</a> | <a href="https://enappd.com/blog/charts-in-ionic-4-apps-and-pwa-part-1/52"  class="markup--anchor markup--li-anchor" rel="noopener"    target="_blank">Chart.js</a></li><li name="fd9c" class="graf graf--li graf-after--li">Ionic 4 Social Logins&#8202;—&#8202;<a href="https://enappd.com/blog/facebook-login-in-ionic-4-apps-using-firebase/25"  class="markup--anchor markup--li-anchor" rel="noopener"    target="_blank">Facebook</a> | <a href="https://enappd.com/blog/google-login-in-ionic-4-apps-using-firebase/39"  class="markup--anchor markup--li-anchor" rel="noopener"    target="_blank">Google</a> | <a href="https://enappd.com/blog/twitter-login-in-ionic-4-apps-using-firebase/24"  class="markup--anchor markup--li-anchor" rel="noopener"    target="_blank">Twitter</a></li><li name="31b6" class="graf graf--li graf-after--li">Ionic 4 Authentications&#8202;—&#8202;<a href="https://enappd.com/blog/email-authentication-with-firebase-in-ionic-4/38"  class="markup--anchor markup--li-anchor" rel="noopener"    target="_blank">Via Email</a> | <a href="https://enappd.com/blog/firebase-anonymous-login-in-ionic-4/37"  class="markup--anchor markup--li-anchor" rel="noopener"    target="_blank">Anonymous</a></li><li name="4a75" class="graf graf--li graf-after--li">Ionic 4 Features&#8202;—&#8202;<a href="https://enappd.com/blog/using-geolocation-geocoding-and-reverse-geocoding-in-ionic-4/45"  class="markup--anchor markup--li-anchor" rel="noopener"    target="_blank">Geolocation</a> | <a href="https://enappd.com/blog/qr-code-scanning-and-optical-character-recognition-ocr-in-ionic-4/9"  class="markup--anchor markup--li-anchor" rel="noopener"    target="_blank">QR Code reader </a>| <a href="https://enappd.com/blog/best-fitness-plugins-for-ionic-4-how-to-use-pedometer/15"  class="markup--anchor markup--li-anchor" rel="noopener"    target="_blank">Pedometer</a></li><li name="819d" class="graf graf--li graf-after--li">Media in Ionic 4&#8202;—&#8202;<a href="https://enappd.com/blog/spotify-like-music-in-ionic-4-apps/48"  class="markup--anchor markup--li-anchor" rel="noopener"    target="_blank">Audio</a> | <a href="https://enappd.com/blog/adding-video-player-in-ionic-4-app/64"  class="markup--anchor markup--li-anchor" rel="noopener"    target="_blank">Video</a> | <a href="https://enappd.com/blog/image-picker-in-ionic-4-app/67"  class="markup--anchor markup--li-anchor" rel="noopener"    target="_blank">Image Picker</a> | <a href="https://enappd.com/blog/how-to-add-image-cropper-in-ionic-4-app/68"  class="markup--anchor markup--li-anchor" rel="noopener"    target="_blank">Image Cropper</a></li><li name="eee3" class="graf graf--li graf-after--li">Ionic 4 Essentials&#8202;—&#8202;<a href="https://enappd.com/blog/ionic-4-save-and-retrieve-data-locally-on-device/59"  class="markup--anchor markup--li-anchor" rel="noopener"    target="_blank">Native Storage</a> | <a href="https://enappd.com/blog/how-to-translate-in-ionic-4-globalization-internationalization-and-localization/11"  class="markup--anchor markup--li-anchor" rel="noopener"    target="_blank">Translations</a> | <a href="https://enappd.com/blog/rtl-right-to-left-use-in-ionic-4/50"  class="markup--anchor markup--li-anchor" rel="noopener"    target="_blank">RTL</a></li><li name="8bbe" class="graf graf--li graf-after--li">Ionic 4 messaging&#8202;—&#8202;<a href="https://enappd.com/blog/implement-ionic-4-firebase-push/34"  class="markup--anchor markup--li-anchor" rel="noopener"    target="_blank">Firebase Push</a> | <a href="https://enappd.com/blog/automatically-read-sms-in-ionic-4-apps/42"  class="markup--anchor markup--li-anchor" rel="noopener"    target="_blank">Reading SMS</a></li><li name="2467" class="graf graf--li graf-after--li">Ionic 4 with Firebase&#8202;—&#8202;<a href="https://enappd.com/blog/how-to-integrate-firebase-in-ionic-4-apps/23"  class="markup--anchor markup--li-anchor" rel="noopener"    target="_blank">Basics</a> | <a href="https://enappd.com/blog/firebase-with-ionic-4-hosting-auth-and-db-connection/58"  class="markup--anchor markup--li-anchor" rel="noopener"    target="_blank">Hosting and DB</a> | <a href="https://enappd.com/blog/firebase-cloud-functions-in-ionic-4-complete-guide/32"  class="markup--anchor markup--li-anchor" rel="noopener"    target="_blank">Cloud functions</a></li></ul><p name="2c47" class="graf graf--p graf-after--li">If you need a base to start your next <strong class="markup--strong markup--p-strong">Ionic 4 Angular app</strong>, you can make your next awesome app using <a href="https://store.enappd.com/product/ionic-4-full-app"  class="markup--anchor markup--p-anchor" rel="noopener"    target="_blank">Ionic 4 Full App</a></p><figure tabindex="0" contenteditable="false" name="0c02" class="graf graf--figure graf-after--p"><div class="aspectRatioPlaceholder is-locked" style="max-width: 560px; max-height: 353px;"><div class="aspectRatioPlaceholder-fill" style="padding-bottom: 63%;"></div><img class="graf-image" data-image-id="0*FEEIJR0kJXNBCWUo.jpeg" data-width="560" data-height="353" alt="Ionic 4 Full App with huge number of layouts and features" src="https://cdn-images-1.medium.com/max/800/0*FEEIJR0kJXNBCWUo.jpeg"><div class="crosshair u-ignoreBlock"></div></div><br/><figcaption class="imageCaption" contenteditable="true" data-default-value="Type caption for image (optional)">Ionic 4 Full App with huge number of layouts and&nbsp;features</figcaption></figure><p name="660f" class="graf graf--p graf--empty graf-after--figure graf--trailing"><br></p></div></div></section></div></article></main>