Skip to content

A Kotlin Multiplatform mobile app to explore live radio stations on a 2D world map with song detection & AI-powered insights.

License

Notifications You must be signed in to change notification settings

realBoltDev/GeoTunes

Repository files navigation

Kotlin

GeoTunes

GeoTunes is a Kotlin Multiplatform app that lets you discover live radio stations from around the world using an interactive 2D map. It lets you stream radio stations and play songs, identify them in real time, and shows what the song is about using AI. You can also build your personal library by saving the songs and ask AI about your saved songs, music taste, or get recommendations as you want.

Built with Compose Multiplatform for Android and iOS, GeoTunes demonstrates how modern Kotlin can used to build such a cross-platform application.

Demo

Demo.mp4

Background (Essay)

I am an undergraduate Computer Science student and I have worked with technologies like Python, JavaScript, Kotlin, C++ in past few years. I genuinely enjoy building things from scratch, taking up challenging ideas and turning them into working projects has helped me develop strong problem solving skills. Compared to backend and general programming, I have had relatively less experience with building native mobile apps. I used to make mobile apps with drag-and-drop tools like Kodular and MIT App Inventor when I was in school.

I listen to a wide variety of music across different genres, languages, and cultures. I wanted to make an app that would let me discover music from different parts of the world, identify those songs in real time, and help me understand their cultural or emotional context.

So I set out to create GeoTunes — a Kotlin Multiplatform app built using Compose Multiplatform for Android and iOS where I used open-source Radio Browser API to get the radio stations data and Shazam to detect the songs playing on the radio. Google Gemini is used to generate summaries of the song and it also powers the AI chat. My experience in Node.js/Express helped me make a REST API server to process the radio stations data and use in the app. This project reflects my interest in music, culture, and modern cross-platform app development. It helped me learn new and advanced concepts of Kotlin Multiplatform along the way.

Screens & Features

  • Discover Screen

    • Interactive 2D Map
    • Dice roll button for random station
    • Play/Pause audio stream
    • Station name, city & country info
    • Detect songs playing live
    • Save to library
    • Get song summary from AI
  • Ask AI Screen

    • Chat with AI
    • Last 10 messages used for context preservation
    • Clear conversation history and context with delete button
  • Library Screen

    • Saved songs shown here
    • Remove songs from library using delete button

How to Run

Requirements

  • macOS for iOS device builds
  • IntelliJ IDEA or Android Studio
  • XCode
  • JDK
  • Kotlin Multiplatform Plugin
  • Node.js
  • Apple Developer Account
  • Maptiler Account
  • Google Gemini

Platforms Supported

  • Android
  • iOS

Installation

  1. Clone GeoTunes repository: git clone https://github.com/realBoltDev/GeoTunes.git

  2. Create a local.properties file and add the following contents:

MAPTILER_URI=your-maptiler-uri
MAPTILER_API_KEY=your-maptiler-api-key
GEOTUNES_API_BASE_URL=your-rest-api-server-base-url
GEMINI_API_KEY=your-gemini-api-key
GEMINI_MODEL=gemini-2.5-flash
JWT_SECRET_KEY=your-jwt-secret-key
  1. Steps to get values for each of those:
  • MAPTILER_URI & MAPTILER_API_KEY

    • Create a Maptiler account.
    • Go to Upload Map page and upload this map style.
    • Choose rendering format as WebP and create map.
    • Copy the link to vector style JSON and assign to MAPTILER_URI. Remove the key from URI and assign it to MAPTILER_API_KEY.
  • GEOTUNES_API_BASE_URL

    • Add localhost:3000 since that's where Node.js server will be running locally.
  • GEMINI_API_KEY & GEMINI_MODEL

  • JWT_SECRET_KEY

    • Generate a random alphanumeric key. This will be used as Bearer token to send request from app and authenticate to /shazam-jwt API endpoint.

Setting up ShazamKit

