From 14c9c112424deaede308191f697fe90d675d0e53 Mon Sep 17 00:00:00 2001 From: Joonas Kerttula Date: Thu, 2 Oct 2025 08:57:53 +0300 Subject: [PATCH 1/3] chore: fix changelog entry for version 0.10.1 --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f6d647e..9c36fcc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,7 +20,7 @@ ### Features * support latest rn versions ([#467](https://github.com/googlemaps/react-native-navigation-sdk/issues/467)) ([2b69764](https://github.com/googlemaps/react-native-navigation-sdk/commit/2b69764462c97a34ec14228410c4de7e189d2ee3)) -* upgrade to latest Android SDK 10.3.0 ([#470](https://github.com/googlemaps/react-native-navigation-sdk/issues/470)) ([85f678a](https://github.com/googlemaps/react-native-navigation-sdk/commit/85f678abd858e1e6f5fd1cb0f1d3fb54dd36d13b)) +* upgrade to latest iOS SDK 10.3.0 ([#470](https://github.com/googlemaps/react-native-navigation-sdk/issues/470)) ([85f678a](https://github.com/googlemaps/react-native-navigation-sdk/commit/85f678abd858e1e6f5fd1cb0f1d3fb54dd36d13b)) ## [0.10.0](https://github.com/googlemaps/react-native-navigation-sdk/compare/v0.9.3...v0.10.0) (2025-08-11) From 7522ce45a5eb2340c58d23cb2abb82b87cdd99e8 Mon Sep 17 00:00:00 2001 From: Joonas Kerttula Date: Fri, 3 Oct 2025 12:51:57 +0300 Subject: [PATCH 2/3] feat!: update android SDK to 7.0.0 - set targetSdkVersion to 36 - add support for new RouteStatus: DUPLICATE_WAYPOINTS_ERROR --- android/build.gradle | 4 +- .../android/react/navsdk/NavModule.java | 28 +--- .../react/navsdk/ObjectTranslationUtil.java | 10 +- example/android/app/build.gradle | 2 +- example/src/screens/MultipleMapsScreen.tsx | 125 +++++----------- example/src/screens/NavigationScreen.tsx | 136 +++++------------- src/navigation/shared.ts | 3 + src/navigation/types.ts | 2 + 8 files changed, 94 insertions(+), 216 deletions(-) diff --git a/android/build.gradle b/android/build.gradle index 9e3a6ee..7e27596 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -48,7 +48,7 @@ android { defaultConfig { minSdkVersion 24 - targetSdkVersion 34 + targetSdkVersion 36 } buildFeatures { @@ -82,6 +82,6 @@ dependencies { implementation "androidx.car.app:app:1.4.0" implementation "androidx.car.app:app-projected:1.4.0" implementation 'androidx.constraintlayout:constraintlayout:2.1.4' - implementation "com.google.android.libraries.navigation:navigation:6.3.1" + implementation "com.google.android.libraries.navigation:navigation:7.0.0" api 'com.google.guava:guava:31.0.1-android' } diff --git a/android/src/main/java/com/google/android/react/navsdk/NavModule.java b/android/src/main/java/com/google/android/react/navsdk/NavModule.java index 030a15b..2c8e22c 100644 --- a/android/src/main/java/com/google/android/react/navsdk/NavModule.java +++ b/android/src/main/java/com/google/android/react/navsdk/NavModule.java @@ -459,13 +459,11 @@ public void setDestinations( pendingRoute = mNavigator.setDestinations(mWaypoints); } - setOnResultListener( - new IRouteStatusResult() { - @Override - public void onResult(Navigator.RouteStatus code) { - sendCommandToReactNative("onRouteStatusResult", code.toString()); - } - }); + if (pendingRoute != null) { + // Set an action to perform when a route is determined to the destination + pendingRoute.setOnResultListener( + code -> sendCommandToReactNative("onRouteStatusResult", code.toString())); + } } @ReactMethod @@ -483,18 +481,6 @@ public void continueToNextDestination() { } } - private void setOnResultListener(IRouteStatusResult listener) { - // Set an action to perform when a route is determined to the destination - if (pendingRoute != null) - pendingRoute.setOnResultListener( - new ListenableResultFuture.OnResultListener() { - @Override - public void onResult(Navigator.RouteStatus code) { - listener.onResult(code); - } - }); - } - @ReactMethod public void startGuidance() { if (mWaypoints.isEmpty()) { @@ -844,8 +830,4 @@ public void onHostPause() {} @Override public void onHostDestroy() {} - - private interface IRouteStatusResult { - void onResult(Navigator.RouteStatus code); - } } diff --git a/android/src/main/java/com/google/android/react/navsdk/ObjectTranslationUtil.java b/android/src/main/java/com/google/android/react/navsdk/ObjectTranslationUtil.java index 7c86f2f..c44cdca 100644 --- a/android/src/main/java/com/google/android/react/navsdk/ObjectTranslationUtil.java +++ b/android/src/main/java/com/google/android/react/navsdk/ObjectTranslationUtil.java @@ -113,12 +113,18 @@ public static DisplayOptions getDisplayOptionsFromMap(Map map) { options.hideDestinationMarkers(!CollectionUtil.getBool("showDestinationMarkers", map, true)); } + // Note: showStopSigns and showTrafficLights are deprecated in Navigation SDK 7.0.0 + // and now default to true. These will be removed in SDK 8.0.0 if (map.containsKey("showStopSigns")) { - options.showStopSigns(CollectionUtil.getBool("showStopSigns", map, false)); + boolean showStopSigns = CollectionUtil.getBool("showStopSigns", map, true); + //noinspection deprecation + options.showStopSigns(showStopSigns); } if (map.containsKey("showTrafficLights")) { - options.showTrafficLights(CollectionUtil.getBool("showTrafficLights", map, false)); + boolean showTrafficLights = CollectionUtil.getBool("showTrafficLights", map, true); + //noinspection deprecation + options.showTrafficLights(showTrafficLights); } return options; diff --git a/example/android/app/build.gradle b/example/android/app/build.gradle index 127fb07..7781511 100644 --- a/example/android/app/build.gradle +++ b/example/android/app/build.gradle @@ -147,7 +147,7 @@ dependencies { implementation "androidx.car.app:app-projected:1.4.0" // Include the Google Navigation SDK. - implementation 'com.google.android.libraries.navigation:navigation:6.3.1' + implementation 'com.google.android.libraries.navigation:navigation:7.0.0' } secrets { diff --git a/example/src/screens/MultipleMapsScreen.tsx b/example/src/screens/MultipleMapsScreen.tsx index 87d8b2b..fe1d9b6 100644 --- a/example/src/screens/MultipleMapsScreen.tsx +++ b/example/src/screens/MultipleMapsScreen.tsx @@ -84,10 +84,6 @@ const MultipleMapsScreen = () => { console.log('mapViewController1 changed', mapViewController1); }, [mapViewController1]); - const onRouteChanged = useCallback(() => { - showSnackbar('Route Changed'); - }, []); - const onArrival = useCallback( (event: ArrivalEvent) => { if (event.isFinalDestination) { @@ -104,10 +100,6 @@ const MultipleMapsScreen = () => { [navigationController] ); - const onTrafficUpdated = useCallback(() => { - showSnackbar('Traffic Updated'); - }, []); - const onNavigationReady = useCallback(async () => { if (navigationViewController1 != null) { await navigationViewController1.setNavigationUIEnabled(true); @@ -128,38 +120,6 @@ const MultipleMapsScreen = () => { [] ); - const onStartGuidance = useCallback(() => { - showSnackbar('Start Guidance'); - }, []); - - const onRouteStatusOk = useCallback(() => { - showSnackbar('Route created'); - }, []); - - const onRouteCancelled = useCallback(() => { - showSnackbar('Error: Route Cancelled'); - }, []); - - const onNoRouteFound = useCallback(() => { - showSnackbar('Error: No Route Found'); - }, []); - - const onNetworkError = useCallback(() => { - showSnackbar('Error: Network Error'); - }, []); - - const onStartingGuidanceError = useCallback(() => { - showSnackbar('Error: Starting Guidance Error'); - }, []); - - const onLocationDisabled = useCallback(() => { - showSnackbar('Error: Location Disabled'); - }, []); - - const onLocationUnknown = useCallback(() => { - showSnackbar('Error: Location Unknown'); - }, []); - const onLocationChanged = useCallback((location: Location) => { console.log('onLocationChanged: ', location); }, []); @@ -175,66 +135,55 @@ const MultipleMapsScreen = () => { console.log('onRemainingTimeOrDistanceChanged', currentTimeAndDistance); }, [navigationController]); - const onRouteStatusResult = useCallback( - (routeStatus: RouteStatus) => { - switch (routeStatus) { - case RouteStatus.OK: - onRouteStatusOk(); - break; - case RouteStatus.ROUTE_CANCELED: - onRouteCancelled(); - break; - case RouteStatus.NO_ROUTE_FOUND: - onNoRouteFound(); - break; - case RouteStatus.NETWORK_ERROR: - onNetworkError(); - break; - case RouteStatus.LOCATION_DISABLED: - onLocationDisabled(); - break; - case RouteStatus.LOCATION_UNKNOWN: - onLocationUnknown(); - break; - default: - console.log('routeStatus: ' + routeStatus); - onStartingGuidanceError(); - } - }, - [ - onRouteStatusOk, - onRouteCancelled, - onNoRouteFound, - onNetworkError, - onLocationDisabled, - onLocationUnknown, - onStartingGuidanceError, - ] - ); + const onRouteStatusResult = useCallback((routeStatus: RouteStatus) => { + switch (routeStatus) { + case RouteStatus.OK: + showSnackbar('Route created'); + break; + case RouteStatus.ROUTE_CANCELED: + showSnackbar('Error: Route Cancelled'); + break; + case RouteStatus.NO_ROUTE_FOUND: + showSnackbar('Error: No Route Found'); + break; + case RouteStatus.NETWORK_ERROR: + showSnackbar('Error: Network Error'); + break; + case RouteStatus.LOCATION_DISABLED: + showSnackbar('Error: Location Disabled'); + break; + case RouteStatus.LOCATION_UNKNOWN: + showSnackbar('Error: Location Unknown'); + break; + case RouteStatus.DUPLICATE_WAYPOINTS_ERROR: + showSnackbar('Error: Consecutive duplicate waypoints are not allowed'); + break; + default: + console.log('routeStatus: ' + routeStatus); + showSnackbar('Error: Starting Guidance Error'); + } + }, []); const navigationCallbacks: NavigationCallbacks = useMemo( () => ({ - onRouteChanged, + onRouteChanged: () => showSnackbar('Route Changed'), onArrival, onNavigationReady, onNavigationInitError, onLocationChanged, onRawLocationChanged, - onTrafficUpdated, + onTrafficUpdated: () => showSnackbar('Traffic Updated'), onRouteStatusResult, - onStartGuidance, + onStartGuidance: () => showSnackbar('Start Guidance'), onRemainingTimeOrDistanceChanged, }), [ - onRouteChanged, onArrival, onNavigationReady, onNavigationInitError, onLocationChanged, onRawLocationChanged, - onTrafficUpdated, onRouteStatusResult, - onStartGuidance, onRemainingTimeOrDistanceChanged, ] ); @@ -260,17 +209,17 @@ const MultipleMapsScreen = () => { console.log('onRecenterButtonClick'); }, []); - const onShowNavControlsClick = useCallback(() => { + const onShowNavControlsClick = () => { setOverlayType(OverlayType.NavControls); - }, []); + }; - const onShowMapsControlsClick1 = useCallback(() => { + const onShowMapsControlsClick1 = () => { setOverlayType(OverlayType.MapControls1); - }, []); + }; - const onShowMapsControlsClick2 = useCallback(() => { + const onShowMapsControlsClick2 = () => { setOverlayType(OverlayType.MapControls2); - }, []); + }; const navigationViewCallbacks: NavigationViewCallbacks = useMemo( () => ({ diff --git a/example/src/screens/NavigationScreen.tsx b/example/src/screens/NavigationScreen.tsx index aadd062..739aac2 100644 --- a/example/src/screens/NavigationScreen.tsx +++ b/example/src/screens/NavigationScreen.tsx @@ -58,8 +58,6 @@ enum OverlayType { AutoMapControls = 'AutoMapControls', } -const marginAmount = 50; - const NavigationScreen = () => { const { arePermissionsApproved } = usePermissions(); const [overlayType, setOverlayType] = useState(OverlayType.None); @@ -81,12 +79,6 @@ const NavigationScreen = () => { const [navigationInitialized, setNavigationInitialized] = useState(false); - const onRouteChanged = useCallback(() => { - showSnackbar('Route Changed'); - }, []); - - const [margin, setMargin] = useState(null); - const onArrival = useCallback( (event: ArrivalEvent) => { if (event.isFinalDestination) { @@ -103,10 +95,6 @@ const NavigationScreen = () => { [navigationController] ); - const onTrafficUpdated = useCallback(() => { - showSnackbar('Traffic Updated'); - }, []); - const onNavigationReady = useCallback(() => { console.log('onNavigationReady'); setNavigationInitialized(true); @@ -124,38 +112,6 @@ const NavigationScreen = () => { [] ); - const onStartGuidance = useCallback(() => { - showSnackbar('Start Guidance'); - }, []); - - const onRouteStatusOk = useCallback(() => { - showSnackbar('Route created'); - }, []); - - const onRouteCancelled = useCallback(() => { - showSnackbar('Error: Route Cancelled'); - }, []); - - const onNoRouteFound = useCallback(() => { - showSnackbar('Error: No Route Found'); - }, []); - - const onNetworkError = useCallback(() => { - showSnackbar('Error: Network Error'); - }, []); - - const onStartingGuidanceError = useCallback(() => { - showSnackbar('Error: Starting Guidance Error'); - }, []); - - const onLocationDisabled = useCallback(() => { - showSnackbar('Error: Location Disabled'); - }, []); - - const onLocationUnknown = useCallback(() => { - showSnackbar('Error: Location Unknown'); - }, []); - const onLocationChanged = useCallback((location: Location) => { console.log('onLocationChanged:', location); }, []); @@ -177,71 +133,60 @@ const NavigationScreen = () => { console.log('called onRemainingTimeOrDistanceChanged'); }, [navigationController]); - const onPromptVisibilityChanged = useCallback((visible: boolean) => { + const onPromptVisibilityChanged = (visible: boolean) => { console.log('Prompt visibility changed to:', visible); - }, []); + }; - const onRouteStatusResult = useCallback( - (routeStatus: RouteStatus) => { - switch (routeStatus) { - case RouteStatus.OK: - onRouteStatusOk(); - break; - case RouteStatus.ROUTE_CANCELED: - onRouteCancelled(); - break; - case RouteStatus.NO_ROUTE_FOUND: - onNoRouteFound(); - break; - case RouteStatus.NETWORK_ERROR: - onNetworkError(); - break; - case RouteStatus.LOCATION_DISABLED: - onLocationDisabled(); - break; - case RouteStatus.LOCATION_UNKNOWN: - onLocationUnknown(); - break; - default: - console.log('routeStatus: ' + routeStatus); - onStartingGuidanceError(); - } - }, - [ - onRouteStatusOk, - onRouteCancelled, - onNoRouteFound, - onNetworkError, - onLocationDisabled, - onLocationUnknown, - onStartingGuidanceError, - ] - ); + const onRouteStatusResult = useCallback((routeStatus: RouteStatus) => { + switch (routeStatus) { + case RouteStatus.OK: + showSnackbar('Route created'); + break; + case RouteStatus.ROUTE_CANCELED: + showSnackbar('Error: Route Cancelled'); + break; + case RouteStatus.NO_ROUTE_FOUND: + showSnackbar('Error: No Route Found'); + break; + case RouteStatus.NETWORK_ERROR: + showSnackbar('Error: Network Error'); + break; + case RouteStatus.LOCATION_DISABLED: + showSnackbar('Error: Location Disabled'); + break; + case RouteStatus.LOCATION_UNKNOWN: + showSnackbar('Error: Location Unknown'); + break; + case RouteStatus.DUPLICATE_WAYPOINTS_ERROR: + showSnackbar('Error: Consecutive duplicate waypoints are not allowed'); + break; + default: + console.log('routeStatus: ' + routeStatus); + showSnackbar('Error: Starting Guidance Error'); + } + }, []); const navigationCallbacks: NavigationCallbacks = useMemo( () => ({ - onRouteChanged, + onRouteChanged: () => showSnackbar('Route Changed'), onArrival, onNavigationReady, onNavigationInitError, onLocationChanged, onRawLocationChanged, - onTrafficUpdated, + onTrafficUpdated: () => showSnackbar('Traffic Updated'), onRouteStatusResult, - onStartGuidance, + onStartGuidance: () => showSnackbar('Start Guidance'), onRemainingTimeOrDistanceChanged, onTurnByTurn, }), [ - onRouteChanged, onArrival, onNavigationReady, onNavigationInitError, onLocationChanged, onRawLocationChanged, - onTrafficUpdated, onRouteStatusResult, - onStartGuidance, onRemainingTimeOrDistanceChanged, onTurnByTurn, ] @@ -291,9 +236,9 @@ const NavigationScreen = () => { } }, [navigationController]); - const onRecenterButtonClick = useCallback(() => { + const onRecenterButtonClick = () => { console.log('onRecenterButtonClick'); - }, []); + }; const onShowNavControlsClick = useCallback(() => { setOverlayType(OverlayType.NavControls); @@ -350,10 +295,7 @@ const NavigationScreen = () => { return arePermissionsApproved ? ( { {mapViewAutoAvailable && (