Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ Mapbox welcomes participation and contributions from everyone.

## Unreleased
#### Features
- Moved `MapboxAudioGuidance` and `MapboxAudioGuidanceState` into public api. [#6336](https://github.com/mapbox/mapbox-navigation-android/pull/6336)
#### Bug fixes and improvements

## Mapbox Navigation SDK 2.9.0-alpha.2 - 16 September, 2022
Expand Down
346 changes: 1 addition & 345 deletions LICENSE.md

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions libnavui-androidauto/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ Mapbox welcomes participation and contributions from everyone.
## Unreleased
#### Features
#### Bug fixes and improvements
- Use `MapboxAudioGuidance` from public api. [#6336](https://github.com/mapbox/mapbox-navigation-android/pull/6336)

## androidauto-v0.11.0 - Sep 16, 2022
### Changelog
Expand Down
3 changes: 1 addition & 2 deletions libnavui-androidauto/api/current.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,9 @@ package com.mapbox.androidauto {
}

public final class MapboxCarApp {
method public com.mapbox.navigation.ui.voice.internal.MapboxAudioGuidance carAppAudioGuidanceService();
method public com.mapbox.androidauto.navigation.location.CarAppLocation carAppLocationService();
method public kotlinx.coroutines.flow.StateFlow<com.mapbox.androidauto.CarAppState> getCarAppState();
method public void setup(android.app.Application application);
method public void setup();
method public void updateCarAppState(com.mapbox.androidauto.CarAppState carAppState);
property public final kotlinx.coroutines.flow.StateFlow<com.mapbox.androidauto.CarAppState> carAppState;
field public static final com.mapbox.androidauto.MapboxCarApp INSTANCE;
Expand Down
7 changes: 3 additions & 4 deletions libnavui-androidauto/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,9 @@ dependencies {
def carSearchVersion = "1.0.0-beta.36"
api("com.mapbox.search:mapbox-search-android:${carSearchVersion}")

debugApi project(":libnavigation-android")
releaseApi("com.mapbox.navigation:android:${carNavVersion}")
debugImplementation project(":libnavui-app")
releaseImplementation("com.mapbox.navigation:ui-app:${carNavVersion}")
// TODO use the carNavVersion when 2.9.0-alpha.2 is available
api(project(":libnavigation-android"))
// api("com.mapbox.navigation:android:${carNavVersion}")

implementation(dependenciesList.androidXAppCompat)
implementation(dependenciesList.coroutinesCore)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,15 @@
package com.mapbox.androidauto

import android.app.Application
import com.mapbox.androidauto.navigation.location.CarAppLocation
import com.mapbox.androidauto.navigation.location.impl.CarAppLocationImpl
import com.mapbox.navigation.base.ExperimentalPreviewMapboxNavigationAPI
import com.mapbox.navigation.core.lifecycle.MapboxNavigationApp
import com.mapbox.navigation.ui.app.internal.SharedApp
import com.mapbox.navigation.ui.voice.internal.MapboxAudioGuidance
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow

/**
* The entry point for your Mapbox Android Auto app.
*/
@OptIn(ExperimentalPreviewMapboxNavigationAPI::class)
object MapboxCarApp {

private val carAppStateFlow = MutableStateFlow<CarAppState>(FreeDriveState)
Expand All @@ -29,12 +25,6 @@ object MapboxCarApp {
fun carAppLocationService(): CarAppLocation =
MapboxNavigationApp.getObserver(CarAppLocation::class)

/**
* Audio guidance service available to the car and app.
*/
fun carAppAudioGuidanceService(): MapboxAudioGuidance =
MapboxNavigationApp.getObserver(MapboxAudioGuidance::class)

/**
* Keep your car and app in sync with CarAppState.
*/
Expand All @@ -43,12 +33,12 @@ object MapboxCarApp {
}

/**
* Setup android auto from your [Application.onCreate]
*
* @param application used to detect when activities are foregrounded
* Setup android auto with defaults
*/
fun setup(application: Application) {
SharedApp.setup(application)
MapboxNavigationApp.registerObserver(CarAppLocationImpl())
@OptIn(ExperimentalPreviewMapboxNavigationAPI::class)
fun setup() {
if (MapboxNavigationApp.getObservers(CarAppLocation::class).isEmpty()) {
MapboxNavigationApp.registerObserver(CarAppLocationImpl())
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import com.mapbox.androidauto.MapboxCarApp
import com.mapbox.navigation.ui.voice.internal.MapboxAudioGuidance
import com.mapbox.navigation.ui.voice.api.MapboxAudioGuidance
import com.mapbox.navigation.ui.voice.api.MapboxAudioGuidanceState
import com.mapbox.navigation.ui.voice.view.MapboxSoundButton
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch
Expand All @@ -17,7 +17,7 @@ fun Fragment.attachAudioGuidance(
mapboxSoundButton: MapboxSoundButton
) {
val lifecycleOwner = viewLifecycleOwner
val flow = MapboxCarApp.carAppAudioGuidanceService().stateFlow()
val flow = MapboxAudioGuidance.getInstance().stateFlow()
lifecycleOwner.lifecycleScope.launch {
lifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
flow.collect { state ->
Expand All @@ -31,7 +31,7 @@ fun Fragment.attachAudioGuidance(
}
}
mapboxSoundButton.setOnClickListener {
MapboxCarApp.carAppAudioGuidanceService().toggle()
MapboxAudioGuidance.getInstance().toggle()
}
}

Expand All @@ -40,17 +40,17 @@ fun Fragment.attachAudioGuidance(
*/
fun Lifecycle.muteAudioGuidance() {
addObserver(object : DefaultLifecycleObserver {
lateinit var initialState: MapboxAudioGuidance.State
lateinit var initialState: MapboxAudioGuidanceState
override fun onResume(owner: LifecycleOwner) {
with(MapboxCarApp.carAppAudioGuidanceService()) {
with(MapboxAudioGuidance.getInstance()) {
initialState = stateFlow().value
mute()
}
}

override fun onPause(owner: LifecycleOwner) {
if (!initialState.isMuted) {
MapboxCarApp.carAppAudioGuidanceService().unmute()
MapboxAudioGuidance.getInstance().unMute()
}
}
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ import androidx.core.graphics.drawable.IconCompat
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.coroutineScope
import androidx.lifecycle.repeatOnLifecycle
import com.mapbox.androidauto.MapboxCarApp
import com.mapbox.androidauto.R
import com.mapbox.androidauto.car.MainActionStrip
import com.mapbox.androidauto.car.action.MapboxActionProvider
import com.mapbox.navigation.ui.voice.api.MapboxAudioGuidance
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.launch
Expand All @@ -28,15 +28,15 @@ class CarAudioGuidanceUi : MapboxActionProvider.ScreenActionProvider {
* Attach this to the screen while navigating.
*/
private fun buildSoundButtonAction(screen: Screen): Action {
val audioGuidance = MapboxCarApp.carAppAudioGuidanceService()
val audioGuidance = MapboxAudioGuidance.getInstance()
val state = audioGuidance.stateFlow().value
return if (!state.isMuted) {
buildIconAction(screen, R.drawable.mapbox_car_ic_volume_on) {
audioGuidance.mute()
}
} else {
buildIconAction(screen, R.drawable.mapbox_car_ic_volume_off) {
audioGuidance.unmute()
audioGuidance.unMute()
}
}
}
Expand All @@ -45,7 +45,7 @@ class CarAudioGuidanceUi : MapboxActionProvider.ScreenActionProvider {
screen.lifecycle.apply {
coroutineScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED) {
MapboxCarApp.carAppAudioGuidanceService().stateFlow()
MapboxAudioGuidance.getInstance().stateFlow()
.distinctUntilChanged { old, new ->
old.isMuted == new.isMuted && old.isPlayable == new.isPlayable
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.mapbox.navigation.ui.app.internal

import android.content.Context
import com.mapbox.navigation.base.ExperimentalPreviewMapboxNavigationAPI
import com.mapbox.navigation.core.internal.extensions.attachCreated
import com.mapbox.navigation.core.lifecycle.MapboxNavigationApp
Expand All @@ -17,9 +16,6 @@ import com.mapbox.navigation.ui.app.internal.controller.StateResetController
import com.mapbox.navigation.ui.app.internal.controller.TripSessionStarterStateController
import com.mapbox.navigation.ui.maps.internal.ui.RouteAlternativeComponent
import com.mapbox.navigation.ui.maps.internal.ui.RouteAlternativeContract
import com.mapbox.navigation.ui.utils.internal.datastore.NavigationDataStoreOwner
import com.mapbox.navigation.ui.voice.internal.MapboxAudioGuidance
import com.mapbox.navigation.ui.voice.internal.impl.MapboxAudioGuidanceImpl
import java.util.concurrent.atomic.AtomicBoolean

@OptIn(ExperimentalPreviewMapboxNavigationAPI::class)
Expand Down Expand Up @@ -55,8 +51,6 @@ object SharedApp {

@JvmOverloads
fun setup(
context: Context,
audioGuidance: MapboxAudioGuidance? = null,
routeAlternativeContract: RouteAlternativeContract? = null
) {
if (isSetup) return
Expand All @@ -69,7 +63,6 @@ object SharedApp {
}
)
MapboxNavigationApp.lifecycleOwner.attachCreated(*navigationObservers)
MapboxNavigationApp.registerObserver(audioGuidance ?: defaultAudioGuidance(context))
}

fun tripSessionTransaction(updateSession: () -> Unit) {
Expand All @@ -80,12 +73,4 @@ object SharedApp {
updateSession()
ignoreTripSessionUpdates.set(false)
}

private fun defaultAudioGuidance(context: Context): MapboxAudioGuidance {
return MapboxAudioGuidanceImpl.create(context).also {
it.dataStoreOwner = NavigationDataStoreOwner(context, DEFAULT_DATA_STORE_NAME)
}
}

private const val DEFAULT_DATA_STORE_NAME = "mapbox_navigation_preferences"
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,12 @@ package com.mapbox.navigation.ui.app.internal.controller

import com.mapbox.navigation.base.ExperimentalPreviewMapboxNavigationAPI
import com.mapbox.navigation.core.MapboxNavigation
import com.mapbox.navigation.core.lifecycle.MapboxNavigationApp
import com.mapbox.navigation.ui.app.internal.Action
import com.mapbox.navigation.ui.app.internal.State
import com.mapbox.navigation.ui.app.internal.Store
import com.mapbox.navigation.ui.app.internal.audioguidance.AudioAction
import com.mapbox.navigation.ui.app.internal.audioguidance.AudioGuidanceState
import com.mapbox.navigation.ui.voice.internal.MapboxAudioGuidance
import com.mapbox.navigation.ui.voice.api.MapboxAudioGuidance

/**
* This class is responsible for playing voice instructions. Use the [AudioAction] to turning the
Expand Down Expand Up @@ -47,7 +46,7 @@ class AudioGuidanceStateController(
override fun onAttached(mapboxNavigation: MapboxNavigation) {
super.onAttached(mapboxNavigation)

val audioGuidance = MapboxNavigationApp.getObserver(MapboxAudioGuidance::class)
val audioGuidance = MapboxAudioGuidance.getInstance()
audioGuidance.stateFlow().observe {
if (it.isMuted != store.state.value.audio.isMuted) {
val newState = AudioGuidanceState(it.isMuted)
Expand All @@ -59,7 +58,7 @@ class AudioGuidanceStateController(
if (it.isMuted) {
audioGuidance.mute()
} else {
audioGuidance.unmute()
audioGuidance.unMute()
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,14 @@
package com.mapbox.navigation.ui.app.internal.controller

import com.mapbox.api.directions.v5.models.VoiceInstructions
import com.mapbox.navigation.base.ExperimentalPreviewMapboxNavigationAPI
import com.mapbox.navigation.core.MapboxNavigation
import com.mapbox.navigation.core.lifecycle.MapboxNavigationApp
import com.mapbox.navigation.testing.MainCoroutineRule
import com.mapbox.navigation.ui.app.internal.State
import com.mapbox.navigation.ui.app.internal.audioguidance.AudioAction
import com.mapbox.navigation.ui.app.internal.audioguidance.AudioGuidanceState
import com.mapbox.navigation.ui.app.internal.navigation.NavigationState
import com.mapbox.navigation.ui.app.testing.TestStore
import com.mapbox.navigation.ui.voice.internal.MapboxAudioGuidance
import com.mapbox.navigation.ui.voice.model.SpeechAnnouncement
import com.mapbox.navigation.ui.voice.api.MapboxAudioGuidance
import com.mapbox.navigation.ui.voice.api.MapboxAudioGuidanceState
import io.mockk.every
import io.mockk.mockk
import io.mockk.mockkObject
Expand All @@ -27,29 +24,27 @@ import org.junit.Before
import org.junit.Rule
import org.junit.Test

@OptIn(ExperimentalPreviewMapboxNavigationAPI::class, ExperimentalCoroutinesApi::class)
@OptIn(ExperimentalCoroutinesApi::class)
class AudioGuidanceStateControllerTest {

@get:Rule
var coroutineRule = MainCoroutineRule()

private lateinit var audioGuidanceState: MutableStateFlow<MapboxAudioGuidance.State>
private lateinit var audioGuidanceState: MutableStateFlow<MapboxAudioGuidanceState>
private lateinit var mockAudioGuidance: MapboxAudioGuidance
private lateinit var testStore: TestStore

@Before
fun setup() {
mockkObject(MapboxNavigationApp)
mockkObject(MapboxAudioGuidance)

audioGuidanceState = MutableStateFlow(
TestAudioGuidanceState(isMuted = false)
mockk { every { isMuted } returns false }
)
mockAudioGuidance = mockk(relaxed = true) {
every { stateFlow() } returns audioGuidanceState
}
every {
MapboxNavigationApp.getObserver(MapboxAudioGuidance::class)
} returns mockAudioGuidance
every { MapboxAudioGuidance.getInstance() } returns mockAudioGuidance

testStore = spyk(TestStore())
}
Expand All @@ -68,9 +63,9 @@ class AudioGuidanceStateControllerTest {
audio = AudioGuidanceState(isMuted = false)
)
)
audioGuidanceState.value = TestAudioGuidanceState(isMuted = true)
audioGuidanceState.value = mockk { every { isMuted } returns true }

sut.onAttached(mockMapboxNavigation())
sut.onAttached(mockk())
assertTrue(testStore.state.value.audio.isMuted)
}

Expand All @@ -83,9 +78,9 @@ class AudioGuidanceStateControllerTest {
audio = AudioGuidanceState(isMuted = false)
)
)
audioGuidanceState.value = TestAudioGuidanceState(isMuted = false)
audioGuidanceState.value = mockk { every { isMuted } returns false }

sut.onAttached(mockMapboxNavigation())
sut.onAttached(mockk())
testStore.setState(
State(
audio = AudioGuidanceState(isMuted = true)
Expand All @@ -105,24 +100,11 @@ class AudioGuidanceStateControllerTest {
)
val sut = AudioGuidanceStateController(testStore)

val mapboxNavigation = mockMapboxNavigation()
val mapboxNavigation: MapboxNavigation = mockk()
sut.onAttached(mapboxNavigation)
testStore.dispatch(AudioAction.Toggle)
sut.onDetached(mapboxNavigation)

assertTrue(testStore.state.value.audio.isMuted)
}

private fun mockMapboxNavigation(): MapboxNavigation {
val mapboxNavigation = mockk<MapboxNavigation>(relaxed = true)
every { MapboxNavigationApp.current() } returns mapboxNavigation
return mapboxNavigation
}

private data class TestAudioGuidanceState(
override val isMuted: Boolean,
override val isPlayable: Boolean = false,
override val voiceInstructions: VoiceInstructions? = null,
override val speechAnnouncement: SpeechAnnouncement? = null
) : MapboxAudioGuidance.State
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package com.mapbox.navigation.dropin

import android.Manifest
import android.app.Activity
import android.app.Application
import android.content.Context
import android.util.AttributeSet
import android.view.LayoutInflater
Expand Down Expand Up @@ -109,7 +108,7 @@ class NavigationView @JvmOverloads constructor(
keepScreenOn = true
captureSystemBarsInsets()

SharedApp.setup(context.applicationContext as Application)
SharedApp.setup()
if (!MapboxNavigationApp.isSetup()) {
MapboxNavigationApp.setup(
NavigationOptions.Builder(context)
Expand Down
Loading