Mapbox tutorial for android: Map, Geolocation, Markers

Initial stuff

Before we begin:

  1. Sign up for an account at mapbox.com/signup. Find your access token on your account page.
  2. Create a new Android Studio project.

Add Gradle dependencies

repositories {
    mavenCentral()
}
implementation 'com.mapbox.mapboxsdk:mapbox-sdk-services:4.3.0'
implementation 'com.mapbox.mapboxsdk:mapbox-android-sdk:6.8.1'
implementation 'com.mapbox.mapboxsdk:mapbox-android-plugin-places-v7:0.7.0'
implementation ('com.mapbox.mapboxsdk:mapbox-android-geocoder:1.0.0@aar'){
    transitive=true
}
implementation 'com.mapbox.mapboxsdk:mapbox-android-plugin-annotation-v7:0.4.0'
implementation 'com.mapbox.mapboxsdk:mapbox-android-plugin-markerview-v7:0.2.0'

AndroidManifest.xml

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

Initialise Mapbox for your project. Add your access token to res/strings.xml

<string name="mapbox_access_token">MAPBOX_ACCESS_TOKEN</string>

Create an application class to initialize Mapbox for our project. This can be done in your activity class too, but it is better to do it this way if you’re using mapbox in more than one view

public class MyApplication extends Application {
    private static Context context;
    public void onCreate() {
        super.onCreate();
        MyApplication.context = getApplicationContext();
        Mapbox.getInstance(this, getString(R.string.mapbox_access_token));
    }
}

in the application tag of your manifest, make sure to add

android:name="your.package.name.MyApplication"

Adding the map

in your activity layout

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:mapbox="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.mapbox.mapboxsdk.maps.MapView
        android:id="@+id/mapView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        mapbox:mapbox_cameraTargetLat="25.2854"
        mapbox:mapbox_cameraTargetLng="51.5310"
        mapbox:mapbox_cameraZoom="14"/>

</android.support.design.widget.CoordinatorLayout>

In your activity/fragment class’ onCreate()

private MapView mapView;
private MapboxMap mbMap;
mapView = findViewById(R.id.mapView);
mapView.onCreate(savedInstanceState);

mapView.getMapAsync(new com.mapbox.mapboxsdk.maps.OnMapReadyCallback() {
    @Override
    public void onMapReady(@NonNull final MapboxMap mapboxMap) {
        mbMap = mapboxMap;
        mapboxMap.setStyle(Style.MAPBOX_STREETS, new Style.OnStyleLoaded() {
            @Override
            public void onStyleLoaded(@NonNull Style style) {
               //create this function & code further stuff there
               initMapStuff(style);
            }
        });
    }
});

Add lifecycle methods

@Override
@SuppressWarnings( {"MissingPermission"})
public void onStart() {
    super.onStart();
    mapView.onStart();
}

@Override
public void onPause() {
    super.onPause();
    mapView.onPause();
}

@Override
public void onStop() {
    super.onStop();
    mapView.onStop();
}

@Override
public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    mapView.onSaveInstanceState(outState);
}

@Override
public void onDestroy() {
    super.onDestroy();
    mapView.onDestroy();
}

@Override
public void onLowMemory() {
    super.onLowMemory();
    mapView.onLowMemory();
}

In case you’re using a fragment, make sure to override onDestroyView()

@Override
public void onDestroyView() {
    super.onDestroyView();
    mapView.onDestroy();
}

Enabling user location

if you want to show the blue user location icon, add this function in onStyleLoaded

 enableLocationComponent(style);

handle permission, and activate the location component.

@SuppressWarnings( {"MissingPermission"})
private void enableLocationComponent(@NonNull Style loadedMapStyle) {
    if (PermissionsManager.areLocationPermissionsGranted(activity)) {
        LocationComponent locationComponent = mbMap.getLocationComponent();
        locationComponent.activateLocationComponent(activity, loadedMapStyle);
        locationComponent.setLocationComponentEnabled(true);
        locationComponent.setCameraMode(CameraMode.TRACKING);
        locationComponent.setRenderMode(RenderMode.COMPASS);
    } else {
        permissionsManager = new PermissionsManager(new PermissionsListener() {
            @Override
            public void onExplanationNeeded(List<String> permissionsToExplain) {
                Toast.makeText(activity, "location not enabled", Toast.LENGTH_LONG).show();
            }

            @Override
            public void onPermissionResult(boolean granted) {
                if (granted) {
                    mbMap.getStyle(new Style.OnStyleLoaded() {
                        @Override
                        public void onStyleLoaded(@NonNull Style style) {
                            initMapStuff(style);
                        }
                    });
                } else {
                    Toast.makeText(activity, "Location services not allowed", Toast.LENGTH_LONG).show();
                }
            }
        });
        permissionsManager.requestLocationPermissions(activity);
    }
}

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    permissionsManager.onRequestPermissionsResult(requestCode, permissions, grantResults);
}

Adding a geolocate button

Add a button in your layout that will zoom the map to the current location upon click

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:mapbox="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.mapbox.mapboxsdk.maps.MapView
        android:id="@+id/mapView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        mapbox:mapbox_cameraTargetLat="25.2854"
        mapbox:mapbox_cameraTargetLng="51.5310"
        mapbox:mapbox_cameraZoom="14"/>

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/myLocationButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="top|right"
        android:layout_marginTop="8dp"
        android:layout_marginRight="8dp"
        android:src="@android:drawable/ic_menu_mylocation"
        app:borderWidth="0dp"
        app:elevation="6dp"
        app:pressedTranslationZ="12dp"
        app:fabSize="mini" />

