What Technologies Are Used in the Google Timeline Visualizer Android App?

The Google Timeline Visualizer Android app is built with Kotlin, Android Jetpack libraries, and AndroidX Media3 for video processing, targeting compileSdk 36 with minSdk 26.

This open-source Android application, hosted at mahlernim/google-timeline-visualizer, ingests Google Takeout JSON exports and transforms location history into interactive timeline visualizations and shareable MP4 videos. Understanding the technology stack behind the Google Timeline Visualizer Android app reveals how modern Android architecture combines declarative UI patterns with powerful media pipelines.

Language and Build System

The Google Timeline Visualizer Android codebase is 100% Kotlin. All source files use the *.kt extension, from UI components to background services.

Build configuration lives in app/build.gradle.kts, which uses the Gradle Kotlin DSL rather than Groovy. Key SDK constraints include:

  • compileSdk: 36
  • minSdk: 26 (Android 8.0+)
  • targetSdk: aligned with compileSdk

The build file enables ViewBinding (buildFeatures.viewBinding = true) for type-safe view access and eliminates findViewById boilerplate.

Core AndroidX and Jetpack Components

UI and Theming

  • AppCompat 1.7.1 (androidx.appcompat:appcompat) — backward-compatible Activity and theming support
  • Material Design Components 1.13.0 (com.google.android.material:material) — Material3 dynamic color and component library

Architecture Components

  • Lifecycle-aware ViewModel 2.10.0 (androidx.lifecycle:lifecycle-viewmodel-ktx) — survives configuration changes, used in MainActivity.kt, SettingsViewModel.kt
  • Activity Result Contracts (androidx.activity) — modern permission and activity result handling, imported in MainActivity.kt as import androidx.activity.result.contract.ActivityResultContracts
  • AppLocale support (androidx.appcompat) — dynamic language switching

