<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Abdurahman Adilovic</title>
    <description>The latest articles on Forem by Abdurahman Adilovic (@abdurahmanadilovic).</description>
    <link>https://forem.com/abdurahmanadilovic</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F356312%2Fdc2a22ff-45e9-417d-94dd-149c38d5375e.jpeg</url>
      <title>Forem: Abdurahman Adilovic</title>
      <link>https://forem.com/abdurahmanadilovic</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/abdurahmanadilovic"/>
    <language>en</language>
    <item>
      <title>Building a podcast app series: 3. Exoplayer</title>
      <dc:creator>Abdurahman Adilovic</dc:creator>
      <pubDate>Tue, 21 Jul 2020 20:14:01 +0000</pubDate>
      <link>https://forem.com/abdurahmanadilovic/building-a-podcast-app-series-3-exoplayer-3718</link>
      <guid>https://forem.com/abdurahmanadilovic/building-a-podcast-app-series-3-exoplayer-3718</guid>
      <description>&lt;p&gt;What is a podcast app if not a wrapper around a media player? And, if we talk Android, there is the only one media player worth considering, ExoPlayer, made by Google engineers. Let’s look at how can we connect all the pieces we have built so far and actually connect the ExoPlayer with the view within the app.&lt;/p&gt;

&lt;h2&gt;
  
  
  ExoPlayer
&lt;/h2&gt;

&lt;p&gt;Exoplayer is very powerful and modular, we are going to use just a fraction of what ExoPlayer really offers. ExoPlayer has a couple of core components that have to work together for it to play anything, in no particular order:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;ExoPlayer instance&lt;/li&gt;
&lt;li&gt;MediaSource&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We need to create an ExoPlayer instance and hold it in memory since it is pretty expensive to create. We will reuse a single instance throughout the app. For it to play anything, we need to create a MediaSource. These sources are basically different types of streams that ExoPlayer has to read in order to fetch the audio data and play it. There are other important parts to the ExoPlayer ecosystem but for starters, we need those two basic things.&lt;/p&gt;

&lt;h2&gt;
  
  
  ExoPlayer instance
&lt;/h2&gt;

&lt;p&gt;This is the heart of ExoPlayer and the object itself. We can simply create a single instance and pass or not pass a bunch of configuration options. Let’s keep it simple and create a basic instance:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;player&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;SimpleExoPlayer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Builder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  MediaSource
&lt;/h2&gt;

&lt;p&gt;So the name of this class is pretty self-explanatory, we have to be aware of the fact that there are a couple of different media sources, depending on the actual source that serves the content:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;DashMediaSource for DASH.&lt;/li&gt;
&lt;li&gt;SsMediaSource for SmoothStreaming.&lt;/li&gt;
&lt;li&gt;HlsMediaSource for HLS.&lt;/li&gt;
&lt;li&gt;ProgressiveMediaSource for regular media files.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s create a simple media source:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;mediaSource&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
   &lt;span class="nc"&gt;ProgressiveMediaSource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Factory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dataSourceFactory&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;
        &lt;span class="nf"&gt;createMediaSource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Uri&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mp3Url&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;        
  &lt;span class="n"&gt;exoPlayer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;prepare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mediaSources&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that’s it. We can now play an episode!&lt;/p&gt;

&lt;p&gt;Since we are building a podcast player, it is safe to assume we will never play one episode at a time, so we need a way to tell ExoPlayer to play the next item when one item is finished playing. To handle that, ExoPlayer has a concept of the concatenated media source. We can bundle together a bunch of media sources, they don’t have to be of the same type, and attach that source to the ExoPlayer instance.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;mediaSources&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;listOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;currentEpisode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;_playlist&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nc"&gt;ProgressiveMediaSource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Factory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dataSourceFactory&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;
        &lt;span class="nf"&gt;createMediaSource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Uri&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mp3Url&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;        
   &lt;span class="p"&gt;}.&lt;/span&gt;&lt;span class="nf"&gt;toTypedArray&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;exoPlayer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;prepare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ConcatenatingMediaSource&lt;/span&gt;&lt;span class="p"&gt;(*&lt;/span&gt;&lt;span class="n"&gt;mediaSources&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So instead of passing just one media source, we can pass in a concatenating media source and the ExoPlayer will automatically play all episodes from that playlist.&lt;/p&gt;

&lt;p&gt;Browse the full code on this &lt;a href="https://github.com/abdurahmanadilovic/podcast-guru/blob/master/app/src/main/java/ba/codingstoic/player/PlayerViewModel.kt" rel="noopener noreferrer"&gt;link&lt;/a&gt; and in the next article, we will talk about a foreground service that needs to run our ExoPlayer and keep our app in the background so Android does not shut down our app to claim more resources :).&lt;/p&gt;