</android.support.design.widget.CoordinatorLayout>

add the code inside onStyleLoaded, or if you have implemented the initMapStuff(style) function

FloatingActionButton FAB = (FloatingActionButton) view.findViewById(R.id.myLocationButton);
FAB.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        if(mbMap.getLocationComponent().getLastKnownLocation() != null) { // Check to ensure coordinates aren't null, probably a better way of doing this...
            mbMap.animateCamera(com.mapbox.mapboxsdk.camera.CameraUpdateFactory.newLatLngZoom(new LatLng(mbMap.getLocationComponent().getLastKnownLocation().getLatitude(),mbMap.getLocationComponent().getLastKnownLocation().getLongitude()), 14));
        }
    }
});

Adding markers

Markers are added via symbol layer.

private SymbolManager symbolManager;
private List<Symbol> symbols = new ArrayList<>();

Initialise and configure the symbolManager inside onStyleLoaded()

symbolManager = new SymbolManager(mapView, mbMap, style);
symbolManager.setIconAllowOverlap(true);  //your choice t/f
symbolManager.setTextAllowOverlap(false);  //your choice t/f
symbolManager.addClickListener(new OnSymbolClickListener() {
    @Override
    public void onAnnotationClick(Symbol symbol) {
        Toast.makeText(activity,"clicked  " + symbol.getTextField().toLowerCase().toString(),Toast.LENGTH_SHORT).show();
    }
});

Custom Marker Image configuration

Choose the image that you want to use as the marker icon, and add it to our Mapbox map style. Write inside onMapLoaded()

Bitmap bm = BitmapFactory.decodeResource(getResources(), R.drawable.myimage);
mbMap.getStyle().addImage("my-marker",bm);

Creating one marker

symbolManager.create(new SymbolOptions()
        .withLatLng(new LatLng(s.getStopLat(),s.getStopLon()))
        .withIconImage("my-marker")
        //set the below attributes according to your requirements
        .withIconSize(1.5f)
        .withIconOffset(new Float[] {0f,-1.5f})
        .withZIndex(10)
        .withTextField(s.getStopName())
        .withTextHaloColor("rgba(255, 255, 255, 100)")
        .withTextHaloWidth(5.0f)
        .withTextAnchor("top")
        .withTextOffset(new Float[] {0f, 1.5f})
        .setDraggable(false)
);

Creating multiple markers

List<SymbolOptions> options = new ArrayList<>();
for (int i = 0; i < 5; i++ {
    options.add(new SymbolOptions()
        .withLatLng(getRandomLatLng())
        .withIconImage("bus-marker")
        //set the below attributes according to your requirements
        .withIconSize(1.5f)
        .withIconOffset(new Float[] {0f,-1.5f})
        .withZIndex(10)
        .withTextField("test marker")
        .withTextHaloColor("rgba(255, 255, 255, 100)")
        .withTextHaloWidth(5.0f)
        .withTextAnchor("top")
        .withTextOffset(new Float[] {0f, 1.5f})
        .setDraggable(false)
    );
}

Finally, add the created markers to the map.

symbols = symbolManager.create(options);

to remove markers

symbolManager.delete(symbols);

Don’t forget to add this in your onDestroy() overridden method

symbolManager.onDestroy();

Adding markers: Method 2 (deprecated)

Although it’s deprecated, this way is relatively simpler so you can use this if you have to show a few markers easily.

For adding a single marker

mbMap.addMarker(markerOptions.add(new MarkerOptions().position(new LatLng(25.2854,51.5310)).setTitle("My Marker")));

For multiple markers

List<MarkerOptions> markerOptions = new ArrayList<>();
//add your data
markerOptions.add(new MarkerOptions().position(new LatLng(25.2854,51.5310)).setTitle("marker1"));
markerOptions.add(new MarkerOptions().position(new LatLng(25.2854,51.5310)).setTitle("marker1"));
markerOptions.add(new MarkerOptions().position(new LatLng(25.2854,51.5310)).setTitle("marker1"));
markerOptions.add(new MarkerOptions().position(new LatLng(25.2854,51.5310)).setTitle("marker1"));

mbMap.addMarkers(markerOptions);

to remove markers

mbMap.clear();

Custom Marker Icon

com.mapbox.mapboxsdk.annotations.Icon myicon;
IconFactory iconFactory = IconFactory.getInstance(activitycontext);
myicon = iconFactory.fromResource(R.drawable.myiconimage);

or you can customize the icon, for example, resize it

com.mapbox.mapboxsdk.annotations.Icon icon = iconFactory.fromResource(R.drawable.myiconimage);
myicon = IconFactory.recreate(icon.getId(), Bitmap.createScaledBitmap(icon.getBitmap(), 35, 35, false));

add it to MarkerOptions

.icon(myicon);

That’s all for now. More to come soon!

 


Also published on Medium.

By |2019-04-03T03:57:36+00:00March 14th, 2019|Categories: Android Tutorials|3 Comments

3 Comments

  1. Iman May 18, 2019 at 6:25 pm - Reply

    Salam Alakoom

    i can,t finf fountion initMapStuff for mapbox on your website
    I need your help

    • Zeba Rahman November 5, 2019 at 3:43 pm - Reply

      walaikumassalam.

      You can just delete that line. It is just to show you where you write further customization and code after the map is all set up.

  2. vinoth kumar November 6, 2019 at 5:58 pm - Reply

    how to draw poly line??

Leave A Comment