Examples
Getting started (3)Create a simple map viewDynamically build a map viewSupport map fragmentDynamic styling (30)HillshadingAdd a vector tile sourceAdd a new layer below labelsAnimate marker positionAdjust a layer's opacityShow time lapseAnimated image source (GIF)Icon update based on API responseChange a layer's colorChange a map's languageColor dependent on zoom levelClick to add photoIndoor MapMarker following routeStyle with missing iconSymbol layer iconsPicture in picturePulsing layer opacityAdd a WMS sourceText anchor positionButton interaction stylingOpacity fadeShow and hide layersSymbolLayer iconsAdjust text labelsMultiple text formatsTransparent render surfaceUse an image sourceAnimated icon movementVariable label placementExtrusions (5)Adjust light location and colorDisplay 3D building height based on vector dataExtrude polygons for 3D indoor mappingRotate and tilt with 3D buildingsUse GeoJSON data to set extrusion heightCamera (5)Animate the map cameraFit camera in bounding boxRestrict map panningRotating cameraZoom to show a cluster's leavesData visualization (33)Baseball spray chartDisplay water depthBiometric fingerprintCalendar integrationCircle icon toggleCircleLayer clustersCircle radiusCircle to icon transitionCreate a line layerCreate hotspots from pointsData time lapseShow heatmap dataDraw a GeoJSON lineDraw a polygon with holesDraw a polygonDraw multiple geometriesJoin local JSON data with vector tile geometriesLine gradientLine behind moving iconMultiple expressionsIcon setting based on Feature propertyOutlined polygon holeSatellite land selectShared preferencesSpinning iconStyle circles categoricallyStyle lines using an identity property functionToggle collision detectionSymbolLayer clusteringSymbol layer info windowZoom-based icon switchUpdate a choropleth layer by zoom levelStyling heatmapsOffline (3)Cache managementA simple offline mapOffline managerQuerying the map (3)Building outlineQuery a map featureSelect a buildingMap style (4)Style attributionLocal style or custom raster styleDefault stylesMapbox Studio styleUser interaction (12)Click on single layerFeature countDrawing search areaHighlighted lineSymbol layer icon size changeInset mapLocation pickerBackground fogRecyclerView DirectionsSearch again in an areaSnaking directionsRecyclerView interactionImage generation (2)Snapshot NotificationShare snapshot imageDevice location (7)Track device locationBasic pulsing locationLocation camera optionsCustom pulsing locationCustomized location iconShow a user's location on a map fragmentShow a user's location

A simple offline map

