Navigation
expo-gaode-map-navigation is a standalone navigation module that integrates map display and navigation capabilities, providing route planning and real-time navigation features.
Features
- ✅ Integrated Map: Built-in map display, no need for separate core package
- ✅ Route Planning: Supports driving, walking, cycling, and transit routes
- ✅ Real-time Navigation: Turn-by-turn voice guidance and route display
- ✅ Independent Service: Route planning without map display
- ✅ Multi-strategy: Supports various route planning strategies
Important Notes
Binary Conflict
The navigation package conflicts with the core map package (expo-gaode-map) and cannot be used together. Choose one based on your needs:
- Use
expo-gaode-map-navigationif you need navigation features - Use
expo-gaode-mapif you only need map display
Installation
npm install expo-gaode-map-navigationQuick Start
1. Configure Plugin
Add to app.json:
{
"expo": {
"plugins": [
[
"expo-gaode-map-navigation",
{
"androidKey": "your-android-key",
"iosKey": "your-ios-key"
}
]
]
}
}2. Initialize SDK
import { ExpoGaodeMapModule } from 'expo-gaode-map-navigation';
if (!ExpoGaodeMapModule.getPrivacyStatus().isReady) {
ExpoGaodeMapModule.setPrivacyConfig({
hasShow: true,
hasContainsPrivacy: true,
hasAgree: true,
});
}
// If native keys are configured via Config Plugin or manually, and you only use
// map/navigation features, you can skip initSDK.
// Only needed for Web API features:
ExpoGaodeMapModule.initSDK({ webKey: 'your-web-api-key' });
// Only if native keys are not configured:
// ExpoGaodeMapModule.initSDK({
// androidKey: 'your-android-key',
// iosKey: 'your-ios-key',
// webKey: 'your-web-api-key', // optional unless using Web API
// });Built-in Map Features
The navigation package includes its own MapView and overlay implementation. The API shape stays aligned with the core package, but the underlying map stack comes from the navigation SDK, so it does not depend on expo-gaode-map.
Import map components
import { useRef } from 'react';
import {
MapView,
Marker,
Cluster,
type MapViewRef,
} from 'expo-gaode-map-navigation';Camera control and event throttling
moveCamera(position, duration?)now usesCameraUpdatecameraEventThrottleMs?: numbercontrols nativeonCameraMovefrequency- Default is
32; pass0to disable throttling
const mapRef = useRef<MapViewRef | null>(null);
await mapRef.current?.moveCamera(
{
target: { latitude: 39.9, longitude: 116.4 },
zoom: 14,
},
300
);Custom Marker / Cluster
Markercustomchildrenare measured automatically from layoutClusternow supportsicon?: stringwith HTTP URL, local file path, or bundle resource name
fitToCoordinates
MapViewRef in the navigation package also exposes fitToCoordinates(points, options?) to auto-fit a point set in the current viewport.
await mapRef.current?.fitToCoordinates(routePoints, {
duration: 500,
paddingFactor: 0.2,
maxZoom: 18,
});calculateFitZoom
The built-in ExpoGaodeMapModule in the navigation package also supports calculateFitZoom(points, options?), useful when you want to pre-compute zoom before calling moveCamera.
import { ExpoGaodeMapModule } from 'expo-gaode-map-navigation';
const points = [
{ latitude: 39.9042, longitude: 116.4074 },
{ latitude: 39.91407, longitude: 116.39765 },
{ latitude: 39.92541, longitude: 116.39707 },
];
const zoom = ExpoGaodeMapModule.calculateFitZoom(points, {
viewportWidthPx: 390,
viewportHeightPx: 844,
paddingPx: 48,
minZoom: 3,
maxZoom: 20,
});
await mapRef.current?.moveCamera(
{
target: points[0],
zoom,
},
300
);3. Use Map Component
import { MapView } from 'expo-gaode-map-navigation';
<MapView
style={{ flex: 1 }}
initialCameraPosition={{
target: { latitude: 39.9042, longitude: 116.4074 },
zoom: 10,
}}
/>Route Planning
Independent Route Service
Plan routes without displaying a map:
import {
ExpoGaodeMapNavigationModule,
DrivingStrategy
} from 'expo-gaode-map-navigation';
// Driving route
const result = await ExpoGaodeMapNavigationModule.calculateDriveRoute({
from: { latitude: 39.9042, longitude: 116.4074 },
to: { latitude: 39.9, longitude: 116.3 },
waypoints: [
{ latitude: 39.91, longitude: 116.35 }
],
strategy: DrivingStrategy.AVOID_CONGESTION,
});
console.log(`Distance: ${result.distance}m`);
console.log(`Duration: ${result.duration}s`);
console.log(`Toll: ${result.tolls}元`);
// Walking route
const walkResult = await ExpoGaodeMapNavigationModule.calculateWalkRoute({
from: { latitude: 39.9042, longitude: 116.4074 },
to: { latitude: 39.9, longitude: 116.3 },
});
// Cycling route
const bikeResult = await ExpoGaodeMapNavigationModule.calculateBikeRoute({
from: { latitude: 39.9042, longitude: 116.4074 },
to: { latitude: 39.9, longitude: 116.3 },
});Navigation View
Display navigation interface with real-time guidance:
import { ExpoGaodeMapNaviView } from 'expo-gaode-map-navigation';
<ExpoGaodeMapNaviView
style={{ flex: 1 }}
startPoint={{ latitude: 39.9042, longitude: 116.4074 }}
endPoint={{ latitude: 39.9, longitude: 116.3 }}
waypoints={[
{ latitude: 39.91, longitude: 116.35 }
]}
strategy={DrivingStrategy.AVOID_CONGESTION}
onCalculateRouteSuccess={(event) => {
console.log('Route calculated:', event.nativeEvent);
}}
onCalculateRouteFailure={(event) => {
console.error('Route failed:', event.nativeEvent);
}}
/>Custom annotation icons are now exposed as image props:
carImage: custom ego vehicle icon on both iOS and AndroidcarImageSize: custom ego vehicle icon size on both iOS and Android ({ width, height }in RN logical pixels)startPointImage/wayPointImage/endPointImage: custom route marker icons on both iOS and AndroidfourCornersImage: Android-only four-corners direction bitmapcarCompassImage: iOS-only ego compass imagecameraImage: iOS-only camera icon
These props accept either a string URI/resource name or a React Native asset source such as require(...).
Custom Embedded Navigation UI
For embedded navigation screens inside your own React Native page, the package now exposes the low-level ExpoGaodeMapNaviView, events, and native props only. The full custom HUD / lane HUD / traffic bar reference implementation has been moved into the repo's example-navigation app under example-navigation/lib/navigation-ui/*.
Recommended approach:
- Use
ExpoGaodeMapNaviViewfor the native navigation map, guidance, lane events, traffic-status events, and cross-image events - Render your own HUD from
onNaviInfoUpdate,onLaneInfoUpdate,onTrafficStatusesUpdate, andonNaviVisualStateChange - Start from the
example-navigation"Custom Navigation UI" example and trim it to your product needs - If you need route picking plus start/end/multi-waypoint input, start from the
route-pickerexample insideexample-navigation
Android embedded note:
- In some React Native / Expo hosts, the official embedded
ExpoGaodeMapNaviViewtop info panel, lane information, and cross-image transitions may differ from the official AMap demo / official black-box page - On Android, the pure official embedded UI is more likely to show incomplete top panels, overlay glitches, or inconsistent styling across hosts/devices; treat it as a boundary-check page rather than a production UI baseline
- If your goal is a stable embedded navigation page, start from the custom UI example in
example-navigation - If you specifically want to verify the native official embedded UI, use the
official-embeddedpage in the repo's example app
Driving Strategies
| Strategy | Description |
|---|---|
DrivingStrategy.DEFAULT (0) | Default, recommended by Gaode |
DrivingStrategy.AVOID_CONGESTION (1) | Avoid traffic jams |
DrivingStrategy.AVOID_HIGHWAY (2) | Avoid highways |
DrivingStrategy.AVOID_TOLL (3) | Avoid tolls |
DrivingStrategy.HIGHWAY_PRIORITY (4) | Prefer highways |
DrivingStrategy.LESS_TOLL (5) | Minimize tolls |
DrivingStrategy.DISTANCE_PRIORITY (6) | Shortest distance |
DrivingStrategy.TIME_PRIORITY (9) | Shortest time |
Android Considerations
Strategy Mapping
Android uses the navi-3dmap SDK with different strategy values. The module automatically maps them:
| Exposed Strategy | Android Value | Description |
|---|---|---|
DEFAULT (0) | 0 | Default |
AVOID_CONGESTION (1) | 4 | Avoid congestion |
AVOID_HIGHWAY (2) | 3 | Avoid highways |
AVOID_TOLL (3) | 1 | Avoid tolls |
HIGHWAY_PRIORITY (4) | 6 | Highway priority |
LESS_TOLL (5) | 2 | Less toll |
DISTANCE_PRIORITY (6) | 5 | Distance priority |
TIME_PRIORITY (9) | 10 | Time priority |
Multi-strategy Support
Android supports combining multiple strategies:
// Avoid highways + avoid tolls
const result = await ExpoGaodeMapNavigationModule.calculateDriveRoute({
from: { latitude: 39.9042, longitude: 116.4074 },
to: { latitude: 39.9, longitude: 116.3 },
strategy: DrivingStrategy.AVOID_HIGHWAY | DrivingStrategy.AVOID_TOLL,
});API Reference
Route Planning Methods
calculateDriveRoute()- Calculate driving routecalculateWalkRoute()- Calculate walking routecalculateBikeRoute()- Calculate cycling route
Navigation View Props
startPoint- Start coordinateendPoint- End coordinatewaypoints- Waypoint array (optional)strategy- Route planning strategycarImageSize- Custom ego vehicle icon size ({ width, height })iosLiveActivityEnabled- Enables iOS Live Activity state updates (requires Widget Extension configuration)mapViewModeType- Cross-platform map mode (0day,1night,2auto,3custom; Android falls back to day when custom style path is unavailable)isNightMode- Legacy compatibility prop (true/falsemaps tomapViewModeType1/0;mapViewModeTypetakes precedence)onCalculateRouteSuccess- Route calculation success callbackonCalculateRouteFailure- Route calculation failure callbacknaviStatusBarEnabled- Android only; enables the official AMap navigation status bar when the underlying AMap SDK exposes that API
iOS Live Activity Notes
- With
iosLiveActivityEnabled, lock screen / Dynamic Island is updated from navigation snapshots. - On destination arrival, the module updates the card to an "Arrived" state first, then auto-dismisses it after about 6 seconds.
- If Xcode prints
[api] Error updating activity content: Payload maximum size exceeded.:- the module now degrades payload automatically (keep turn icon first, trim text first),
- and only drops the turn icon as a last fallback.
- Useful diagnostics:
payload ... keeping turn iconpayload still too large ... dropped turn iconarrived destination card displayed for ... stopping activity
Custom UI Reference
The package no longer exports a ready-made EmbeddedNaviView. Instead, the example app contains a reference implementation you can reuse:
example-navigation/lib/navigation-ui/EmbeddedNaviView.tsxexample-navigation/lib/navigation-ui/EmbeddedNaviHud.tsxexample-navigation/lib/navigation-ui/EmbeddedNaviLaneView.tsxexample-navigation/lib/navigation-ui/EmbeddedNaviTrafficBar.tsxexample-navigation/app/examples/ui-props.tsxexample-navigation/app/examples/route-picker.tsxexample-navigation/app/examples/official-embedded.tsx
That example demonstrates:
- full custom mode with
showUIElements={false} - embedded-friendly
driveViewEdgePadding/screenAnchorhandling - a top HUD rendered from
onNaviInfoUpdate - a custom lane HUD rendered from
onLaneInfoUpdate - a custom traffic bar rendered from
onTrafficStatusesUpdate - floating overview/lock and traffic toggle controls
Map Component
The navigation package includes all map component features. See Map View API for details.
Android SDK Compatibility
naviStatusBarEnableddepends on Android AMap SDK versions that exposeAMapNaviViewOptions.setNaviStatusBarEnabled(...).- The module now applies this setting compatibly.
- If the resolved AMap SDK in the host app does not provide that method, the module no longer fails compilation.
- In that case, Android skips the setting at runtime and logs a warning, so
naviStatusBarEnabledbehaves as a no-op. - If you need this prop to actually take effect on Android, upgrade the host app's AMap navigation SDK to a version that includes the API.
Related Documentation
- Map View API - Map display features
- Search API - Native search module
- Web API - Web API services