Android Example

A Kotlin Android application that renders a MapLibre GL Native vector tile map and adds places search. Uses a custom OkHttp interceptor for tile authentication.

Prerequisites

  • Android Studio Ladybug (2024.2+)
  • Android API 24+ (Android 7.0) device or emulator
  • A Geog API key (create one in the console)

Quick Start

git clone https://github.com/geogdev/examples.git

Open examples/mobile/android-maplibre in Android Studio. Add your API key to local.properties:

GEOG_API_KEY=your-api-key-here

Click Sync Now when prompted for Gradle sync, then run the app.

Project Structure

FileDescription
local.propertiesAPI key storage (git-ignored) — injected via Gradle buildConfigField
app/build.gradle.ktsModule config — reads API key from local.properties into BuildConfig
app/src/main/java/.../api/GeogService.ktAPI client — OkHttp-based authentication and places search
app/src/main/java/.../MapFragment.ktFragment — MapLibre map with programmatic style and OkHttp auth interceptor
app/src/main/java/.../PlacesSearchFragment.ktFragment — search UI, results list, and marker management
app/src/main/java/.../api/Place.kt@Serializable data model for search results

How It Works

Bundle / Application ID Authentication

Mobile apps authenticate using application ID restrictions instead of token exchange. When you create an API token in the console, you can restrict it to specific Android application IDs (e.g., com.yourcompany.yourapp). The app sends its application ID via the X-App-Bundle-Id header, and the Geog API rejects calls whose header doesn't match an allowed identifier.

Application ID restrictions reduce casual abuse — an extracted key won't work from an app with a different application ID — but the header is client-supplied and can be spoofed. For production apps with high-value keys, consider proxying API calls through your own backend so the key is never shipped in the APK.

To configure application ID restrictions:

  1. Go to Tokens in the console
  2. Edit your token's settings
  3. Add your app's application ID under Allowed Bundle IDs

API Key Configuration

The API key is stored in local.properties (git-ignored) and injected into the app at build time through Gradle:

// app/build.gradle.kts
android {
    defaultConfig {
        buildConfigField(
            "String",
            "GEOG_API_KEY",
            "\"${localProperties["GEOG_API_KEY"]}\""
        )
    }
}

Access it in code as BuildConfig.GEOG_API_KEY.

Custom OkHttp Interceptor

MapLibre GL Native for Android uses OkHttp under the hood. A custom interceptor attaches the API key and application ID to all Geog API requests (tiles and places):

val client = OkHttpClient.Builder()
    .addInterceptor { chain ->
        val request = chain.request()
        if (request.url.host == "api.geog.dev") {
            chain.proceed(
                request.newBuilder()
                    .header("Authorization", "Bearer ${BuildConfig.GEOG_API_KEY}")
                    .header("X-App-Bundle-Id", BuildConfig.APPLICATION_ID)
                    .build()
            )
        } else {
            chain.proceed(request)
        }
    }
    .build()

HttpRequestUtil.setOkHttpClient(client)

Coroutines

All API calls are suspend functions and run within lifecycleScope for structured concurrency.

Full Source

github.com/geogdev/examples/tree/main/mobile/android-maplibre

See Also