Chapters

Hide chapters

Android Apprentice

Third Edition · Android 10 · Kotlin 1.3 · Android Studio 3.6

Before You Begin

Section 0: 4 chapters
Show chapters Hide chapters

Section II: Building a List App

Section 2: 7 chapters
Show chapters Hide chapters

Section III: Creating Map-Based Apps

Section 3: 7 chapters
Show chapters Hide chapters

20. Networking
Written by Tom Blankenship

Heads up... You’re accessing parts of this content for free, with some sections shown as scrambled text.

Heads up... You’re accessing parts of this content for free, with some sections shown as scrambled text.

Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.

Unlock now

In this section, you’re going to utilize many of the skills you’ve already learned and dive into some more advanced areas of Android development. You’ll build a full-featured podcast manager and player app named PodPlay. This app will allow searching and subscribing to podcasts from iTunes and provide a playback interface with speed controls.

The following new topics are covered:

  • Android networking.
  • Retrofit REST API library.
  • XML Parsing.
  • Search activity.
  • MediaPlayer library.

Getting started

PodPlay will contain these main features:

  1. Quick searching of podcasts by keyword or name.

  1. Display for previewing podcast episodes.

  1. Playback of audio and video podcasts.

  1. Subscribing to your favorite podcasts.

  1. Playback at various speeds.

Project set up

You’ll start by creating a project with a single empty Activity. This app uses the same structure as PlaceBook, but it will also add a new services layer.

Where are the podcasts?

Before you get to the fun part of podcast playback, you need to answer a fundamental question: Where do podcasts come from? The answer is just about anywhere. Podcasts are distributed using a standard format called RSS (Rich Site Summary, commonly referred to as Really Simple Syndication).

Android networking

So far, all of the apps you’ve built during your apprenticeship have been self-contained. They have not had to access any remote or network-based services directly. Although PlaceBook did access Google Places and download place photos, that was all handled by the Places library. That’s about to change with PodPlay.

PodPlay architecture

Continuing with the layered architecture, you’ll create a service layer that handles all network access to iTunes and hides the details of that communication. This will make it easy to swap out different methods for network access, without affecting any other parts of the code.

iTunes search service

If you regularly listen to or have ever created a podcast, you’re probably familiar with the iTunes podcast directory. This provides a single place to find almost any podcast from a variety of categories.

Retrofit

Now that you know how to get search results, the next step is to turn them into data models.

Defining Retrofit dependencies

First, you need to define the Retrofit dependency.

ext {
  kotlin_version = '1.3.61'
  retrofit_version = '2.7.1'
}
implementation "com.squareup.retrofit2:retrofit:$retrofit_version"
implementation "com.squareup.retrofit2:converter-gson:$retrofit_version"
compileOptions {
  sourceCompatibility = 1.8
  targetCompatibility = 1.8
}
kotlinOptions {
  jvmTarget = JavaVersion.VERSION_1_8.toString()
}

Creating the podcast response model

Now you’ll create the model that represents a response from the iTunes service.

data class PodcastResponse(
    val resultCount: Int,
    val results: List<ItunesPodcast>) {

  data class ItunesPodcast(
      val collectionCensoredName: String,
      val feedUrl: String,
      val artworkUrl30: String,
      val releaseDate: String
  )
}
interface ItunesService {
  // 1
  @GET("/search?media=podcast")
  // 2
  fun searchPodcastByTerm(@Query("term") term: String):
      Call<PodcastResponse>
  // 3
  companion object {
    // 4
    val instance: ItunesService by lazy {
      // 5
      val retrofit = Retrofit.Builder()
          .baseUrl("https://itunes.apple.com")
          .addConverterFactory(GsonConverterFactory.create())
          .build()
      // 6
      retrofit.create<ItunesService>(ItunesService::class.java)
    }
  }
}
// 1
class ItunesRepo(private val itunesService: ItunesService) {
  // 2
  fun searchByTerm(term: String,
      callBack: (List<ItunesPodcast>?) -> Unit) {
    // 3
    val podcastCall = itunesService.searchPodcastByTerm(term)
    // 4
    podcastCall.enqueue(object : Callback<PodcastResponse> {    
      // 5
      override fun onFailure(call: Call<PodcastResponse>?,
          t: Throwable?) {
        // 6
        callBack(null)
      }
      // 7
      override fun onResponse(
          call: Call<PodcastResponse>?,
          response: Response<PodcastResponse>?) {
        // 8
        val body = response?.body()
        // 9
        callBack(body?.results)
      }
    })
  }
}
val TAG = javaClass.simpleName

val itunesService = ItunesService.instance

val itunesRepo = ItunesRepo(itunesService)

itunesRepo.searchByTerm("Android Developer") {
  Log.i(TAG, "Results = $it")
}
<uses-permission android:name="android.permission.INTERNET"/>
I/PodcastActivity: Results = [ItunesPodcast(collectionCensoredName=Fragmented - Android Developer Podcast, feedUrl=https://rss.simplecast.com/podcasts/1684/rss, artworkUrl30=http://is5.mzstatic.com/image/thumb/Music62/v4/4a/6f/e7/4a6fe7c8-7ca1-c43f-241d-f7e84a014f1b/source/30x30bb.jpg, releaseDate=2017-09-18T05:00:00Z), ItunesPodcast(collectionCensoredName=Android Developers Backstage, feedUrl=http://feeds.feedburner.com/blogspot/AndroidDevelopersBackstage, artworkUrl30=http://is3.mzstatic.com/image/thumb/Music62/v4/15/c9/96/15c996fd-4856-79bb-12ba-1d25c67d77d7/source/30x30bb.jpg, releaseDate=2017-09-11T17:20:00Z), ItunesPodcast(collectionCensoredName=The Android Cast, feedUrl=http://www.buzzsprout.com/60878.rss, artworkUrl30=http://is1.mzstatic.com/image/thumb/Music71/v4/8d/b5/4c/8db54c53-75c0-b214-9606-a228e19f49f9/source/30x30bb.jpg, releaseDate=2016-10-08T07:00:00Z)]

Where to go from here?

The term dependency injection was mentioned briefly when you created the iTunesRepo class. You used a simple form of dependency injection when you passed in the ItunesService instance to the iTunesRepo constructor.

Have a technical question? Want to report a bug? You can ask questions and report bugs to the book authors in our official book forum here.
© 2024 Kodeco Inc.

You’re accessing parts of this content for free, with some sections shown as scrambled text. Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.

Unlock now