Using Mapbox Maps SDK for Android - Java
I’m going to study implementing Map-related application. I have searched several map service provider and finally decide to try Mapbox.
Why Mapbox?
There are several map service providers. Google Map is the most popular one, which is the default map application in Android phones. HereMap and TomTom also are famous. If the app only requires showing the map and the point of interest in the map, we can use their Map SDK. However, the Navigation SDK is restricted at this moment. It needs to send an official request to discuss with them in order to access the navigation SDK.
Although Mapbox is young and less famous, it is open to register an account and apply for Token. Key to access Map SDK and Navigation SDK. As long as your usage of the service does not exceed the limited amount, it is free to use. Therefore, I choose Mapbox for self-learning.
First, go to Mapbox website to sign up for an account. Then go to the document page to select which part to study.
I will studied in those 4 aspects
Show the device location on the map (Maps SDK)
Search the location of place by typing the name (Search SDK)
Request routes and draw on the map (Navigation SDK)
Navigation (Navigation SDK)
Only Koltin source code is provided in the document page. I will follow some of the tutorials and examples in the document page and implement the examples in Java. It may help someone who have not studied Koltin yet.
Create Token keys and keep them Securely
Following the instructions in the document page, we need to have 1 public token key(to use the instance of key components in SDK) and a secret token key with Downloads:read scop (to download the SDK from Mapbox server to Android Studio).
Mapbox bills us according to the usage of service of each token key. Therefore, it is important to keep the token key hidden to public
We configure Git to not track the file which stores the keys.
Create or open .gitignore file. Add a file name with relative path in the file: for example, YOUR_APP_MODULE_NAME/src/main/res/values/non-disclosure.xml
Create the xml file with the same name and location that you add in step 1. Then Git will not trace and upload this file.
Add your public token in this xml file <string name="mapbox_access_token">PASTE_YOUR_TOKEN_HERE</string>
Similarly, add the secret token in file gradle.properties and make Git not to trace and upload this file.
MAPBOX_DOWNLOADS_TOKEN=YOUR_SECRET_MAPBOX_ACCESS_TOKEN
Check Dependencies of each SDK
If you want to use Maps SDK, Search SDK and Navigation in the same project, please check the dependencies of each SDK. Make sure the version of dependencies required by each SDK are the same.
Add the corresponding SDK in module build.gradle and settings.gradle by following the official instructions.
Add MapView
First add MapView in the layout xml file(I put it into Fragment layout for example). We can set the default location that the camera looks at when the fragment is created each time with the parameter “mapbox:mapbox_cameraTargetLat” and “mapbox:mapbox_cameraTargetLng”.
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="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=".ShowMapFragment"> <com.mapbox.maps.MapView xmlns:mapbox="http://schemas.android.com/apk/res-auto" android:id="@+id/mapView" mapbox:layout_constraintBottom_toBottomOf="parent" mapbox:layout_constraintEnd_toEndOf="parent" mapbox:layout_constraintStart_toStartOf="parent" mapbox:layout_constraintTop_toTopOf="parent" mapbox:mapbox_cameraTargetLat="40.7128" mapbox:mapbox_cameraTargetLng="-74.0060" mapbox:mapbox_cameraZoom="16.0" android:layout_width="match_parent" android:layout_height="match_parent" /> </androidx.constraintlayout.widget.ConstraintLayout>
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); mapView = binding.mapView; mapView.getMapboxMap().loadStyleUri(Style.MAPBOX_STREETS, new Style.OnStyleLoaded(){ @Override public void onStyleLoaded(Style style){ } }); }
@Override public void onStart(){ super.onStart(); mapView.onStart(); } @Override public void onStop(){ super.onStop(); mapView.onStop(); } @Override public void onLowMemory(){ super.onLowMemory(); mapView.onLowMemory(); } @Override public void onDestroyView() { super.onDestroyView(); mapView.onDestroy(); binding = null; }
Show Device Location
In order to show the device Location, app must grant ACCESS_FINE_LOCATION and ACCESS_COARSE_LOCATION permission.
Mapbox has implemented a Location Provider object to deal with the device location by utilising Android GPS and Network Location Providers and Google fused Location Providers . All we need is to enable the MapView to show the device location after the location permissions granted and device’s GPS turn on.
We look at the example Display the user's location which is programmed in Koltin. This part is to enable the MapView to display the device location.
private fun initLocationComponent() { val locationComponentPlugin = mapView.location locationComponentPlugin.updateSettings { this.enabled = true this.locationPuck = LocationPuck2D( bearingImage = AppCompatResources.getDrawable( this@LocationTrackingActivity, R.drawable.mapbox_user_puck_icon,), …. }
In Java, we need to use one of these 2 methods to get LocationCompoentPlugin Class which controls the location display and the icon representing the device location.
LocationComponentPlugin2 locationComponentPlugin = mapView.getPlugin(Plugin.MAPBOX_LOCATION_COMPONENT_PLUGIN_ID); LocationComponentPlugin2 locationComponentPlugin = LocationComponentUtils.getLocationComponent2(mapView); 7
LocationComponentPlugin2 locationComponentPlugin = mapView.getPlugin(Plugin.MAPBOX_LOCATION_COMPONENT_PLUGIN_ID); locationComponentPlugin.setEnabled(true);
LocationPuck2D puck2D = LocationComponentUtils.createDefault2DPuck(locationComponentPlugin, getContext(), true); locationComponentPlugin.setLocationPuck(puck2D); locationComponentPlugin.setPuckBearingEnabled(true); // enable the puck to rotate to track the device bearing locationComponentPlugin.setPuckBearingSource(PuckBearingSource.HEADING);
Change Camera viewing position at the device location
Now we move the device and so as the blue spot on the screen. If we want the blue spot to always stay at the centre of the screen even if we move around. We can set the camera in the OnIndicatorPositionChangedListener, in which method will be invoked every time the device location changes. We also set the focal point of gesture here so that the camera will rotate and zoom at the device position.
private OnIndicatorPositionChangedListener onIndicatorPositionChangedListener = new OnIndicatorPositionChangedListener(){ @Override public void onIndicatorPositionChanged(Point point){ mapView.getMapboxMap().setCamera(new CameraOptions.Builder().center(point).build()); GesturesPlugin gesturesPlugin = mapView.getPlugin(Plugin.MAPBOX_GESTURES_PLUGIN_ID); gesturesPlugin.setFocalPoint(mapView.getMapboxMap().pixelForCoordinate(point)); } };
If we hope the map automatically rotates as the device so that the bearing direction of the blue spot always points to the top side of the screen. We could use OnIndicatorBearingChangedListener. We set the pointing direction of the camera when the bearing of the device changes.
private final OnIndicatorBearingChangedListener onIndicatorBearingChangedListener = new OnIndicatorBearingChangedListener(){ @Override public void onIndicatorBearingChanged(double bearing){ mapView.getMapboxMap().setCamera(new CameraOptions.Builder().bearing(bearing).build()); } };
If we want to look at other places on the map, we swipe the screen. At this moment, we may not want the camera to automatically recenter at the device location. Therefore, we need to remove the above changed listeners when we move the map.
private final OnMoveListener onMoveListener = new OnMoveListener() { @Override public void onMoveBegin(@NotNull MoveGestureDetector moveGestureDetector) { onCameraTrackingDismissed(); } @Override public boolean onMove(@NotNull MoveGestureDetector moveGestureDetector) { return false; } @Override public void onMoveEnd(@NotNull MoveGestureDetector moveGestureDetector) { } };
OnMoveListener is the interface responsible for gesture events. We add this listener into GesturePlugin and invoke the method onCameraTackingDismissed() to remove the relevant listener when a user gesture is detected.
GesturesPlugin gesturesPlugin = mapView.getPlugin(Plugin.MAPBOX_GESTURES_PLUGIN_ID); gesturesPlugin.addOnMoveListener(onMoveListener);
This is the end of the study on the example Display the user's location. Next time, I will study the Mapbox Search SDK for Geocoding (get the coordinate of a place by providing the name of the place) .
View the source code in GitHub.
留言
發佈留言