Note: An Apple Account with valid Apple Developer Program subscription is required to use ShazamKit.

  • iOS Device
    • Follow this guide to enable ShazamKit service on your iOS app.
  • Android Device
    1. Download ShazamKit SDK for Android and unzip it.
    2. Move the shazamkit-android-release.aar file to GeoTunes/composeApp/libs directory.
    3. Go to Identifiers tab in In Certificates, Identifiers & Profiles.
    4. Click add button and select Media IDs.
    5. Enter your app Identifier, Description and enable ShazamKit. Click Continue -> Register.
    6. Now go to Keys tab in Certificates, Identifiers & Profiles
    7. Click add button. Add key name and enable Media Services (MusicKit, ShazamKit, Apple Music Feed). Then click configure for it.
    8. Select your Media ID and click Save -> Continue -> Register.
    9. Download the key file and move it to GeoTunes/server directory. Copy the Key ID.
    10. Copy your Team ID from Account visible in Membership details.

Setting up API Server

  • Create a .env file in GeoTunes/server directory and the following contents:
    TEAM_ID="your-team-id"
    KEY_ID="your-key-id"
    PRIVATE_KEY_FILE="your-private-key-file-name"
    JWT_SECRET_KEY="your-jwt-secret-key"
    
    • Add the Team ID and Key ID copied from before
    • Add your downloaded private key file name and the JWT secret key generated from before

Running the App

API Server Android iOS
Go to GeoTunes/server and run npm install, then run node index.js in GeoTunes/server/src Open the project in Intellij Idea and run the composeApp configuration Open iosApp/iosApp.xcodeproj in XCode
API server will start on port 3000 Select an emulator or device and click Run Select a device or simulator and run the app

Usage

Stream Radio Station

To start streaming a station, zoom in and click on a green dot which resembles radio station by interacting in the 2D Map. You can move around or zoom in/out freely. If you want to stream a random radio station, click the roll dice button on the bottom right of the map.

Play/Pause Stream

To play or pause the stream, you can click on the toggle button in the Radio Station section.

Detect Song

In order to detect song, first play a radio station. Then click on Detect button which will ask you permission to access your microphone. This is required because Shazam records audio to detect songs playing around you. When song changes on the radio or you move to a different station, use the Detect button again.

Save Song

After song is detected by Shazam, it will show its title, artist, and artwork along with a Save button. Use it to save the song to your library.

Generating Song Summary

Song summary is automatically generated via Gemini when song is detected.

Viewing/Deleting Saved Songs

Go to Library screen from the Navbar to see your saved songs. Use the delete button on the top right of the cards to delete individual songs.

Chatting with AI

In the Ask AI screen you can chat with AI. You can ask information about your saved songs, get suggestions, etc. Use the delete button on the top right to clear the conversation history and reset context.

Libraries Used

Kotlin Multiplatform App

Library Purpose
Kotlin Multiplatform Shared business logic across Android, iOS, and Desktop
Compose Multiplatform Declarative UI framework for Android, Desktop, and shared UI
Kotlinx Serialization JSON serialization/deserialization for network and data models
Ktor Client Multiplatform HTTP client used for API communication
Koin Dependency Injection for shared and platform-specific code
Kotlinx Coroutines Asynchronous programming and concurrency
Generative AI AI features using Gemini models via a KMP-compatible client
MapLibre Compose Interactive map rendering for geographic features
Navigation Compose Navigation handling in Compose UI
Coil Image loading optimized for Compose Multiplatform
Media3 ExoPlayer Audio streaming and playback on Android
Multiplatform Markdown Renderer Rendering AI responses and content in Markdown
BuildKonfig Compile-time configuration (API keys, environment variables)
spmForKmp Swift Package Manager integration for iOS native libraries

Server (Node.js)

Library Purpose
Express HTTP server and REST API framework
Axios HTTP client for external API requests
better-sqlite3 Embedded SQLite database for fast local storage
jsonwebtoken JWT-based authentication and token handling
rate-limiter-flexible API rate limiting and abuse protection
compression Gzip/Brotli compression for API responses
cors Cross-Origin Resource Sharing (CORS) support
dotenv Environment variable management
Turf.js Geospatial utilities (point-in-polygon checks)

About

A Kotlin Multiplatform mobile app to explore live radio stations on a 2D world map with song detection & AI-powered insights.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published