The UI layer combines these in files like [TimelineView.kt](https://github.com/mahlernim/google-timeline-visualizer/blob/main/app/src/main/java/dev/mahlernim/timelinevisualizer/ui/TimelineView.kt) and [MainActivity.kt](https://github.com/mahlernim/google-timeline-visualizer/blob/main/app/src/main/java/dev/mahlernim/timelinevisualizer/MainActivity.kt).

Asynchronous Processing with Kotlin Coroutines

All background work—parsing large JSON files, generating video frames, writing MP4 files—runs on Kotlin Coroutines 1.10.2 (kotlinx-coroutines-android).

This appears in ViewModels through viewModelScope.launch(Dispatchers.IO) and in the export pipeline through structured concurrency.

Data Parsing with Gson

Google Takeout exports arrive as dense JSON. The app uses Gson 2.13.2 (com.google.code.gson:gson) for deserialization into Kotlin data classes. The parsing logic resides in [TimelineParser.kt](https://github.com/mahlernim/google-timeline-visualizer/blob/main/app/src/main/java/dev/mahlernim/timelinevisualizer/data/TimelineParser.kt).

Example pattern from the codebase:

class TimelineViewModel : ViewModel() {
    private val _timeline = MutableLiveData<Timeline>()
    val timeline: LiveData<Timeline> = _timeline

    fun load(json: String) {
        viewModelScope.launch(Dispatchers.IO) {
            val parsed = Gson().fromJson(json, Timeline::class.java)
            _timeline.postValue(parsed)
        }
    }
}

Video Pipeline: AndroidX Media3

The Google Timeline Visualizer Android app's signature feature—exporting location timelines as MP4 videos—depends entirely on AndroidX Media3 1.11.0. Three modules handle different responsibilities:

Media3 Module Purpose Implementation Location
media3-exoplayer In-app video preview/playback MainActivity.kt
media3-muxer MP4 file generation Mp4Exporter.kt
media3-ui Player controls and surface Layout XML with PlayerView

ExoPlayer Integration

Playback setup in MainActivity.kt (simplified):

// MainActivity.kt – player initialization
private val player = ExoPlayer.Builder(this).build().apply {
    setMediaItem(MediaItem.fromUri(videoUri))
    prepare()
    playWhenReady = true
}
binding.playerView.player = player

MP4 Export with Muxer

The [Mp4Exporter.kt](https://github.com/mahlernim/google-timeline-visualizer/blob/main/app/src/main/java/dev/mahlernim/timelinevisualizer/export/Mp4Exporter.kt) file contains the video encoding logic:

@OptIn(UnstableApi::class)
fun exportMp4(frames: List<Frame>, output: File) {
    val muxer = Mp4Muxer(
        FileOutputStream(output).channel, 
        Mp4Muxer.OutputMode.MUXER_OUTPUT_MODE_AUTO
    )
    val track = muxer.addVideoTrack(
        MediaFormatUtil.createVideoFormat(MIME_VIDEO_AVC, width, height, 30_000L)
    )
    frames.forEach { frame ->
        muxer.writeSampleData(
            track, 
            frame.buffer, 
            MuxerBufferInfo(frame.timeUs, frame.size, false)
        )
    }
    muxer.close()
}

The [VideoExportService.kt](https://github.com/mahlernim/google-timeline-visualizer/blob/main/app/src/main/java/dev/mahlernim/timelinevisualizer/export/VideoExportService.kt) wraps this in a foreground service with notification support for long-running exports.

Storage, Preferences, and Permissions

Simple Preferences

Rather than a full dependency injection framework, the app uses androidx.core.content.edit extension functions for lightweight SharedPreferences operations, visible across multiple *Preferences.kt files.

Required Permissions

The [AndroidManifest.xml](https://github.com/mahlernim/google-timeline-visualizer/blob/main/app/src/main/AndroidManifest.xml) declares:

  • INTERNET — for map tile loading
  • FOREGROUND_SERVICE and FOREGROUND_SERVICE_MEDIA_PLAYBACK — for video export
  • Notification permissions — for export progress updates

Testing Infrastructure

Unit tests rely on:

  • JUnit 4.13.2 — test runner
  • Robolectric — Android framework simulation without emulator
  • AndroidX Test Core 1.7.0 — ActivityScenario and core test utilities

Summary

  • Language: Kotlin throughout, with Gradle Kotlin DSL build configuration
  • UI Framework: Jetpack ViewBinding, Material3, Lifecycle ViewModel, Activity Result Contracts
  • Concurrency: Kotlin Coroutines for all async operations
  • Serialization: Gson for Google Takeout JSON parsing
  • Media Stack: AndroidX Media3 (ExoPlayer, Muxer, UI components) for playback and MP4 export
  • Architecture: MVVM pattern with ViewModel and LiveData
  • Services: Foreground service with notifications for background video rendering

Frequently Asked Questions

What is the minimum Android version required for Google Timeline Visualizer?

The app requires Android 8.0 (API 26) or higher, as specified by minSdk 26 in app/build.gradle.kts. This covers approximately 95%+ of active Android devices globally.

Why does the app use Media3 instead of older media libraries?

Media3 consolidates ExoPlayer, media session APIs, and media extraction tools into a single maintained library. The Google Timeline Visualizer Android app specifically needs Media3's Mp4Muxer class—unavailable in legacy support libraries—for frame-accurate video generation without external ffmpeg dependencies.

Is the Google Timeline Visualizer Android app written in Java or Kotlin?

The codebase is 100% Kotlin. Every source file in app/src/main/java/ uses the .kt extension, including Activities, ViewModels, Services, and data classes. This aligns with Google's modern Android development recommendations.

How does the app handle large Google Takeout JSON files without freezing the UI?

JSON parsing executes on the IO dispatcher via viewModelScope.launch(Dispatchers.IO), keeping the main thread responsive. The parsed Timeline object posts to LiveData, which the UI observes on the main thread—a standard coroutine pattern for file I/O in Android.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →