Chapters

Hide chapters

Android Apprentice

Fourth Edition · Android 11 · Kotlin 1.4 · Android Studio 4.1

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 Kevin D Moore

Heads up... You're reading this book for free, with parts of this chapter shown beyond this point as scrambled text.

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.

Introducing 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.4.21'
  coroutines_version = '1.4.2'
  retrofit_version = '2.9.0'
}
implementation "com.squareup.retrofit2:retrofit:$retrofit_version"
implementation "com.squareup.retrofit2:converter-gson:$retrofit_version"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_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
  suspend fun searchPodcastByTerm(@Query("term") term: String): Response<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::class.java)
    }
  }
}
// 1
class ItunesRepo(private val itunesService: ItunesService) {
  // 2
  suspend fun searchByTerm(term: String) = itunesService.searchPodcastByTerm(term) // 3
}
val TAG = javaClass.simpleName
val itunesService = ItunesService.instance
val itunesRepo = ItunesRepo(itunesService)

GlobalScope.launch {
  val results = itunesRepo.searchByTerm("Android Developer")
  Log.i(TAG, "Results = ${results.body()")
}
<uses-permission android:name="android.permission.INTERNET"/>
I/PodcastActivity: Results = PodcastResponse(resultCount=4, results=[ItunesPodcast(collectionCensoredName=Android Developers Backstage, feedUrl=http://feeds.feedburner.com/blogspot/AndroidDevelopersBackstage, artworkUrl30=https://is5-ssl.mzstatic.com/image/thumb/Podcasts113/v4/27/04/86/2704860b-686b-99a8-d97e-c475983bc904/mza_2743413905807513331.png/30x30bb.jpg, releaseDate=2020-12-23T14:30:00Z), ItunesPodcast(collectionCensoredName=Droid Dev Talk, feedUrl=https://anchor.fm/s/f117d30/podcast/rss, artworkUrl30=https://is1-ssl.mzstatic.com/image/thumb/Podcasts113/v4/d2/3b/62/d23b62c7-746d-32e0-a070-845e750522c0/mza_6742547218733609407.jpg/30x30bb.jpg, releaseDate=2020-09-19T07:21:00Z), ItunesPodcast(collectionCensoredName=Menjadi Android Developer Expert, feedUrl=https://anchor.fm/s/c5be3dc/podcast/rss, artworkUrl30=https://is1-ssl.mzstatic.com/image/thumb/Podcasts123/v4/99/b5/f7/99b5f713-e6e0-794b-a888-b4bd67b6b548/mza_3930316646477617026.jpg/30x30bb.jpg, releaseDate=2019-08-25T05:00:00Z), ItunesPodcast(collectionCensoredName=How to pick a android app developer in India : The Insider’s Guide, feedUrl=https://anchor.fm/s/1c33bac8/podcast/rss, artworkUrl30=https://is3-ssl.mzstatic.com/image/thumb/Podcasts113/v4/0a/9f/73/0a9f73fa-9bf3-cc13-7902-51e2f2e8dbd7/mza_16007747104321932097.jpg/30x30bb.jpg, releaseDate=2020-07-14T07:27:00Z)])

Key Points

In this chapter you learned:

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 reading for free, with parts of this chapter shown as scrambled text. Unlock this book, and our entire catalogue of books and videos, with a Kodeco Personal Plan.

Unlock now