Skip to content

Commit 212726d

Browse files
committed
Add drop-in UI support for Feedback Agent
1 parent 40fc82d commit 212726d

104 files changed

Lines changed: 2065 additions & 2 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

examples/src/main/AndroidManifest.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,11 @@
101101
android:screenOrientation="portrait">
102102
</activity>
103103

104+
<activity
105+
android:name="com.mapbox.navigation.examples.voicefeedback.MapboxVoiceFeedbackActivity"
106+
android:label="@string/title_voice_feedback">
107+
</activity>
108+
104109
<activity
105110
android:name="com.mapbox.navigation.examples.MainActivity"
106111
android:exported="true">

examples/src/main/java/com/mapbox/navigation/examples/MainActivity.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import com.mapbox.navigation.examples.core.databinding.LayoutActivityMainBinding
3333
import com.mapbox.navigation.examples.util.LocationPermissionsHelper
3434
import com.mapbox.navigation.examples.util.LocationPermissionsHelper.Companion.areLocationPermissionsGranted
3535
import com.mapbox.navigation.examples.util.RouteDrawingActivity
36+
import com.mapbox.navigation.examples.voicefeedback.MapboxVoiceFeedbackActivity
3637

3738
class MainActivity : AppCompatActivity(), PermissionsListener {
3839

@@ -148,6 +149,11 @@ class MainActivity : AppCompatActivity(), PermissionsListener {
148149
getString(R.string.title_adasis),
149150
getString(R.string.description_adasis),
150151
AdasisActivity::class.java
152+
),
153+
SampleItem(
154+
getString(R.string.title_voice_feedback),
155+
getString(R.string.description_voice_feedback),
156+
MapboxVoiceFeedbackActivity::class.java
151157
)
152158
)
153159
}
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
package com.mapbox.navigation.examples.voicefeedback
2+
3+
import android.Manifest
4+
import android.os.Bundle
5+
import android.widget.Toast
6+
import androidx.activity.result.contract.ActivityResultContracts
7+
import androidx.appcompat.app.AppCompatActivity
8+
import com.mapbox.maps.MapboxMap
9+
import com.mapbox.maps.plugin.locationcomponent.location
10+
import com.mapbox.navigation.base.ExperimentalPreviewMapboxNavigationAPI
11+
import com.mapbox.navigation.base.options.NavigationOptions
12+
import com.mapbox.navigation.core.MapboxNavigation
13+
import com.mapbox.navigation.core.lifecycle.MapboxNavigationApp
14+
import com.mapbox.navigation.core.lifecycle.MapboxNavigationObserver
15+
import com.mapbox.navigation.core.lifecycle.requireMapboxNavigation
16+
import com.mapbox.navigation.examples.core.databinding.LayoutActivityVoiceFeedbackBinding
17+
import com.mapbox.navigation.examples.util.Utils
18+
import com.mapbox.navigation.ui.base.installer.installComponents
19+
import com.mapbox.navigation.ui.maps.location.NavigationLocationProvider
20+
import com.mapbox.navigation.ui.voicefeedback.voiceFeedbackButton
21+
22+
/**
23+
* Example activity demonstrating the [libnavui-voicefeedback](https://docs.mapbox.com/android/navigation/ui/latest/libnavui-voicefeedback/overview/)
24+
* SDK. This SDK provides voice feedback capabilities, allowing users to report issues,
25+
* suggest improvements, or give feedback directly through voice while navigating.
26+
*
27+
* It utilizes [MapboxVoiceFeedbackButton] and [FeedbackAgentSession] (via the ComponentInstaller)
28+
* to manage the lifecycle and UI states of the voice interaction flow.
29+
*/
30+
@OptIn(ExperimentalPreviewMapboxNavigationAPI::class)
31+
class MapboxVoiceFeedbackActivity : AppCompatActivity() {
32+
33+
private val navigationLocationProvider = NavigationLocationProvider()
34+
private lateinit var binding: LayoutActivityVoiceFeedbackBinding
35+
private lateinit var mapboxMap: MapboxMap
36+
private val mapboxNavigation: MapboxNavigation by requireMapboxNavigation(
37+
onResumedObserver = object : MapboxNavigationObserver {
38+
override fun onAttached(mapboxNavigation: MapboxNavigation) {
39+
}
40+
41+
override fun onDetached(mapboxNavigation: MapboxNavigation) {
42+
}
43+
},
44+
onInitialize = this::initNavigation
45+
)
46+
47+
private val requestPermissionLauncher = registerForActivityResult(
48+
ActivityResultContracts.RequestMultiplePermissions()
49+
) { permissions ->
50+
val areGranted = permissions.values.all { it }
51+
if (areGranted) {
52+
mapboxNavigation.startTripSession()
53+
} else {
54+
Toast.makeText(
55+
this,
56+
"Location and Microphone permissions are required",
57+
Toast.LENGTH_LONG
58+
).show()
59+
finish()
60+
}
61+
}
62+
63+
override fun onCreate(savedInstanceState: Bundle?) {
64+
super.onCreate(savedInstanceState)
65+
binding = LayoutActivityVoiceFeedbackBinding.inflate(layoutInflater)
66+
setContentView(binding.root)
67+
68+
mapboxMap = binding.mapView.getMapboxMap()
69+
70+
requestPermissionLauncher.launch(
71+
arrayOf(
72+
Manifest.permission.ACCESS_FINE_LOCATION,
73+
Manifest.permission.RECORD_AUDIO
74+
)
75+
)
76+
}
77+
78+
private fun initNavigation() {
79+
if (!MapboxNavigationApp.isSetup()) {
80+
MapboxNavigationApp.setup(
81+
NavigationOptions.Builder(this)
82+
.accessToken(Utils.getMapboxAccessToken(this))
83+
.build()
84+
)
85+
}
86+
87+
MapboxNavigationApp.installComponents(this) {
88+
voiceFeedbackButton(binding.voiceFeedbackButton)
89+
}
90+
91+
binding.mapView.location.apply {
92+
enabled = true
93+
setLocationProvider(navigationLocationProvider)
94+
}
95+
96+
mapboxMap.setCamera(
97+
com.mapbox.maps.CameraOptions.Builder()
98+
.center(com.mapbox.geojson.Point.fromLngLat(-73.98513, 40.748817)) // New York City
99+
.zoom(13.0)
100+
.build()
101+
)
102+
}
103+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
3+
xmlns:app="http://schemas.android.com/apk/res-auto"
4+
android:layout_width="match_parent"
5+
android:layout_height="match_parent">
6+
7+
<com.mapbox.maps.MapView
8+
android:id="@+id/mapView"
9+
android:layout_width="match_parent"
10+
android:layout_height="match_parent"
11+
app:mapbox_cameraZoom="14" />
12+
13+
<com.mapbox.navigation.ui.voicefeedback.view.MapboxVoiceFeedbackButton
14+
android:id="@+id/voiceFeedbackButton"
15+
android:layout_width="wrap_content"
16+
android:layout_height="wrap_content"
17+
android:layout_margin="16dp"
18+
app:layout_constraintEnd_toEndOf="parent"
19+
app:layout_constraintBottom_toBottomOf="parent" />
20+
21+
</androidx.constraintlayout.widget.ConstraintLayout>

examples/src/main/res/values/strings.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@
3939
<string name="title_adasis" translatable="false">Adasis Example</string>
4040
<string name="description_adasis" translatable="false">Demonstrates to to access Adasis functionality.</string>
4141

42+
<string name="title_voice_feedback" translatable="false">Voice Feedback Example</string>
43+
<string name="description_voice_feedback" translatable="false">Demonstrates the use of voice feedback API.</string>
44+
4245
<string name="label_start_navigation" translatable="false">Start Navigation</string>
4346
<string name="play_history" translatable="false">Play history</string>
4447
<string name="select_history" translatable="false">Select history</string>

gradle/dependencies.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ ext {
141141
androidStartup : "androidx.startup:startup-runtime:${version.androidStartup}",
142142
androidXFragment : "androidx.fragment:fragment-ktx:${version.androidXFragmentVersion}",
143143
androidXArchCoreTesting : "androidx.arch.core:core-testing:${version.androidXArchCoreVersion}",
144+
androidXFragmentTesting : "androidx.fragment:fragment-testing:${version.androidXFragmentVersion}",
144145
androidXDataStore : "androidx.datastore:datastore-preferences:${version.androidXDataStore}",
145146
androidXWorkManager : "androidx.work:work-runtime-ktx:${version.androidXWorkManager}",
146147

gradle/publish.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ sdkNameMap["libnavui-tripprogress"] = "mobile-navigation-ui-tripprogress"
7474
sdkNameMap["libnavui-maneuver"] = "mobile-navigation-ui-maneuver"
7575
sdkNameMap["libnavui-resources"] = "mobile-navigation-ui-resources"
7676
sdkNameMap["libnavui-voice"] = "mobile-navigation-ui-voice"
77+
sdkNameMap["libnavui-voicefeedback"] = "mobile-navigation-ui-voicefeedback"
7778
sdkNameMap["libnavui-speedlimit"] = "mobile-navigation-ui-speedlimit"
7879
sdkNameMap["libnavui-shield"] = "mobile-navigation-ui-shield"
7980
sdkNameMap["libnavui-status"] = "mobile-navigation-ui-status"

libnavigation-android/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ dependencies {
3434
api project(":libnavui-speedlimit")
3535
api project(":libnavui-tripprogress")
3636
api project(":libnavui-voice")
37+
api project(":libnavui-voicefeedback")
3738
api project(":libnavui-status")
3839
}
3940

libnavigation-voicefeedback/src/main/java/com/mapbox/navigation/voicefeedback/FeedbackAgentSession.kt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,12 @@ class FeedbackAgentSession private constructor(
197197
engine.disconnect()
198198
}
199199

200-
private companion object {
200+
companion object {
201201
private const val TAG = "FeedbackAgentSession"
202+
203+
@JvmStatic
204+
fun getRegisteredInstance(): FeedbackAgentSession = MapboxNavigationApp
205+
.getObservers(FeedbackAgentSession::class)
206+
.firstOrNull() ?: Builder().build().also { MapboxNavigationApp.registerObserver(it) }
202207
}
203208
}

libnavigation-voicefeedback/src/main/java/com/mapbox/navigation/voicefeedback/internal/audio/microphone/AudioRecordMicrophone.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,9 @@ internal class AudioRecordMicrophone : Microphone {
185185
logD(TAG) { "After startRecording: ${AudioInfoRetriever.stateString(audioRecord)}" }
186186
cont.invokeOnCancellation {
187187
logD(TAG) { "stream cancelled, calling audioRecord.stop()" }
188-
audioRecord.stop()
188+
if (audioRecord.recordingState == AudioRecord.RECORDSTATE_RECORDING) {
189+
audioRecord.stop()
190+
}
189191
}
190192
while (
191193
cont.isActive &&

0 commit comments

Comments
 (0)