# Download Regional Data

Use this section to start regional downloads after binding the download screen lifecycle and choosing the download network policy where each download can include both road-network data and map-tile data for the selected region.

## Bind the Download Screen Lifecycle

Call _beginDownloadPage()_ and _endDownloadPage(owner)_ on the main thread, and pass the same owner to both calls. A “Fragment” should use _viewLifecycleOwner_ and clean up in _onDestroyView()_. An “Activity” can pair the calls in _onCreate()_ and _onDestroy()_.

```kotlin
private var progressSubscription:
    NBNavigation.OfflineProgressSubscription? = null

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    NBNavigation.beginDownloadPage(viewLifecycleOwner, savedInstanceState)
    progressSubscription = NBNavigation.observeOfflineProgress {
        renderDownloadProgress(it)
    }
}

override fun onDestroyView() {
    progressSubscription?.cancel()
    progressSubscription = null
    NBNavigation.endDownloadPage(viewLifecycleOwner)
    super.onDestroyView()
}
```

## Set the Download Network Policy

The default policy is `WIFI_ONLY`. Set the policy before starting or resuming a download.

```kotlin
NBNavigation.setDownloadNetworkPolicy(
    OfflineDownloadNetworkPolicy.WIFI_ONLY
)
```

| Policy | Behavior |
| --- | --- |
| `WIFI_ONLY` | Wi-Fi only. It is the default |
| `UNMETERED` | Allows Wi-Fi, Ethernet, and other unmetered networks |
| `ANY` | Allows mobile data. It is recommended to display the download size and obtain user confirmation first. |

## Start a Download

```kotlin

NBNavigation.downloadRegion(
    regionId,
    object : NBNavigationTaskCallback<OfflineRegionDownloadData> {
        override fun onSuccess(result: OfflineRegionDownloadData?) {
            if (result == null) return
            Log.i("OfflineNavigation", "route=${result.routeRegion.downloadStatus}, " +
                "map=${result.mapTileRegion.action}")
        }
        override fun onError(throwable: Throwable) {
            Log.e("OfflineNavigation", "downloadRegion failed", throwable)
        }
    }
)
```

The SDK submits the map task first and then performs the road-network download. A successful callback means that request orchestration completed. It does not mean that the map download finished. If the road-network operation fails, the map task may still be active. Use _observeOfflineProgress()_ as the source of truth for final state.

| Result field | Meaning | Application use |
| --- | --- | --- |
| `regionId` | Requested catalog region | Associate the response with the UI row |
| `routeRegion.downloadStatus` | _IDLE_, _DOWNLOADING_, _COMPLETE_, _PARTIAL_, _FAILED_, _PAUSED_, or _UNKNOWN_ | Use the enum for the immediate route-side state |
| `routeRegion.tilesDone` / `tilesTotal` | Route tiles available after this run | Show route-side completion when the total is valid |
| `routeRegion.downloadSuccessCount` / `downloadFailedCount` | Tile requests that succeeded or failed during this run | Diagnostics only. Use observed progress for the final UI state |
| `routeRegion.skipped` / `interrupted` / `interruptReason` | Whether duplicate work was skipped or this native run stopped early | Refresh progress before deciding whether to resume or retry |
| `routeRegion.autoRetryAttempts` / `completedAfterAutoRetry` | SDK-managed retry summary | Useful for diagnostics. Do not schedule an unbounded second retry loop |
| `routeRegion.errorCode` | Native route error; 0 means none reported | Record for diagnostics. Do not parse message text |
| `mapTileRegion.action` | _ENQUEUED_, _RESUMED_, _ALREADY_COMPLETED_, or _ALREADY_IN_PROGRESS_ | Use this enum for application logic |
| `mapTileRegion.message` | Human-readable diagnostic text | Display or log only. Not a stable status code |

Submitting the same regionId again does not create a duplicate active map task. Use _resumeRegion()_ for paused, failed, or partially completed work. Always refresh observed progress after either a success or an error callback.
