SWMAPS DocumentationAPI portal

Offline and mobile

Mobile: PWA and native apps

Integrate the same map data on phones while accounting for platform storage, rendering and permission differences.

On this page

Browser and PWA checklist #

The hosted and React examples work in mobile browsers when their container has a responsive height. Build your PWA application shell, manifest, service worker, download UI and storage lifecycle in your app; the reference viewer does not automatically provide them.

  • Use a viewport meta tag and a map container with a bounded visible height; keep controls clear of phone safe areas.
  • Bundle JS, CSS and application icons during the connected build; cache the shell for offline start.
  • Download and verify packs while connected; use OPFS and the local-resource recipe in the previous guide.
  • Provide visible states: estimating, downloading, verifying, ready, failed and removable. Never label a partial pack available offline.
  • Test GPS permission, screen lock/resume, low storage, process termination, and cold start in airplane mode.
  • Keep online APIs optional in offline UI: local place matching can work, but live service routing cannot.

React Native recipe #

Native integration recipes are documentation-checked, not exercised on Android/iOS devices in this repository. Select and pin compatible SDK versions in your application. Do not import the DOM-dependent @sw-maps/core root into React Native.

Install @maplibre/maplibre-react-native using its native setup instructions and the SW core tarball for services/style/MGRS helpers. The following targets the current v11 component naming; v10 used MapView instead of Map. Native project linking/build setup is still required.

jsx
import { Map } from '@maplibre/maplibre-react-native';
import { configure, search } from '@sw-maps/core/services';
import { toMgrs } from '@sw-maps/core/mgrs';

configure({ baseUrl: 'https://maps.example/', apiKey: 'YOUR_API_KEY' });
const style = 'https://maps.example/maps/styles/dark.json?key=' + encodeURIComponent('YOUR_API_KEY');
export default function FieldMap() {
  return <Map style={{ flex: 1 }} mapStyle={style} />;
}
// In a search action: await search('Lahug');
// In your location callback: toMgrs([longitude, latitude]);

This loads the online style; it does not download a pack. Keep credentials in the application’s configuration/secure storage workflow, remembering that a distributed application key is extractable. For location use a native permission/location provider and feed coordinates to the map and MGRS helpers.

Official setup and API: React Native setup and Map component. External links are optional references; reading this documentation makes no requests to them.

Android recipe #

Prerequisites: a native Android project with MapLibre SDK and INTERNET permission, a maps key, and trusted server TLS. Initialize MapLibre before creating MapView. For an existing Activity-owned MapView named mapView:

kotlin
// Kotlin; imports from org.maplibre.android.*
// Call MapLibre.getInstance(this) before inflating the MapView.
val key = java.net.URLEncoder.encode("YOUR_API_KEY", "UTF-8")
mapView.getMapAsync { map ->
    map.setStyle("https://maps.example/maps/styles/dark.json?key=$key") {
        map.cameraPosition = org.maplibre.android.camera.CameraPosition.Builder()
            .target(org.maplibre.android.geometry.LatLng(14.5995, 120.9842))
            .zoom(12.0).build()
    }
}

Android LatLng uses latitude,longitude; convert deliberately from SW’s longitude-first arrays. Forward Activity lifecycle events to MapView, including create/start/resume/pause/stop/destroy/save-state/low-memory, according to the SDK setup. Request runtime location permission before enabling a device location component.

PMTiles support starts with Android SDK 11.7.0. Native sources need fully specified URLs such as pmtiles://https://... or pmtiles://file://.... Its standard offline pack manager does not download/cache PMTiles sources: use SW’s file manifests and your own downloader. See official Android PMTiles guidance and Activity setup.

iOS recipe #

Prerequisites: an iOS project linking MapLibre, valid HTTPS, a maps key and a view controller. Add location usage descriptions and request permission only if using device location. This minimal UIKit controller illustrates online map loading.

swift
import UIKit
import CoreLocation
import MapLibre

final class FieldMapController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        var url = URLComponents(string: "https://maps.example/maps/styles/dark.json")!
        url.queryItems = [URLQueryItem(name: "key", value: "YOUR_API_KEY")]
        let map = MLNMapView(frame: view.bounds, styleURL: url.url!)
        map.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        map.setCenter(CLLocationCoordinate2D(latitude: 14.5995, longitude: 120.9842),
                      zoomLevel: 12, animated: false)
        view.addSubview(map)
    }
}

iOS PMTiles source support starts with SDK 6.10.0. Check the exact SDK’s file URL/resource handling and supported style properties. See official iOS PMTiles guidance. This controller has not been device-tested against SW Maps.

Native offline resources and acceptance gates #

Download the SW manifest and files into an app-owned pack directory, verify SHA-256, extract fonts, and rewrite __MAP_BASE__ to the local resource root. For JavaScript use resolveStyle; Kotlin/Swift apps implement the same targeted rewriting for source URLs/tile arrays, glyphs and sprites. Use absolute URLs inside pmtiles://. Do not assume pointing an SDK offline manager at a style will download these archives.

  • Confirm the selected renderer can open vector and raster/DEM PMTiles from local storage.
  • Confirm local styles, sprite JSON/PNG/@2x variants and glyph URL templates resolve without the server. Supply an app resource adapter or local HTTP resource service only where needed by that SDK.
  • Test dark/light style expressions and bathymetry rendering on both Android and iOS.
  • Test z15 in, across and outside shore boxes. The web packProtocol setting has no automatic native equivalent; native fallback remains an acceptance gate.
  • Verify cold start in airplane mode, all map zooms, local names, attribution, storage migration/deletion and background/resume behavior.
  • Keep service-dependent features unavailable or explicitly marked while disconnected; do not promise offline routing.

These are application integration tasks, not additional endpoints supplied by SW Maps. The browser’s FileSource, OPFS and Web Serial APIs are not native resource adapters.