Developing an android radio app for phones and Wear OS

Promise Ochornma
3 min readDec 26, 2019

--

Photo by Matt Botsford on Unsplash

I, decided to pen down my thoughts and experience from developing the DCLM Radio app

The Radio Fragment

To develop a radio app, it is important to seek permission for foreground service, wake lock and internet.

From android documentation, the android:networkSecurityConfig “lets apps customize their network security settings in a safe, declarative configuration file without modifying app code. These settings can be configured for specific domains and for a specific app.”

From the documentation, the followings are the key capabilities of this feature

Custom trust anchors: Customize which Certificate Authorities (CA) are trusted for an app’s secure connections. For example, trusting particular self-signed certificates or restricting the set of public CAs that the app trusts.

Debug-only overrides: Safely debug secure connections in an app without added risk to the installed base.

Cleartext traffic opt-out: Protect apps from accidental usage of cleartext traffic.

Certificate pinning: Restrict an app’s secure connection to particular certificates.

From my experience, this is necessary if the domain throws http and you need your app to function on Android 8 and above. Below is a format for the network configuration xml file.

I optimized the app to function on standalone Wear OS. To do this, I added a new module from the file menu > New > New Module and then selected the WearOS Module. then updated the build.gradle of the wear mode with the following


implementation 'androidx.wear:wear:1.0.0'
implementation 'com.google.android.support:wearable:2.5.0'
compileOnly 'com.google.android.wearable:wearable:2.5.0'

Then the WearOS manifest file updated to allow the app run WearOS

For the app to work both on square and round wearOS, you need this attribute boxedEdges on the wearOS layout file.

I used the Exoplayer library as against the Android multimedia framework (MediaPlayer).

The Exoplayer supports DASH Streaming, HLS which are not supported by MediaPlayer.

Below is the layout for the app

Since the app will be playing on background even when the activity lifecycle is in onStop state we will need the Android service.

We will be using the Foreground service and will be bounding it to the MainActivity.

For the audio focus I choose C.CONTENT_TYPE_SPEECH since I want the radio to pause, when another audio is played since it is a podcast. There are other types you can choose such as C.CONTENT_TYPE_MOVIE, C.CONTENT_TYPE_MUSIC, C.CONTENT_TYPE_SONIFICATIONor C.CONTENT_TYPE_UNKNOWN.

I also increased the DefaultHttpDataSourceFactory connection and read timeout to 30 Seconds because the default time was giving socket timeout exception (Caused by: java.net.SocketTimeoutException: connect timed out)

For the onDestroy, I used the boolean check to detect if the mediaSession, mediaSessionConnector, playerNotificationManager and the player is not null.

If they are null, trying to release those resources will throw a nullpointer exception

Above is the MainActivity of the app. It is bounded to the service at the onStart lifecycle of the app and unbounded in the onStop.

It is important to check if the WearOS has an inbuilt speaker device before starting the background service as this is one of the prerequisite for developing a media player for WearOS as stated on Android guide for WearOS

Whenever the app is destroyed, the background service is stopped/destroyed (stopService()).

The exoplayer/service is started using the Util.startForegroundService(MainActivity.this, intent);

Note: if the service need to be stated before it can persist even when the app is in onStop state and that’s the reason the player is started in the onStartCommand of the RadioService even the Notification, media session and media session connector

The buttonLive is used to recreate the player, if the app has been paused for a long time. It is intended to imitate the YouTube live button.

--

--