Skip to content

[Bug]: (int) prefrerredHeading case #654

Description

@spendres

Is there an existing issue for this?

  • I have searched the existing issues

Description of the bug

Repo: https://github.com/googlemaps/react-native-navigation-sdk/issues/new

Title: Android: setDestinations throws ClassCastException when a waypoint sets preferredHeading (Double cast to Integer)

Environment

  • @googlemaps/react-native-navigation-sdk 0.16.3 (the cast is unchanged on main at 036c83e, 2026-09-07)
  • React Native 0.86, Expo SDK 57, new architecture
  • Android (Samsung, Android 15); iOS is unaffected

Steps

await navigationController.setDestinations(
  [
    { title: 'Entry', position: { lat: 42.27853, lng: -83.67608 }, preferredHeading: 0 },
    { title: 'Destination', position: { lat: 42.32438, lng: -83.62626 } },
  ],
  { routingOptions: { travelMode: TravelMode.DRIVING } },
);

Expected

The route is computed with the heading preference applied to the first waypoint (as on iOS).

Actual

The promise rejects before the SDK is called:

Exception in HostFunction: java.lang.Double cannot be cast to java.lang.Integer
  at com.google.android.react.navsdk.NavModule.createWaypoint(NavModule.java:571)
  at com.google.android.react.navsdk.NavModule.setDestinations(NavModule.java:604)

Cause

NavModule.createWaypoint casts the raw map value:

if (map.containsKey("preferredHeading")) {
  int preferredHeading = (int) map.get("preferredHeading");   // line 571
  waypointBuilder.setPreferredHeading(preferredHeading);
}

Every JS number crosses the bridge as a java.lang.Double, so the (int) cast throws. The same file already handles this correctly two lines earlier for travelMode via CollectionUtil.getInt, which does ((Double) map.get(name)).intValue().

Fix (one line)

if (map.containsKey("preferredHeading")) {
  int preferredHeading = CollectionUtil.getInt("preferredHeading", map, 0);
  waypointBuilder.setPreferredHeading(preferredHeading);
}

Happy to open a PR if that is welcome.

Workaround

Omit preferredHeading on Android (Platform.OS === 'android'), which loses the side-of-road hint there.

iOS Platform

Not affected

Android Platform

Affected

React Native version

0.86.2

React version

19.2.3

Package version

wrapper 0.16.3 with its stock native pins, Navigation SDK for iOS 10.13.0 and for Android 7.6.1.

Native SDK versions

  • I haven't changed the version of the native SDKs

React Native Doctor Output

Common
✓ Node.js - Required to execute JavaScript code
✓ yarn - Required to install NPM dependencies
✓ npm - Required to install NPM dependencies
● Watchman - Used for watching changes in the filesystem when in development mode
● Metro - Metro Bundler is not running

Android
✖ Adb - No devices and/or emulators connected. Please create emulator with Android Studio or connect Android device.
✓ JDK - Required to compile Java code
✓ Android Studio - Required for building and installing your app on Android
✓ ANDROID_HOME - Environment variable that points to your Android SDK installation
✖ Gradlew - Build tool required for Android builds
✖ Android SDK - Required for building and installing your app on Android

  • Versions found: 30.0.3, 33.0.2, 34.0.0, 34.0.0, 35.0.0, 36.0.0
  • Version supported: Not Found

iOS
✓ Xcode - Required for building and installing your app on iOS
✓ Ruby
✖ CocoaPods - Required for installing iOS dependencies

  • Version found: N/A
  • Version supported: >= 1.10.0
    ✓ .xcode.env - File to customize Xcode environment

Errors: 4
Warnings: 2

Expo SDK 57 managed project, native builds on EAS; no local android/ or ios/ checkout, hence Gradlew and CocoaPods missing and no supported SDK version detected. The Samsung device was disconnected when this ran.

Steps to reproduce

  1. Install @googlemaps/react-native-navigation-sdk 0.16.3 in a React Native 0.86 app (new architecture) and run it on an Android device. iOS is not needed; it is unaffected.
  2. Initialize navigation as usual: NavigationView mounted, terms accepted, navigationController.init() returned OK, and a location fix has arrived.
  3. Call setDestinations with any waypoint that sets preferredHeading, for example:
    await navigationController.setDestinations(
    [
    { title: 'Entry', position: { lat: 42.27853, lng: -83.67608 }, preferredHeading: 0 },
    { title: 'Destination', position: { lat: 42.32438, lng: -83.62626 } },
    ],
    { routingOptions: { travelMode: TravelMode.DRIVING } },
    );
  4. Observe: the promise rejects immediately, before the native SDK computes a route:
    Exception in HostFunction: java.lang.Double cannot be cast to java.lang.Integer
    at com.google.android.react.navsdk.NavModule.createWaypoint(NavModule.java:571)
    at com.google.android.react.navsdk.NavModule.setDestinations(NavModule.java:604)
    Any value reproduces it, including 0, 12, and 12.0, because the JS number always arrives as a java.lang.Double.
  5. Remove preferredHeading from the waypoint and call again: the route is computed and guidance starts. The same waypoint with preferredHeading works on iOS.

Expected vs Actual Behavior

The route is computed with the heading preference applied to the first waypoint (as on iOS).

Code Sample

if (map.containsKey("preferredHeading")) {
  int preferredHeading = CollectionUtil.getInt("preferredHeading", map, 0);
  waypointBuilder.setPreferredHeading(preferredHeading);
}

Additional Context

No response

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

priority: p2Moderately-important priority. Fix may not be included in next release.type: bugError or flaw in code with unintended results or allowing sub-optimal usage patterns.

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions