Swift Radio, now on Android

People kept asking for it. Every few months, someone would open an issue or send an email: "Is there an Android version?" For ten years, the answer was no. Swift Radio was iOS-only. Now it runs on both.

Swift Radio Android is not a wrapper or a cross-platform port. It is a native Android app, built from scratch with Kotlin and Jetpack Compose. If you already run the iOS version, the same stations.json file works on both platforms without changes. Drop it in and your stations show up.

Swift Radio Android station list showing six stations with album art and a now playing bar at the bottom
Swift Radio Android now playing screen with full-screen album art, track name, and LIVE indicator

Same format, different platform

The iOS and Android versions share the same station JSON schema. If you have a remote stations.json powering Swift Radio on iOS, point the Android app at the same URL and it works. No conversion, no mapping. This was a deliberate choice to make maintaining both platforms as simple as changing one file.

{
  "station": [
    {
      "name": "Station Name",
      "streamURL": "https://example.com/stream",
      "imageURL": "station-image",
      "desc": "Short description",
      "longDesc": "Detailed description for the info sheet.",
      "website": "https://example.com"
    }
  ]
}

Station images can be bundled assets or remote URLs, same as iOS.

What it does

The feature set matches the iOS version where it matters, and uses Android-native equivalents where the platforms diverge:

  • Android Auto: full browse tree with station artwork, playback controls, and metadata. Think of it as CarPlay, but for the other side of the aisle.
  • Background playback: audio continues when the app is backgrounded, with lock screen and notification controls via a Media3 session.
  • Live metadata: ICY stream metadata updates the track name and artist in real time. Album art pulls from the iTunes Search API when available.
  • Search and filter: a search bar filters stations by name or description. Toggled on or off in Config.kt.
  • Material You: on Android 12+, the app picks up the device's dynamic color palette. On older devices, it falls back to a default dark theme.
  • Pull-to-refresh: swipe down on the station list to reload from the JSON source.
  • Localization-ready: all user-facing strings live in strings.xml. Add a values-XX folder for a new language and Android handles the rest.

Under the hood

The entire UI is Jetpack Compose with Material 3. No XML layouts, no fragments. Navigation between the station list and the now playing screen uses Compose navigation with a shared PlayerViewModel that bridges the UI to the audio service.

Audio playback runs on Media3 ExoPlayer inside a foreground service. The MediaLibraryService exposes a browse tree for Android Auto and any other MediaBrowser client. Artwork for bundled station images is embedded directly into the media metadata as a byte array, because Android Auto cannot resolve file:///android_asset/ URIs the way a local app can.

Networking uses Ktor with Kotlinx Serialization for JSON parsing, and Coil handles image loading and caching throughout the app.

LibraryPurpose
AndroidX Media3Audio playback, media session, Android Auto
Jetpack ComposeUI framework with Material 3
CoilImage loading and caching
KtorHTTP client for remote station loading
Kotlinx SerializationJSON parsing

Getting started

The setup is the same idea as the iOS version. Fork, configure, build:

  1. Open the project in Android Studio
  2. Edit Config.kt to set your stations URL, contact info, and feature flags
  3. Replace the stations in app/src/main/assets/stations.json with your own
  4. Build and run

The app targets Android 7.0+ (API 24), which covers the vast majority of active devices.

About the name

Yes, it is called Swift Radio and it is written in Kotlin. The name comes from the iOS original, which has been around since 2015 and has nearly 3,000 stars on GitHub. The Android version keeps the name because the project, the station format, and the community are the same. The language is just a detail.

What's next

The v3 iOS release laid the groundwork for a shared architecture across platforms. The Android version is now at feature parity for the core experience. Next up: a single-station version for both iOS and Android, bundled together.

Star the repo if it is useful, fork it if you want to make it yours.