Source on GitHub
baato/navigation-sdkWorked example
A complete navigation screen, end to end.
Features
Turn-by-turn navigation
Voice instructions
Automatic re-routing
Custom map styles
Installation
1
Add the JitPack repository
In your project’s
build.gradle:allprojects{
repositories {
maven { url 'https://jitpack.io' }
}
}
2
Add the dependencies
dependencies {
implementation 'com.github.baato.navigation-sdk:baato-navigation-android:${latest-version}'
implementation 'com.github.baato.navigation-sdk:baato-navigation-android-ui:${latest-version}'
}
Replace
${latest-version} with the current release tag from the
releases page.3
Configure the app module
defaultConfig {
multiDexEnabled true
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
dependencies {
// location service by google, use latest stable version
implementation 'androidx.localbroadcastmanager:localbroadcastmanager:1.0.0'
implementation 'com.google.android.gms:play-services-location:17.0.0'
}
If you use Mapbox as your map service, the SDK currently supports only these versions:
//mapbox sdk
implementation('com.mapbox.mapboxsdk:mapbox-android-sdk:6.5.0') {
exclude group: 'group_name', module: 'module_name'
}
implementation 'com.mapbox.mapboxsdk:mapbox-android-plugin-locationlayer:0.8.1'
4
Declare the permissions
// For Notification
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
// For Location
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
// Since app uses baato-services add network services
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
// for targetSDKVersion 30 and above
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
READ_PHONE_STATE is required only when your targetSdkVersion is 30 or above.Managing location permission and updates
Navigation needs a live location fix, which means requesting the runtime permission and driving a location engine.1
Implement PermissionsListener
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
@NonNull int[] grantResults) {
permissionsManager.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
@Override
public void onExplanationNeeded(List<String> permissionsToExplain) {
//do something so the user see the required permission
}
@Override
public void onPermissionResult(boolean granted) {
if (!granted) {
//do something
}
}
2
Check the location permission
permissionsManager = new PermissionsManager(context);
if (!PermissionsManager.areLocationPermissionsGranted(context)) {
permissionsManager.requestLocationPermissions(context);
} else {
// get location and set map component accordingly
getMyLocation();
}
3
Initialise the location service
If you use multiple map instances, add the following code only to the base map
activity. Once the location is calibrated,
LocationEngineListener receives updates.// Initialize once when permissions are granted
@Override
public void onPermissionResult(boolean granted) {
if (granted)
getMyLocation();
}
//on google api client connected
@Override
public void onConnected(@Nullable Bundle bundle) {
getMyLocation();
}
private void getMyLocation() {
if (googleApiClient != null) {
if (googleApiClient.isConnected()) {
int permissionLocation = 0;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
permissionLocation = checkSelfPermission(
Manifest.permission.ACCESS_FINE_LOCATION);
}
if (permissionLocation == PackageManager.PERMISSION_GRANTED) {
//get GPS Location
mylocation = LocationServices.FusedLocationApi.getLastLocation(googleApiClient);
if (mylocation != null) {
// update gps
locationLayer.forceLocationUpdate(mylocation);
}
// Initilaizing google location engine
LocationRequest locationRequest = new LocationRequest();
locationRequest.setInterval(3000);
locationRequest.setFastestInterval(3000);
locationRequest.setPriority(LocationRequest.PRIORITY_LOW_POWER);
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
.addLocationRequest(locationRequest);
builder.setAlwaysShow(true);
LocationServices.FusedLocationApi
.requestLocationUpdates(googleApiClient, locationRequest, (LocationListener) this);
PendingResult result =
LocationServices.SettingsApi
.checkLocationSettings(googleApiClient, builder.build());
result.setResultCallback(result1 -> {
final Status status = result1.getStatus();
switch (status.getStatusCode()) {
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
// Location settings are not satisfied.
// But could be fixed by showing the user a dialog.
try {
// Show the dialog by calling startResolutionForResult(),
status.startResolutionForResult(this,
Constants.GPS_REQUEST);
} catch (IntentSender.SendIntentException e) {
// Ignore the error.
}
break;
case LocationSettingsStatusCodes.SUCCESS:
// All location settings are satisfied.
// You can initialize location requests here.
int permissionLocation1 = 0;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
permissionLocation1 = checkSelfPermission(
Manifest.permission.ACCESS_FINE_LOCATION);
}
if (permissionLocation1 == PackageManager.PERMISSION_GRANTED) {
mylocation = LocationServices.FusedLocationApi
.getLastLocation(googleApiClient);
originPoint = Point.fromLngLat(mylocation.getLongitude(),
mylocation.getLatitude());
locationLayer.forceLocationUpdate(mylocation);
// locationEngine.activate();
}
break;
case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
// Location settings are not satisfied. However, we have no way to fix the
// settings so we won't show the dialog.
//finish();
break;
}
});
}
} else googleApiClient.connect();
} else setUpGClient();
}
//setup google api client
private synchronized void setUpGClient() {
googleApiClient = new GoogleApiClient.Builder(this)
.enableAutoManage(this, 0, this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
googleApiClient.connect();
}
4
Listen for location updates
//Initialize the location engine
LocationEngineProvider locationEngineProvider = new LocationEngineProvider(context);
locationEngine = locationEngineProvider.obtainBestLocationEngineAvailable();
//Set locationEnginePriority
locationEngine.setPriority(LocationEnginePriority.LOW_POWER);
//Add listner
locationEngine.addLocationEngineListener(context);
//Location update interval
locationEngine.setFastestInterval(ONE_SECOND_INTERVAL);
//activate
locationEngine.activate();
5
Deactivate the engine on destroy
if (locationEngine != null) {
locationEngine.removeLocationEngineListener(context);
}
Requesting a route
Fetch a route withBaatoNavigationRoute, following the
Java client for the request itself. Once you have a route, the
Navigation UI SDK takes over.
Launching turn-by-turn navigation
Launching navigation requires
READ_PHONE_STATE when your targetSdkVersion is 30 or
above. Declare it in the manifest and request it at runtime.<uses-permission android:name="android.permission.READ_PHONE_STATE" />
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
int res = checkSelfPermission(android.Manifest.permission.READ_PHONE_STATE);
if (res != PackageManager.PERMISSION_GRANTED) {
requestPermissions(
new String[]{android.Manifest.permission.READ_PHONE_STATE},
Constants.PHONE_STATE_PERMISSION_REQUEST);
} else {
callTurnByTurnNavigationActivity();
}
}
// Route fetched from BaatoNavigationRoute
DirectionsRoute currentRoute = ...;
boolean simulateRoute = false; // true replays the route without moving
NavigationLauncherOptions options = NavigationLauncherOptions.builder()
.directionsRoute(currentRoute)
.shouldSimulateRoute(simulateRoute)
.build();
NavigationLauncher.startNavigation(YourActivity.this, options);
Setting
shouldSimulateRoute(true) replays the route at your desk — the quickest way to
test navigation without walking it. For a fuller mocking setup, see
testing without moving.Next
Complete turn-by-turn example
A full navigation screen: tap a destination, draw the route, hand off to the navigation UI.