-
Notifications
You must be signed in to change notification settings - Fork 21
Description
Is there an existing issue for this?
- I have searched the existing issues
Description of the bug
the navigation view works fine on Andorid
But in Ios it's not working correctly sometimes it starts navigation, but most of the time it's not working correctly I just getting the black map and also it's not detecting the device location internally
mapViewController.getMyLocation() return undefined even though I have given permission
React Native version
0.74.1
React version
18.2.0
Package version
0.9.3
Native SDK versions
- I haven't changed the version of the native SDKs
React Native Doctor Output
WARNING: You should run npx react-native@latest to ensure you're always using the most current version of the CLI. NPX has cached version (0.74.1) != current release (0.79.2)
warn Package rn-fetch-blob contains invalid configuration: "dependency.hooks" is not allowed. Please verify it's properly linked using "npx react-native config" command and contact the package maintainers about this.
⠙ Running diagnostics...warn Package rn-fetch-blob contains invalid configuration: "dependency.hooks" is not allowed. Please verify it's properly linked using "npx react-native config" command and contact the package maintainers about this.
Common
✓ Node.js - Required to execute JavaScript code
✓ yarn - 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 - Required to verify if the android device is attached correctly
✓ 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: N/A
- Version supported: 34.0.0
iOS
✓ Xcode - Required for building and installing your app on iOS
✓ Ruby - Required for installing iOS dependencies
✓ CocoaPods - Required for installing iOS dependencies
● ios-deploy - Required for installing your app on a physical device with the CLI
✓ .xcode.env - File to customize Xcode environment
Errors: 1
Warnings: 2
Steps to reproduce
Expected vs Actual Behavior
The navigation should start in IOS, but it's not working
Code Sample
import React, {useState, useEffect, useCallback, useMemo} from 'react';
import {
Alert,
BackHandler,
Platform,
StatusBar,
StyleSheet,
Text,
TouchableOpacity,
View,
} from 'react-native';
import Snackbar from 'react-native-snackbar';
import MaterialIcons from 'react-native-vector-icons/MaterialIcons';
import {calculateDistanceTraveled} from '../../utils/misc';
import {strings} from '../../utils/strings';
import {
NavigationView,
useNavigation,
RouteStatus,
type ArrivalEvent,
type Location,
type NavigationViewController,
type MapViewController,
MapViewCallbacks,
NavigationViewCallbacks,
TravelMode,
NavigationCallbacks,
MapType,
} from '@googlemaps/react-native-navigation-sdk';
import usePermissions from './helpers/checkPermission';
import DirectionPanel from './DirectionPanel';
import MapBottomSheet from './MapBottomSheet';
import {useFocusEffect} from '@react-navigation/native';
import {stat} from 'react-native-fs';
// Utility function for showing Snackbar
const showSnackbar = (text: string, duration = Snackbar.LENGTH_SHORT) => {
Snackbar.show({text, duration});
};
export const GoogleNavigationView = ({
navigation,
setDirectionRouteDetails,
origin,
currentLocation,
setScreenData,
imageAnnotations,
handleSubmit,
setTraveledPath,
setArrived,
arrived,
handleErrorRefresh,
}: any) => {
const {arePermissionsApproved} = usePermissions();
const {navigationController, addListeners, removeListeners} = useNavigation();
const [navigationViewController, setNavigationViewController] =
useState<NavigationViewController | null>(null);
const [mapViewController, setMapViewController] =
useState<MapViewController | null>(null);
const [navigationInitialized, setNavigationInitialized] = useState(false);
const [showMapControls, setShowMapControls] = useState(false);
const [isTrafficEnabled, setIsTrafficEnabled] = useState(true);
const [directionSteps, setDirectionSteps] = useState([]);
const [isSatelliteMode, setIsSatelliteMode] = useState(false);
const [showDirections, setShowDirections] = useState(false);
const getDirections = async () => {
const startOrigin = `${origin[1]},${origin[0]}`;
const destination = `${currentLocation[1]},${currentLocation[0]}`;
const response = await fetch(
`https://maps.googleapis.com/maps/api/directions/json?origin=${startOrigin}&destination=${destination}&key=${key}`,
);
const data = await response.json();
console.log('Directions data:', data);
console.log('data.routes[0].legs[0].steps', data.routes[0].legs[0].steps);
const steps = data.routes[0]?.legs[0]?.steps || [];
setDirectionSteps(steps);
};
const onRecenterButtonClick = useCallback(() => {
console.log('onRecenterButtonClick');
}, []);
const navigationViewCallbacks: NavigationViewCallbacks = {
onRecenterButtonClick,
};
console.log('oringin ', origin);
console.log('currentLocation ', currentLocation);
// 🔴 Android Back Button Handling
useEffect(() => {
const backAction = () => {
Alert.alert('Hold on!', 'Are you sure you want to go back?', [
{text: 'Cancel', onPress: () => null, style: 'cancel'},
{
text: 'YES',
onPress: () => {
navigationController.stopGuidance();
navigationController.clearDestinations();
navigationController.cleanup();
navigation.replace(strings.MAP);
},
},
]);
return true;
};
const backHandler = BackHandler.addEventListener(
'hardwareBackPress',
backAction,
);
return () => {
// On screen unmount or back navigation
if (navigationController) {
navigationController.stopGuidance();
navigationController.clearDestinations();
navigationController.cleanup();
}
backHandler.remove();
};
}, []);
// 🏁 Handle Arrival
const onArrival = useCallback(
(event: ArrivalEvent) => {
if (!arrived) {
setArrived(true);
Snackbar.show({
text: 'Arrived at Destination',
duration: Snackbar.LENGTH_SHORT,
});
navigationController.stopGuidance();
navigationController.clearDestinations();
navigationController.cleanup();
setTimeout(() => handleSubmit(), 1000);
}
},
[arrived, handleSubmit, setArrived],
);
// 🚦 Route Progress Updates
const onRemainingTimeOrDistanceChanged = useCallback(async () => {
const progress = await navigationController.getCurrentTimeAndDistance();
const LatLong = await navigationController.getTraveledPath();
setTraveledPath(LatLong);
console.log('LatLong : ', LatLong);
console.log('progress : ', progress);
const distanceInMeters = calculateDistanceTraveled(LatLong);
console.log('Distance in Meters: ', distanceInMeters);
console.log(
`🚗 Distance Traveled: ${(distanceInMeters / 1000).toFixed(2)} km`,
);
setDirectionRouteDetails({
distanceRemaining: progress.meters,
distanceTraveled: distanceInMeters,
durationRemaining: progress.seconds,
});
}, [navigationController]);
// ❌ Handle Navigation Errors
const onNavigationInitError = (errorCode: any) => {
Alert.alert('Navigation Init Error', `Error Code: ${errorCode}`);
};
const onRouteStatusResult = (status: RouteStatus) => {
if (status !== RouteStatus.OK) {
Alert.alert('Route Error', `Status: ${status}`);
}
};
const onNavigationReady = useCallback(async () => {
console.log('onNavigationReady');
if (mapViewController) {
const loc = await mapViewController.getMyLocation();
console.log('Fardeen - My location:', loc);
}
setNavigationInitialized(true);
}, [mapViewController]);
// 🎯 Register Callbacks
const navigationCallbacks: NavigationCallbacks = useMemo(
() => ({
onArrival,
onRemainingTimeOrDistanceChanged,
onNavigationReady,
onNavigationInitError,
onRouteStatusResult,
}),
[onArrival, onRemainingTimeOrDistanceChanged],
);
useFocusEffect(
useCallback(() => {
addListeners(navigationCallbacks);
return () => {
removeListeners(navigationCallbacks);
};
}, [navigationCallbacks, addListeners, removeListeners]),
);
const onMapReady = useCallback(async () => {
console.log('Map is ready, initializing navigator...');
try {
mapViewController?.setMyLocationButtonEnabled(true);
mapViewController?.setMyLocationEnabled(true);
mapViewController?.setZoomControlsEnabled(true);
const isLocation = await mapViewController?.isMyLocationEnabled();
console.log('isLocation : ', isLocation);
await navigationController.init();
getDirections();
} catch (error) {
console.error('Error initializing navigator', error);
showSnackbar('Error initializing navigator');
}
}, [navigationController]);
const mapViewCallbacks: MapViewCallbacks = useMemo(() => {
return {
onMapReady,
};
}, [mapViewController, onMapReady]);
const startNavigation = useCallback(async () => {
try {
if (!origin || !currentLocation) {
console.log('Origin or destination not set yet.');
return;
}
const waypoint2 = {
title: 'From',
position: {
lat: origin[1], // Latitude
lng: origin[0], // Longitude
},
};
const waypoint = {
title: 'Destination',
position: {
lat: currentLocation[1], // Latitude
lng: currentLocation[0], // Longitude
},
};
const routingOptions = {
travelMode: TravelMode.TWO_WHEELER, // TravelMode.TWO_WHEELER
avoidFerries: false,
avoidTolls: false,
};
const displayOptions = {
showDestinationMarkers: true,
showStopSigns: true,
showTrafficLights: true,
};
await navigationController.setDestinations(
[waypoint],
routingOptions,
displayOptions,
);
await navigationController.startGuidance();
console.log('Navigation started successfully!');
} catch (error) {
console.error('Error starting navigation', error);
}
}, [navigationController, origin, currentLocation]);
// 🚀 Start navigation when initialized
useEffect(() => {
if (navigationInitialized) {
startNavigation();
}
}, [navigationInitialized, startNavigation]);
const setMapType = (isSatellite: boolean) => {
if (!isSatellite) {
console.log('Setting map type to NORMAL');
mapViewController?.setMapType(MapType.NORMAL);
} else {
console.log('Setting map type to SATELLITE');
mapViewController?.setMapType(MapType.SATELLITE);
}
};
console.log('isSatelliteMode', isSatelliteMode);
return (
<View style={styles.container}>
<StatusBar barStyle={'light-content'} />
<NavigationView
style={{flex: 1}}
androidStylingOptions={{
primaryDayModeThemeColor: '#34eba8',
headerDistanceValueTextColor: '#76b5c5',
headerInstructionsFirstRowTextSize: '20f',
}}
iOSStylingOptions={{
navigationHeaderPrimaryBackgroundColor: '#34eba8',
navigationHeaderDistanceValueTextColor: '#76b5c5',
}}
navigationViewCallbacks={navigationViewCallbacks}
mapViewCallbacks={mapViewCallbacks}
onNavigationViewControllerCreated={setNavigationViewController}
onMapViewControllerCreated={setMapViewController} // Added MapViewController
/>
<TouchableOpacity
style={styles.directionButton}
onPress={() => setShowDirections(!showDirections)}>
<MaterialIcons
name={showDirections ? 'cancel' : 'directions'}
size={30}
color="#fff"
/>
</TouchableOpacity>
<TouchableOpacity
style={styles.stopNavigation}
onPress={() => {
setScreenData(4);
setShowDirections(false);
}}>
<MaterialIcons name={'cancel'} size={30} color="#fff" />
</TouchableOpacity>
{showDirections && (
<MapBottomSheet
steps={directionSteps}
isSatellite={isSatelliteMode}
onToggleSatellite={val => {
setMapType(val);
setIsSatelliteMode(val);
}}
/>
)}
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
},
floatingButton: {
position: 'absolute',
bottom: 200,
right: 20,
backgroundColor: '#1E90FF',
paddingVertical: 12,
paddingHorizontal: 20,
borderRadius: 25,
elevation: 5,
zIndex: 1000,
},
buttonText: {
color: '#fff',
fontWeight: 'bold',
},
directionButton: {
backgroundColor: '#007AFF',
justifyContent: 'center',
alignItems: 'center',
borderRadius: 25,
height: 40,
width: 40,
position: 'absolute',
bottom: 200,
right: 20,
},
stopNavigation: {
backgroundColor: '#007AFF',
justifyContent: 'center',
alignItems: 'center',
borderRadius: 25,
height: 40,
width: 40,
position: 'absolute',
bottom: 260,
right: 20,
},
});
export default GoogleNavigationView;Additional Context
Many Time The Roue Navigation not started in Ios

