diff --git a/gradle/dependencies.gradle b/gradle/dependencies.gradle index f1ec8817662..2dedd988b11 100644 --- a/gradle/dependencies.gradle +++ b/gradle/dependencies.gradle @@ -17,7 +17,7 @@ ext { println("Navigation Native version: " + mapboxNavigatorVersion) version = [ - mapboxMapSdk : '10.0.1', + mapboxMapSdk : '10.0.0', mapboxSdkServices : '6.0.0', mapboxEvents : '8.1.0', mapboxCore : '5.0.0', diff --git a/libtrip-notification/src/main/java/com/mapbox/navigation/trip/notification/MapboxTripNotificationView.kt b/libtrip-notification/src/main/java/com/mapbox/navigation/trip/notification/MapboxTripNotificationView.kt index 02de0f63e00..291760e9373 100644 --- a/libtrip-notification/src/main/java/com/mapbox/navigation/trip/notification/MapboxTripNotificationView.kt +++ b/libtrip-notification/src/main/java/com/mapbox/navigation/trip/notification/MapboxTripNotificationView.kt @@ -66,7 +66,7 @@ internal class MapboxTripNotificationView( */ fun setEndNavigationButtonText(textResource: Int) { expandedView?.setTextViewText( - R.id.endNavigationBtnText, + R.id.endNavigationBtn, context.getString(textResource) ) } @@ -145,7 +145,7 @@ internal class MapboxTripNotificationView( setTextViewText(R.id.notificationDistanceText, "") setTextViewText(R.id.notificationArrivalText, "") setTextViewText(R.id.notificationInstructionText, "") - setTextViewText(R.id.endNavigationBtnText, "") + setTextViewText(R.id.endNavigationBtn, "") setViewVisibility(R.id.etaContent, View.GONE) setViewVisibility(R.id.notificationInstructionText, View.GONE) setViewVisibility(R.id.freeDriveText, View.GONE) diff --git a/libtrip-notification/src/main/java/com/mapbox/navigation/trip/notification/internal/MapboxTripNotification.kt b/libtrip-notification/src/main/java/com/mapbox/navigation/trip/notification/internal/MapboxTripNotification.kt index 77ff10d0487..9fa89250bcb 100644 --- a/libtrip-notification/src/main/java/com/mapbox/navigation/trip/notification/internal/MapboxTripNotification.kt +++ b/libtrip-notification/src/main/java/com/mapbox/navigation/trip/notification/internal/MapboxTripNotification.kt @@ -13,11 +13,13 @@ import android.graphics.Canvas import android.graphics.Matrix import android.graphics.drawable.Drawable import android.os.Build +import android.text.SpannableString import android.text.TextUtils import android.text.format.DateFormat import android.view.View.GONE import android.view.View.VISIBLE import androidx.core.app.NotificationCompat +import androidx.core.content.ContextCompat import com.mapbox.annotation.module.MapboxModule import com.mapbox.annotation.module.MapboxModuleType import com.mapbox.api.directions.v5.models.BannerInstructions @@ -39,7 +41,6 @@ import com.mapbox.navigation.utils.internal.NAVIGATION_NOTIFICATION_CHANNEL import com.mapbox.navigation.utils.internal.NOTIFICATION_CHANNEL import com.mapbox.navigation.utils.internal.NOTIFICATION_ID import com.mapbox.navigation.utils.internal.ifChannelException -import com.mapbox.navigation.utils.internal.ifNonNull import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.channels.ClosedReceiveChannelException import kotlinx.coroutines.channels.ClosedSendChannelException @@ -74,9 +75,12 @@ class MapboxTripNotification constructor( var currentManeuverModifier: String? = null private set private var currentRoundaboutAngle: Float? = null + private var currentManeuverImage: Bitmap? = null private var currentInstructionText: String? = null private var currentDistanceText: Double? = null + private var currentFormattedDistance: SpannableString? = null + private var currentFormattedTime: String? = null private var pendingOpenIntent: PendingIntent? = null private var pendingCloseIntent: PendingIntent? = null private val etaFormat: String = applicationContext.getString(R.string.mapbox_eta_format) @@ -205,6 +209,11 @@ class MapboxTripNotification constructor( .setCustomBigContentView(notificationView.expandedView) .setOngoing(true) + if (Build.VERSION.SDK_INT >= 31) { + val color = ContextCompat.getColor(applicationContext, R.color.mapbox_notification_blue) + builder.setColor(color).setColorized(true) + } + pendingOpenIntent?.let { pendingOpenIntent -> builder.setContentIntent(pendingOpenIntent) } @@ -253,21 +262,10 @@ class MapboxTripNotification constructor( when (state) { is TripNotificationState.TripNotificationFreeState -> setFreeDriveMode(true) is TripNotificationState.TripNotificationData -> { - if (isDistanceTextChanged(state.distanceRemaining)) { - updateDistanceText(state.distanceRemaining) - } - generateArrivalTime(state.durationRemaining)?.let { formattedTime -> - updateViewsWithArrival(formattedTime) - } - state.bannerInstructions?.let { bannerInstructions -> - val primary = bannerInstructions.primary().text() - if (isInstructionTextChanged(primary)) { - updateInstructionText(primary) - } - if (isManeuverStateChanged(bannerInstructions)) { - updateManeuverImage(state.drivingSide ?: ManeuverModifier.RIGHT) - } - } + updateDistanceText(state.distanceRemaining) + updateViewsWithArrival(state.durationRemaining) + updateInstructionText(state.bannerInstructions) + updateManeuverImage(state.bannerInstructions, state.drivingSide) setFreeDriveMode(false) } } @@ -291,11 +289,11 @@ class MapboxTripNotification constructor( } private fun updateDistanceText(distanceRemaining: Double?) { - val formattedDistance = distanceRemaining?.let { - distanceFormatter.formatDistance(distanceRemaining) - } ?: return - currentDistanceText = distanceRemaining - notificationView.updateDistanceText(formattedDistance) + if (isDistanceTextChanged(distanceRemaining) && distanceRemaining != null) { + currentDistanceText = distanceRemaining + currentFormattedDistance = distanceFormatter.formatDistance(distanceRemaining) + } + currentFormattedDistance?.let { notificationView.updateDistanceText(it) } } private fun generateArrivalTime( @@ -314,17 +312,20 @@ class MapboxTripNotification constructor( } } - private fun updateViewsWithArrival(time: String) { - notificationView.updateArrivalTime(time) + private fun updateViewsWithArrival(durationRemaining: Double?) { + generateArrivalTime(durationRemaining)?.let { currentFormattedTime = it } + currentFormattedTime?.let { notificationView.updateArrivalTime(it) } } private fun isInstructionTextChanged(primaryText: String): Boolean { return currentInstructionText.isNullOrEmpty() || currentInstructionText != primaryText } - private fun updateInstructionText(primaryText: String) { - notificationView.updateInstructionText(primaryText) - currentInstructionText = primaryText + private fun updateInstructionText(bannerInstructions: BannerInstructions?) { + bannerInstructions?.primary()?.text() + ?.takeIf { isInstructionTextChanged(it) } + ?.let { currentInstructionText = it } + currentInstructionText?.let { notificationView.updateInstructionText(it) } } private fun isManeuverStateChanged(bannerInstruction: BannerInstructions): Boolean { @@ -341,23 +342,21 @@ class MapboxTripNotification constructor( currentRoundaboutAngle != previousRoundaboutAngle } - private fun updateManeuverImage(drivingSide: String) { - val notificationTurnIcon = turnIconHelper.retrieveTurnIcon( - currentManeuverType, - currentRoundaboutAngle, - currentManeuverModifier, - drivingSide - ) - ifNonNull(notificationTurnIcon) { turnIcon -> - ifNonNull(turnIcon.icon) { image -> - val originalDrawable = notificationView.getImageDrawable(image) - ifNonNull(originalDrawable) { drawable -> - ifNonNull(getManeuverBitmap(drawable, turnIcon.shouldFlipIcon)) { bitmap -> - notificationView.updateImage(bitmap) - } - } + private fun updateManeuverImage(bannerInstructions: BannerInstructions?, drivingSide: String?) { + if (bannerInstructions != null && isManeuverStateChanged(bannerInstructions)) { + turnIconHelper.retrieveTurnIcon( + currentManeuverType, + currentRoundaboutAngle, + currentManeuverModifier, + drivingSide = drivingSide ?: ManeuverModifier.RIGHT, + )?.let { turnIcon -> + turnIcon.icon + ?.let { notificationView.getImageDrawable(it) } + ?.let { getManeuverBitmap(it, turnIcon.shouldFlipIcon) } + ?.let { currentManeuverImage = it } } } + currentManeuverImage?.let { notificationView.updateImage(it) } } private fun getManeuverBitmap(drawable: Drawable, shouldFlipIcon: Boolean): Bitmap? { diff --git a/libtrip-notification/src/main/res/layout/mapbox_notification_navigation_collapsed.xml b/libtrip-notification/src/main/res/layout/mapbox_notification_navigation_collapsed.xml index ede98fed391..9c58ceebbf2 100644 --- a/libtrip-notification/src/main/res/layout/mapbox_notification_navigation_collapsed.xml +++ b/libtrip-notification/src/main/res/layout/mapbox_notification_navigation_collapsed.xml @@ -3,8 +3,9 @@ xmlns:tools="http://schemas.android.com/tools" android:id="@+id/navigationCollapsedNotificationLayout" android:layout_width="match_parent" - android:layout_height="64dp" - android:background="@color/mapbox_notification_blue"> + android:layout_height="wrap_content" + android:background="@color/mapbox_notification_blue" + android:padding="@dimen/mapbox_notification_padding"> diff --git a/libtrip-notification/src/main/res/layout/mapbox_notification_navigation_expanded.xml b/libtrip-notification/src/main/res/layout/mapbox_notification_navigation_expanded.xml index 485806f7a8b..4105a44d6a2 100644 --- a/libtrip-notification/src/main/res/layout/mapbox_notification_navigation_expanded.xml +++ b/libtrip-notification/src/main/res/layout/mapbox_notification_navigation_expanded.xml @@ -11,33 +11,21 @@ - - - - - - - + android:paddingBottom="@dimen/mapbox_notification_padding" + android:paddingEnd="@dimen/mapbox_notification_padding" + android:paddingStart="@dimen/mapbox_notification_padding" + android:drawablePadding="8dp" + android:drawableStart="@drawable/mapbox_ic_close" + android:textAllCaps="true" + android:textColor="@android:color/white" + tools:text="@string/mapbox_end_navigation" /> diff --git a/libtrip-notification/src/main/res/values-v31/dimens.xml b/libtrip-notification/src/main/res/values-v31/dimens.xml new file mode 100644 index 00000000000..77d5ad95159 --- /dev/null +++ b/libtrip-notification/src/main/res/values-v31/dimens.xml @@ -0,0 +1,4 @@ + + + 0dp + \ No newline at end of file diff --git a/libtrip-notification/src/main/res/values/dimens.xml b/libtrip-notification/src/main/res/values/dimens.xml index e972ea2a250..fb311bf50d3 100644 --- a/libtrip-notification/src/main/res/values/dimens.xml +++ b/libtrip-notification/src/main/res/values/dimens.xml @@ -2,4 +2,5 @@ 48dp 48dp + 8dp \ No newline at end of file diff --git a/libtrip-notification/src/test/java/com/mapbox/navigation/trip/notification/MapboxTripNotificationViewTest.kt b/libtrip-notification/src/test/java/com/mapbox/navigation/trip/notification/MapboxTripNotificationViewTest.kt index 73461385a9e..4eebcd20854 100644 --- a/libtrip-notification/src/test/java/com/mapbox/navigation/trip/notification/MapboxTripNotificationViewTest.kt +++ b/libtrip-notification/src/test/java/com/mapbox/navigation/trip/notification/MapboxTripNotificationViewTest.kt @@ -15,7 +15,7 @@ import io.mockk.every import io.mockk.mockk import io.mockk.mockkObject import io.mockk.verify -import junit.framework.Assert.assertNotNull +import org.junit.Assert.assertNotNull import org.junit.Before import org.junit.Test import java.util.Locale @@ -86,7 +86,7 @@ class MapboxTripNotificationViewTest { it.setEndNavigationButtonText(R.string.mapbox_stop_session) } - verify { view.expandedView!!.setTextViewText(R.id.endNavigationBtnText, STOP_SESSION) } + verify { view.expandedView!!.setTextViewText(R.id.endNavigationBtn, STOP_SESSION) } } @Test @@ -206,7 +206,7 @@ class MapboxTripNotificationViewTest { R.drawable.mapbox_ic_navigation ) } - verify { view.expandedView!!.setTextViewText(R.id.endNavigationBtnText, STOP_SESSION) } + verify { view.expandedView!!.setTextViewText(R.id.endNavigationBtn, STOP_SESSION) } } @Test @@ -228,7 +228,7 @@ class MapboxTripNotificationViewTest { verify { view.expandedView!!.setViewVisibility(R.id.notificationInstructionText, View.VISIBLE) } - verify { view.expandedView!!.setTextViewText(R.id.endNavigationBtnText, END_NAVIGATION) } + verify { view.expandedView!!.setTextViewText(R.id.endNavigationBtn, END_NAVIGATION) } } private fun createContext(): Context { diff --git a/libtrip-notification/src/test/java/com/mapbox/navigation/trip/notification/internal/MapboxTripNotificationTest.kt b/libtrip-notification/src/test/java/com/mapbox/navigation/trip/notification/internal/MapboxTripNotificationTest.kt index 20b83317359..fce08007690 100644 --- a/libtrip-notification/src/test/java/com/mapbox/navigation/trip/notification/internal/MapboxTripNotificationTest.kt +++ b/libtrip-notification/src/test/java/com/mapbox/navigation/trip/notification/internal/MapboxTripNotificationTest.kt @@ -16,7 +16,6 @@ import android.widget.RemoteViews import com.mapbox.api.directions.v5.models.BannerInstructions import com.mapbox.api.directions.v5.models.BannerText import com.mapbox.navigation.base.formatter.DistanceFormatter -import com.mapbox.navigation.base.internal.factory.TripNotificationStateFactory import com.mapbox.navigation.base.internal.factory.TripNotificationStateFactory.buildTripNotificationState import com.mapbox.navigation.base.internal.time.TimeFormatter import com.mapbox.navigation.base.options.NavigationOptions @@ -34,6 +33,7 @@ import io.mockk.mockkObject import io.mockk.mockkStatic import io.mockk.slot import io.mockk.verify +import kotlinx.coroutines.ExperimentalCoroutinesApi import org.junit.Assert.assertEquals import org.junit.Assert.assertNotNull import org.junit.Assert.assertNull @@ -157,6 +157,7 @@ class MapboxTripNotificationTest { verify(exactly = 1) { mockedContext.registerReceiver(any(), any()) } } + @ExperimentalCoroutinesApi @Test fun whenTripStoppedThenCleanupIsDone() { val notificationManager = @@ -242,8 +243,8 @@ class MapboxTripNotificationTest { mockUpdateNotificationAndroidInteractions() val suffix = "this is nice formatting" mockTimeFormatter(suffix) - val result = String.format(FORMAT_STRING, suffix + duration.toDouble().toString()) - val state = TripNotificationStateFactory.buildTripNotificationState( + val result = String.format(FORMAT_STRING, suffix + duration.toString()) + val state = buildTripNotificationState( null, distance, duration, @@ -257,7 +258,7 @@ class MapboxTripNotificationTest { } @Test - fun whenUpdateNotificationCalledTwiceWithSameDataThenRemoteViewAreNotUpdatedTwice() { + fun whenUpdateNotificationCalledTwiceWithSameDataThenRemoteViewUpdatedTwice() { val state = mockk(relaxed = true) val primaryText = { "Primary Text" } val bannerText = mockBannerText(state, primaryText) @@ -272,8 +273,8 @@ class MapboxTripNotificationTest { notification.updateNotification(state) verify(exactly = 2) { bannerText.text() } - verify(exactly = 1) { collapsedViews.setTextViewText(any(), primaryText()) } - verify(exactly = 1) { expandedViews.setTextViewText(any(), primaryText()) } + verify(exactly = 2) { collapsedViews.setTextViewText(any(), primaryText()) } + verify(exactly = 2) { expandedViews.setTextViewText(any(), primaryText()) } assertEquals(notification.currentManeuverType, MANEUVER_TYPE) assertEquals(notification.currentManeuverModifier, MANEUVER_MODIFIER) } @@ -412,7 +413,7 @@ class MapboxTripNotificationTest { expandedViews.setViewVisibility(R.id.freeDriveText, any()) } verify(exactly = 2) { - expandedViews.setTextViewText(R.id.endNavigationBtnText, STOP_SESSION) + expandedViews.setTextViewText(R.id.endNavigationBtn, STOP_SESSION) } }