</description>
      <category>kotlin</category>
      <category>android</category>
      <category>exoplayer</category>
      <category>podcast</category>
    </item>
    <item>
      <title>Building a podcast app series: 2. Player state</title>
      <dc:creator>Abdurahman Adilovic</dc:creator>
      <pubDate>Tue, 07 Jul 2020 10:15:14 +0000</pubDate>
      <link>https://forem.com/abdurahmanadilovic/building-a-podcast-app-series-2-player-state-4men</link>
      <guid>https://forem.com/abdurahmanadilovic/building-a-podcast-app-series-2-player-state-4men</guid>
      <description>&lt;p&gt;After the view is set up, it’s very important to have a model that will drive that UI, something that we can observe and render our UI according to its state. It would be nice to react to model changes with some kind of a listener and it would be great if we don’t have to manually subscribe/unsubscribe to this model. Luckily, Android has a ViewModel class that is built for this exact purpose.&lt;/p&gt;

&lt;h3&gt;
  
  
  ViewModel
&lt;/h3&gt;

&lt;p&gt;View modes are a relatively new invention. Before ViewModels came along, and the whole AAC (android architecture components), representing ViewModels in a clean and safe way was particularly tricky. Android activity or a fragment can be in multiple states and properly connecting/disconnecting a particular activity or a fragment is a dance around onCreate / onDestrory, onResume / onPause, and other lifecycle methods. Since our in-app player view is visible on all screens, wee need a globally accessible state holder for that player. Luckily, a ViewModel is all we need to safely share the player state across different fragments. Since we are using a single activity pattern, ViewModels are automatically tied to that activity and can be shared across fragments! This means that we can easily tell other views what is the state of our in-app player by just sharing a ViewModel across multiple fragments! Oh, by the way, ViewModels survive configuration change, so that is also being taken care of.&lt;/p&gt;

&lt;p&gt;So, how do we create a new view model? We can simply write in any fragment&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;playerViewModel&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt; &lt;span class="n"&gt;sharedViewModel&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;PlayerViewModel&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The basic idea here is that ViewModels do not care who is using its LiveData, it can be a single fragment or bunch of them, it does not matter. ViewModels should not reference any Fragment or Activity, they simply expose data for Views to observe!&lt;/p&gt;

&lt;p&gt;If you are curious about the code for the PlayerViewModel check out this &lt;a href="https://github.com/abdurahmanadilovic/podcast-guru/blob/master/app/src/main/java/ba/codingstoic/player/PlayerViewModel.kt" rel="noopener noreferrer"&gt;link&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  LiveData
&lt;/h3&gt;

&lt;p&gt;Once we have a shared state holder for our player, we need a safe way to update our views. That is where LiveData comes in, it is a safe container for any kind of data. And the best part about LiveData is that it automatically knows if our fragment or activity is active and can receive updates, so we don’t have to handle that logic ourselves! This means no more null pointer exceptions of illegal state exceptions. We are free to post new data to LiveData and be sure that nothing will crash as a result of that.&lt;/p&gt;

&lt;p&gt;How do we create and update live data?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;_currentlyPlaying&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;MutableLiveData&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Episode&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;()&lt;/span&gt;
&lt;span class="n"&gt;currentlyPlaying&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;currentEpisode&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Repository pattern
&lt;/h3&gt;

&lt;p&gt;The last piece of the state puzzle is to identify where does our data come from? In a simple word: from a Repository of Podcasts! Repository pattern is such a simple pattern and very useful. We can make our Repository do a bunch of interesting things. We can cache data to the local DB, we can mock our data, we can fetch something from the internet, everything related to data, and its retrieval is hidden behind our Repository class.&lt;/p&gt;

&lt;p&gt;How does a simple repository look like?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PodcastRepository&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;getPodcasts&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Podcast&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
        &lt;span class="nf"&gt;listOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Podcast&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"The Joe Rogan experience"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Basic setup for every screen
&lt;/h3&gt;

