---
title: "Getting Started with Offline Pack API - Kotlin SDK | Mobile sdk | Mobile sdk android | Android"
description: "Offline Pack API that allows you to download map regions for use without an active internet connection."
---

> For AI agents: a documentation index is available at [/llms.txt](https://docs.maptiler.com/llms.txt). Markdown versions of all pages are available by appending .md to any URL.

# Getting Started with Offline Pack API - Kotlin SDK

The MapTiler SDK for Kotlin provides a powerful **Offline Pack API** that enables downloading map regions for offline usage. This is a critical feature for navigation, hiking apps, or any scenario where internet access is unreliable.

Before you begin, ensure you have followed the [Android SDK Getting Started guide](https://docs.maptiler.com/mobile-sdk/android/) to configure your project and set your API key.

## Installation

Add the MapTiler SDK dependency to your `build.gradle.kts` file:

```kotlin
dependencies {
    implementation("com.maptiler.sdk:maptiler-sdk-kotlin:2.0.0")
}
```

[View Installation Instructions](https://docs.maptiler.com/mobile-sdk/android/#-installation)

## Basic usage

Implementing offline maps involves defining a region, creating an offline pack via the manager, and tracking the download progress.

### Step 1: define the region

Specify the geometry (area), zoom range, and the MapTiler style you want to make available offline.

```kotlin
import com.maptiler.maptilersdk.offline.*
import com.maptiler.maptilersdk.map.style.MTMapReferenceStyle

// Define a bounding box (e.g., Zurich)
val bbox = MTBoundingBox(
    minLon = 8.52, minLat = 47.36,
    maxLon = 8.56, maxLat = 47.39
)

// Create the definition
val definition = MTOfflineRegionDefinition(
    geometry = MTOfflineRegionGeometry.BoundingBox(bbox),
    minZoom = 1,
    maxZoom = 12,
    referenceStyle = MTMapReferenceStyle.STREETS
)
```

### Step 2: create the offline pack

Use the `MTOfflineManager` to initialize a new pack on the device.

```kotlin
/ In a coroutine scope
val pack = MTOfflineManager.createPack(context, definition)
```

### Step 3: observe download progress

Set up observers in a coroutine scope.

```kotlin
launch {
  pack.progressFlow.collect { progress ->
    val percent = (progress.percentage * 100).toInt()
    println("Progress: $percent% (${progress.downloadedResources}/${progress.totalResources} resources)")
              
    // You can also access:
    // progress.downloadSpeed (resources/sec)
    // progress.estimatedTimeRemaining (seconds)
  }
}

// Observe state changes (DOWNLOADING, COMPLETED, FAILED, etc.)
launch {
  pack.stateFlow.collect { state ->
    when (state) {
      MTOfflinePackState.DOWNLOADING -> println("Download started...")
      MTOfflinePackState.COMPLETED -> println("Download finished successfully!")
      MTOfflinePackState.FAILED -> println("Download failed.")
      else -> println("Current state: ${state.name}")
    }
  }
}
```

### Step 4: start the download

Trigger the download process. Using `useBackground = true` will offload the work to Android’s _WorkManager_.

```kotlin
pack.download(useBackground = true)
```

## Features

### Flexible Geometries

Offline regions aren’t limited to rectangles. You can define regions based on:

-   **Bounding Box**: A simple rectangular area.
-   **Route**: Download tiles along a GeoJSON route with a specific buffer.
-   **Polygon**: Download tiles within a custom polygon boundary.

### Background Downloading

With `useBackground = true`, the SDK uses _WorkManager_ to handle downloads. It automatically manages battery optimization, network changes, and device reboots.

### Pack Management

Easily manage your stored maps:

-   **List Packs**: `await MTOfflinePack.packs()`
-   **Resume/Pause**: `await pack.resume()` or `await pack.pause()`
-   **Remove**: `await pack.remove()`

## Permissons

The MapTiler SDK serves offline tiles via an internal server. To access these tiles, Android requires you to explicitly permit cleartext traffic to 127.0.0.1 and localhost. We recommend creating a dedicated Network Security Configuration to scope this permission securely.

Create `res/xml/network_security_config.xml`:

```xml
<?xml version="1.0" encoding="utf-8"?>
  <network-security-config>
     <domain-config cleartextTrafficPermitted="true">
         <domain includeSubdomains="false">127.0.0.1</domain>
         <domain includeSubdomains="false">localhost</domain>
     </domain-config>
 </network-security-config>
```

Reference it in your `AndroidManifest.xml`:

```xml
<application
    android:networkSecurityConfig="@xml/network_security_config"
    ... >
</application>
```

## What to Expect

**Storage**: Map tiles are stored in a dedicated folder. A typical city-sized area at zoom level 12 might take 50-100MB depending on the style complexity.

**Expiration**: Packs have an expiration date (default is 30 days). You can use `pack.refresh()` to update the resources and reset the timer.

**Network**: The SDK automatically handles intermittent connectivity, pausing and resuming downloads as the network becomes available.

## Learn more

To learn about more advanced functionalities of the SDK, refer to the [API Reference](https://docs.maptiler.com/mobile-sdk/android/api/).

Check out our [SDK Kotlin Examples](https://docs.maptiler.com/mobile-sdk/android/examples/). In addition to the documentation examples take a look at the plug and play examples provided in the SDK GitHub repository, as well as pre-made demo app: [maptiler-sdk-kotlin/Examples](https://github.com/maptiler/maptiler-sdk-kotlin/tree/main/Examples)