activity_offline_simple
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:mapbox="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".examples.offline.SimpleOfflineMapActivity">
<com.mapbox.mapboxsdk.maps.MapView
android:id="@+id/mapView"
android:layout_width="match_parent"
android:layout_height="match_parent"
mapbox:mapbox_cameraTargetLat="37.73359"
mapbox:mapbox_cameraTargetLng="-119.58410"
mapbox:mapbox_cameraZoom="10"
mapbox:mapbox_cameraZoomMin="10"/>
<ProgressBar
android:id="@+id/progress_bar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="25dp"
android:paddingLeft="25dp"
android:layout_gravity="center"
android:paddingRight="25dp"
android:visibility="gone"/>
</FrameLayout>
SimpleOfflineMapActivity.java
package com.mapbox.mapboxandroiddemo.examples.offline;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import android.view.View;
import android.widget.ProgressBar;
import android.widget.Toast;
import com.mapbox.mapboxandroiddemo.R;
import com.mapbox.mapboxsdk.Mapbox;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.geometry.LatLngBounds;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
import com.mapbox.mapboxsdk.maps.Style;
import com.mapbox.mapboxsdk.offline.OfflineManager;
import com.mapbox.mapboxsdk.offline.OfflineRegion;
import com.mapbox.mapboxsdk.offline.OfflineRegionError;
import com.mapbox.mapboxsdk.offline.OfflineRegionStatus;
import com.mapbox.mapboxsdk.offline.OfflineTilePyramidRegionDefinition;
import org.json.JSONObject;
import timber.log.Timber;
/**
* Download and view an offline map using the Mapbox Android SDK.
*/
public class SimpleOfflineMapActivity extends AppCompatActivity {
private boolean isEndNotified;
private ProgressBar progressBar;
private MapView mapView;
private OfflineManager offlineManager;
// JSON encoding/decoding
public static final String JSON_CHARSET = "UTF-8";
public static final String JSON_FIELD_REGION_NAME = "FIELD_REGION_NAME";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Mapbox access token is configured here. This needs to be called either in your application
// object or in the same activity which contains the mapview.
Mapbox.getInstance(this, getString(R.string.access_token));
// This contains the MapView in XML and needs to be called after the access token is configured.
setContentView(R.layout.activity_offline_simple);
mapView = findViewById(R.id.mapView);
mapView.onCreate(savedInstanceState);
mapView.getMapAsync(new OnMapReadyCallback() {
@Override
public void onMapReady(@NonNull final MapboxMap mapboxMap) {
mapboxMap.setStyle(Style.OUTDOORS, new Style.OnStyleLoaded() {
@Override
public void onStyleLoaded(@NonNull Style style) {
// Set up the OfflineManager
offlineManager = OfflineManager.getInstance(SimpleOfflineMapActivity.this);
// Create a bounding box for the offline region
LatLngBounds latLngBounds = new LatLngBounds.Builder()
.include(new LatLng(37.7897, -119.5073)) // Northeast
.include(new LatLng(37.6744, -119.6815)) // Southwest
.build();
// Define the offline region
OfflineTilePyramidRegionDefinition definition = new OfflineTilePyramidRegionDefinition(
style.getUri(),
latLngBounds,
10,
20,
SimpleOfflineMapActivity.this.getResources().getDisplayMetrics().density);
// Set the metadata
byte[] metadata;
try {
JSONObject jsonObject = new JSONObject();
jsonObject.put(JSON_FIELD_REGION_NAME, "Yosemite National Park");
String json = jsonObject.toString();
metadata = json.getBytes(JSON_CHARSET);
} catch (Exception exception) {
Timber.e("Failed to encode metadata: %s", exception.getMessage());
metadata = null;
}
// Create the region asynchronously
if (metadata != null) {
offlineManager.createOfflineRegion(
definition,
metadata,
new OfflineManager.CreateOfflineRegionCallback() {
@Override
public void onCreate(OfflineRegion offlineRegion) {
offlineRegion.setDownloadState(OfflineRegion.STATE_ACTIVE);
// Display the download progress bar
progressBar = findViewById(R.id.progress_bar);
startProgress();
// Monitor the download progress using setObserver
offlineRegion.setObserver(new OfflineRegion.OfflineRegionObserver() {
@Override
public void onStatusChanged(OfflineRegionStatus status) {
// Calculate the download percentage and update the progress bar
double percentage = status.getRequiredResourceCount() >= 0
? (100.0 * status.getCompletedResourceCount() / status.getRequiredResourceCount()) :
0.0;
if (status.isComplete()) {
// Download complete
endProgress(getString(R.string.simple_offline_end_progress_success));
} else if (status.isRequiredResourceCountPrecise()) {
// Switch to determinate state
setPercentage((int) Math.round(percentage));
}
}
@Override
public void onError(OfflineRegionError error) {
// If an error occurs, print to logcat
Timber.e("onError reason: %s", error.getReason());
Timber.e("onError message: %s", error.getMessage());
}
@Override
public void mapboxTileCountLimitExceeded(long limit) {
// Notify if offline region exceeds maximum tile count
Timber.e("Mapbox tile count limit exceeded: %s", limit);
}
});
}
@Override
public void onError(String error) {
Timber.e("Error: %s", error);
}
});
}
}
});
}
});
}
@Override
public void onResume() {
super.onResume();
mapView.onResume();
}
@Override
protected void onStart() {
super.onStart();
mapView.onStart();
}
@Override
protected void onStop() {
super.onStop();
mapView.onStop();
}
@Override
public void onPause() {
super.onPause();
mapView.onPause();
if (offlineManager != null) {
offlineManager.listOfflineRegions(new OfflineManager.ListOfflineRegionsCallback() {
@Override
public void onList(OfflineRegion[] offlineRegions) {
if (offlineRegions.length > 0) {
// delete the last item in the offlineRegions list which will be yosemite offline map
offlineRegions[(offlineRegions.length - 1)].delete(new OfflineRegion.OfflineRegionDeleteCallback() {
@Override
public void onDelete() {
Toast.makeText(
SimpleOfflineMapActivity.this,
getString(R.string.basic_offline_deleted_toast),
Toast.LENGTH_LONG
).show();
}
@Override
public void onError(String error) {
Timber.e("On delete error: %s", error);
}
});
}
}
@Override
public void onError(String error) {
Timber.e("onListError: %s", error);
}
});
}
}
@Override
public void onLowMemory() {
super.onLowMemory();
mapView.onLowMemory();
}
@Override
protected void onDestroy() {
super.onDestroy();
mapView.onDestroy();
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
mapView.onSaveInstanceState(outState);
}
// Progress bar methods
private void startProgress() {
// Start and show the progress bar
isEndNotified = false;
progressBar.setIndeterminate(true);
progressBar.setVisibility(View.VISIBLE);
}
private void setPercentage(final int percentage) {
progressBar.setIndeterminate(false);
progressBar.setProgress(percentage);
}
private void endProgress(final String message) {
// Don't notify more than once
if (isEndNotified) {
return;
}
// Stop and hide the progress bar
isEndNotified = true;
progressBar.setIndeterminate(false);
progressBar.setVisibility(View.GONE);
// Show a toast
Toast.makeText(SimpleOfflineMapActivity.this, message, Toast.LENGTH_LONG).show();
}
}
Was this page helpful?