&lt;p&gt;In conclusion, every screen in our app will reference ViewModels and will subscribe to a LiveData. ViewModels will fetch data from Repositories and update a LiveData and we have a reactive setup for each screen in our app. Error handling is done in the same manner, we just have a LiveData of error messages where we can push errors and observe them inside Fragments.&lt;/p&gt;

&lt;p&gt;Browse the full code on this &lt;a href="https://github.com/codingstoic/podcast-guru" rel="noopener noreferrer"&gt;link&lt;/a&gt;. Stay tuned for the next article in this series where we explore exoPlyaer, brains behind any podcast app.&lt;/p&gt;

</description>
      <category>android</category>
      <category>kotlin</category>
      <category>exoplayer</category>
    </item>
    <item>
      <title>Android - Building a podcast app series: 1. mini in-app player</title>
      <dc:creator>Abdurahman Adilovic</dc:creator>
      <pubDate>Tue, 30 Jun 2020 14:34:44 +0000</pubDate>
      <link>https://forem.com/abdurahmanadilovic/building-a-podcast-app-series-1-mini-in-app-player-7k0</link>
      <guid>https://forem.com/abdurahmanadilovic/building-a-podcast-app-series-1-mini-in-app-player-7k0</guid>
      <description>&lt;p&gt;I am currently working on a project to rewrite an existing podcast app that was originally built with xamarin into a fully native Android app. The most important feature of any podcast app is the player, and specifically, the in-app player that has to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;be visible on all screens&lt;/li&gt;
&lt;li&gt;have collapsed and expanded view&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s clarify the second point, the in-app player should have two modes, collapsed mode where the player’s view is small and should sit below the main content. The second mode is expanded mode, where the player’s view should occupy the whole screen. Ideally, there should be an animation when the player is transitioning between those two states. Let’s talk about solving problem number 1.&lt;/p&gt;

&lt;h2&gt;
  
  
  Navigation library
&lt;/h2&gt;

&lt;p&gt;If we use the navigation library and single activity pattern from AAC (android architecture components), we can easily make our in-app player visible on all screens by restricting the navigation host fragment to be above the in-app player’s view. Since the navigation framework loads / unloads all views inside the navigation host fragment, we can make all views in our app span just up to the in-app player. If the player is hidden, all views automatically span over it, otherwise, they will span to just above the player.&lt;/p&gt;

&lt;p&gt;A nice side effect of using the single activity pattern is the player itself will be configured from one place, main activity, and in combination with a view model, we can implement the player without violating the DRY principle. Now let’s talk about implementing the second feature.&lt;br&gt;
Layout behavior&lt;/p&gt;

&lt;p&gt;Ever since the coordinator layout came out, Android became a lot more flexible in terms of animations and interaction between views. In this specific use case all I had to do was to write a normal constraint layout and add one line to it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;androidx.constraintlayout.widget.ConstraintLayout&lt;/span&gt;
&lt;span class="err"&gt;....&lt;/span&gt;
&lt;span class="na"&gt;app:layout_behavior=&lt;/span&gt;&lt;span class="s"&gt;"com.google.android.material.bottomsheet.BottomSheetBehavior"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That was enough to have a view that can sit on the bottom of the screen, be expanded and animate those state changes out of the box. Pretty awesome if you ask me. So, how does the final layout look like?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;CoordinatorLayout&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;MainContent/&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;InAppPlayer/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/CoordinatorLayout&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Of course, nothing is this simple, is it? :). But, what if our app has tabs and a BottomNavigationView? Our in-app player should, of course, sit above the BottomNavigationView but below the main content. One solution to this edge case is to position the main content above the bottom tabs’ view using constraint layout.&lt;/p&gt;

&lt;h2&gt;
  
  
  DRY principle and ViewModel
&lt;/h2&gt;

&lt;p&gt;Since the player exists across multiple screens (fragments), we need a view model to group together all the player features in one place and just reuse the view model across all views. What better way to implement this than to use AAC ViewModel class. We can easily share this view model across fragments and have a player UI in sync at all times. PlayerViewModel can get data from a PodcastRepository class which will make network calls or read from the local database.&lt;/p&gt;

&lt;p&gt;Please refer to this &lt;a href="https://github.com/codingstoic/podcast-guru" rel="noopener noreferrer"&gt;GitHub link&lt;/a&gt; for the code.&lt;/p&gt;

&lt;p&gt;Stay tuned for the next article in this series!&lt;/p&gt;

</description>
      <category>android</category>
      <category>exoplayer</category>
      <category>kotlin</category>
    </item>
  </channel>
</rss>
