Implementing the compass functionality with HERE SDK Navigate edition
Last week, we showed you how to render real-time realistic views during navigation using HERE SDK Navigate Edition. This week, we have another exciting tutorial for you: how to listen to the device hardware motion sensors like gyroscope or magnetometer to update the azimuth value on the device motion and orientation in HERE SDK. This will allow you to implement custom compass functionality with HERE SDK for Android (Navigate edition), and enhance your app's navigation capabilities. Let’s get started!
1. Create UI Part in XML file for Navigation Screen
<RelativeLayout 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”>
———— Other UI Components ————
<androidx.cardview.widget.CardView
android:layout_width="50dp"
android:layout_height="50dp"
android:clickable="true"
android:onClick="compassClicked"
app:cardCornerRadius="25dp"
app:cardPreventCornerOverlap="true"
app:cardUseCompatPadding="false"
app:contentPadding="6dp">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@drawable/compass_needle" />
</androidx.cardview.widget.CardView>
</RelativeLayout>
2. Create a variable in class file for checking the compass status, name it as “isCompassOn”
private boolean isCompassOn = true;
3. Create a function in the class for compassClicked
public void compassClicked(View view) {
isCompassOn = !isCompassOn;
}
4. Define a sensor manager for compass sensor
//For compass UI
private CardView compassFab;
//For sensor configs
private SensorManager mSensorManager;
private Sensor mRotationSensor;
private float[] mRotationMatrix = new float[9];
private float[] mOrientation = new float[3];
//For current location
private GeoCoordinates currentLocation;
//Additional variable for saving map camera zoom
private int cameraZoom = 0;
5. Initialize the variables in onCreate function
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_navigation);
compassFab = findViewById(R.id.compassFab);
//sensor configs
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
// Get a reference to the rotation vector sensor
mRotationSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR);
}
6. Register map camera listener with map; and register and unregister sensor listener in onResume and onStop respectively.
public class NavigationActivity extends AppCompatActivity implements SensorEventListener, MapCameraListener {
mapView.getMapScene().loadScene(MapScheme.NORMAL_DAY, new MapScene.LoadSceneCallback() {
@Override
public void onLoadScene(@Nullable MapError mapError) {
if (mapError == null) {
——— other functions —————
mapView.getCamera().addListener(NavigationActivity.this);
} else {
Log.d(TAG, "Loading map failed: mapErrorCode: " + mapError.name());
}
}
}
@Override
protected void onResume() {
super.onResume();
// Register the sensor listener
mSensorManager.registerListener(this, mRotationSensor, SensorManager.SENSOR_DELAY_NORMAL);
}
@Override
protected void onPause() {
super.onPause();
// Unregister the sensor listener
mSensorManager.unregisterListener(this);
}
}
7. Save the current location from the navigation location listener on visual navigator
visualNavigator.setNavigableLocationListener(new NavigableLocationListener() {
@Override
public void onNavigableLocationUpdated(@NonNull NavigableLocation currentNavigableLocation) {
———— other functionality —————
currentLocation = currentNavigableLocation.originalLocation.coordinates;
}
});
8. Change the compass icon rotation according to the map camera rotation if compass is ON
@Override
public void onMapCameraUpdated(@NonNull MapCamera.State state) {
// Rotate the compass image
if (isCompassOn) {
compassFab.setRotation((float) state.orientationAtTarget.bearing);
}
}
9. Change the map camera according to the sensor
@Override
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() == Sensor.TYPE_ROTATION_VECTOR) {
// Convert the rotation vector to a rotation matrix
SensorManager.getRotationMatrixFromVector(mRotationMatrix, event.values);
// Convert the rotation matrix to orientation angles
SensorManager.getOrientation(mRotationMatrix, mOrientation);
// Convert the azimuth angle to degrees
float azimuthInRadians = mOrientation[0];
float azimuthInDegrees = (float) Math.toDegrees(azimuthInRadians);
// Rotate the map camera and compass image using compass sensor
if (!isCompassOn) {
compassFab.setRotation(-azimuthInDegrees);
GeoOrientationUpdate orientationUpdate = new GeoOrientationUpdate((double) -azimuthInDegrees, 0.0);
if (currentLocation != null) {
// please make a check for zoom as it should be one time only
mapView.getCamera().startAnimation(MapCameraAnimationFactory.flyTo(new GeoCoordinatesUpdate(currentLocation), orientationUpdate, cameraZoom == 0 ? 300 : 0, Duration.ofMillis(1)));
cameraZoom = 300;
}
}
}
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// Do nothing
}
We hope this tutorial has shown you how to use device hardware motion sensors with HERE SDK to create custom compass functionality for your navigation apps. This feature can enhance the user experience by providing more accurate and reliable orientation information. You can also customize the appearance and behavior of the compass to suit your app design and preferences. HERE SDK offers many other features and capabilities for creating amazing navigation apps, so make sure to check out our developer blog for more tips and tricks. If you have any questions or comments, reach us out on our Slack channel, and we'll be happy to assist you! Or simply drop by to say hi and connect with fellow developers. We're looking forward to hearing from you!
Resources- HERE SDK for Android (Navigate Edition)
- Full-fledged Android reference application source code including above implementation can be downloaded from - https://demo.support.here.com/sdk_examples/HEREDriveAndroid.zip
- For more examples, please visit - https://demo.support.here.com/mobilesdk_examples
Have your say
Sign up for our newsletter
Why sign up:
- Latest offers and discounts
- Tailored content delivered weekly
- Exclusive events
- One click to unsubscribe