@amrshbib/react-native-geolocation
v2.0.1
Published
React Native geolocation package with FusedLocationProviderClient for high accuracy location tracking
Maintainers
Readme
React Native Geolocation
A high-performance React Native geolocation library with advanced location tracking capabilities using Google's FusedLocationProviderClient for Android and CoreLocation for iOS.
✨ Features
- 🚀 Cross-Platform: Full support for both Android and iOS
- 📍 High Accuracy Location: Uses Google's FusedLocationProviderClient on Android
- 🔄 Background Location: Continuous location tracking in background
- 🛡️ Smart Permissions: Automatic permission request dialogs with user guidance
- 🎯 Multiple Providers: GPS, Network, Passive, and Bluetooth-based location
- ⚡ Real-time Watching: Continuous location updates with configurable intervals
- 📝 TypeScript: Complete TypeScript support with type definitions
- 🔗 Auto-linking: Zero configuration setup for React Native 0.60+
- 📱 Easy API: Simple getCurrentLocation/watchLocation methods
- 🔧 Permission Management: Check and request permissions programmatically
📦 Installation
npm install @amrshbib/react-native-geolocation
# or
yarn add @amrshbib/react-native-geolocationNote: This package is currently in version 0.0.1 and ready for use. The package supports both Android and iOS platforms with comprehensive geolocation capabilities.
React Native 0.60+
This package supports auto-linking. No additional configuration is required.
React Native < 0.60
For older React Native versions, you'll need to manually link the package:
react-native link @amrshbib/react-native-geolocation🚀 Quick Start
import Geolocation from "@amrshbib/react-native-geolocation";
// Get current location
const getCurrentLocation = async () => {
try {
const location = await Geolocation.getCurrentLocation({
enableHighAccuracy: true,
timeout: 15000,
priority: "high_accuracy",
});
console.log("Location:", location);
// {
// latitude: 37.7749,
// longitude: -122.4194,
// altitude: 10.5,
// accuracy: 5.0,
// heading: 45.0,
// speed: 2.5,
// timestamp: 1640995200000,
// provider: "gps",
// fromMockProvider: false,
// coords: { ... }
// }
} catch (error) {
console.error("Error getting location:", error);
}
};
// Watch location changes
const watchLocation = async () => {
try {
const watchId = await Geolocation.watchLocation(
(location, error) => {
if (error) {
console.error("Location error:", error);
} else {
console.log("Location update:", location);
}
},
{
enableHighAccuracy: true,
interval: 1000,
priority: "high_accuracy",
}
);
// Stop watching after 30 seconds
setTimeout(() => {
Geolocation.stopWatching(watchId);
}, 30000);
} catch (error) {
console.error("Error watching location:", error);
}
};
// Check permissions
const checkPermissions = async () => {
const permissions = await Geolocation.checkPermissions();
console.log("Fine location:", permissions.fine);
console.log("Background location:", permissions.background);
};
// Request permissions
const requestPermissions = async () => {
const permissions = await Geolocation.requestPermissions();
if (permissions.fine) {
console.log("Location permission granted!");
}
};📖 API Reference
Geolocation.getCurrentLocation(options)
Get the current location once.
Parameters:
options(Object, optional):enableHighAccuracy(boolean): Use high accuracy mode (default: true)timeout(number): Timeout in milliseconds (default: 15000)maximumAge(number): Maximum age of cached location in milliseconds (default: 10000)priority(string): Location priority - 'high_accuracy', 'balanced_power_accuracy', 'low_power', 'no_power' (default: 'high_accuracy')interval(number): Update interval in milliseconds (default: 1000)fastestInterval(number): Fastest update interval in milliseconds (default: 1000)smallestDisplacement(number): Minimum displacement for updates in meters (default: 0)
Returns: Promise<LocationData> - Resolves with location data
Example:
const location = await Geolocation.getCurrentLocation({
enableHighAccuracy: true,
timeout: 10000,
priority: "high_accuracy",
});Geolocation.watchLocation(callback, options)
Watch for location changes continuously.
Parameters:
callback(Function): Function called with (location, error)location: LocationData object or nullerror: Error string or null
options(Object, optional): Same as getCurrentLocation
Returns: Promise<number> - Resolves with watchId
Example:
const watchId = await Geolocation.watchLocation(
(location, error) => {
if (error) {
console.error("Location error:", error);
} else {
console.log("New location:", location);
}
},
{
enableHighAccuracy: true,
interval: 2000,
smallestDisplacement: 5,
}
);Geolocation.stopWatching(watchId)
Stop watching location changes.
Parameters:
watchId(number): The watch ID returned by watchLocation
Returns: Promise<void> - Resolves when watching stops
Example:
await Geolocation.stopWatching(watchId);Geolocation.checkPermissions()
Check current permission status.
Returns: Promise<{fine: boolean, background: boolean}> - Permission status
Example:
const permissions = await Geolocation.checkPermissions();
console.log("Fine location:", permissions.fine);
console.log("Background location:", permissions.background);Geolocation.requestPermissions()
Request location permissions from the user.
Returns: Promise<{fine: boolean, background: boolean}> - Permission status after request
Example:
const permissions = await Geolocation.requestPermissions();
if (permissions.fine) {
console.log("Location permission granted!");
}Geolocation.isLocationEnabled()
Check if location services are enabled on the device.
Returns: Promise<boolean> - True if location services are enabled
Example:
const enabled = await Geolocation.isLocationEnabled();
if (!enabled) {
Alert.alert("Location Services", "Please enable location services in settings");
}🔧 Platform-Specific Setup
Android Setup
The package automatically handles Android configuration, but you need to add location permissions to your android/app/src/main/AndroidManifest.xml:
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Location permissions -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
</manifest>iOS Setup
For iOS, you need to add location usage descriptions to your ios/YourApp/Info.plist:
<key>NSLocationWhenInUseUsageDescription</key>
<string>This app needs access to location when open.</string>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>This app needs access to location when open and in the background.</string>Optional: For background location tracking, add background modes:
<key>UIBackgroundModes</key>
<array>
<string>location</string>
</array>🎯 Use Cases
- Location Tracking: Track user location for fitness apps
- Navigation: Real-time navigation and routing
- Geofencing: Location-based notifications and actions
- Asset Tracking: Track vehicles, equipment, or packages
- Social Features: Location-based social networking
- Emergency Services: Emergency location sharing
- Delivery Apps: Real-time delivery tracking
- Weather Apps: Location-based weather information
📱 Example Implementation
import React, { useEffect, useState } from "react";
import { View, Text, TouchableOpacity, Alert } from "react-native";
import Geolocation from "@amrshbib/react-native-geolocation";
const App = () => {
const [location, setLocation] = useState(null);
const [permissions, setPermissions] = useState({ fine: false, background: false });
const [watchId, setWatchId] = useState(null);
const [isWatching, setIsWatching] = useState(false);
useEffect(() => {
checkPermissions();
return () => {
if (watchId) {
Geolocation.stopWatching(watchId);
}
};
}, []);
const checkPermissions = async () => {
try {
const perms = await Geolocation.checkPermissions();
setPermissions(perms);
} catch (error) {
console.error("Error checking permissions:", error);
}
};
const requestPermissions = async () => {
try {
const perms = await Geolocation.requestPermissions();
setPermissions(perms);
if (perms.fine) {
Alert.alert("Success", "Location permissions granted!");
} else {
Alert.alert("Permission Required", "Please grant location permission to use this feature.");
}
} catch (error) {
Alert.alert("Error", "Failed to request permissions");
}
};
const getCurrentLocation = async () => {
try {
if (!permissions.fine) {
Alert.alert("Permission Required", "Please grant location permission first.");
return;
}
const loc = await Geolocation.getCurrentLocation({
enableHighAccuracy: true,
timeout: 15000,
priority: "high_accuracy",
});
setLocation(loc);
Alert.alert("Success", `Location: ${loc.latitude}, ${loc.longitude}`);
} catch (error) {
if (error.message && error.message.includes("permissions not granted")) {
Alert.alert("Permission Required", "Location permission is required.");
} else {
Alert.alert("Error", error.message || "Failed to get location");
}
}
};
const startWatching = async () => {
try {
if (!permissions.fine) {
Alert.alert("Permission Required", "Please grant location permission first.");
return;
}
const id = await Geolocation.watchLocation(
(loc, error) => {
if (error) {
console.error("Location watch error:", error);
Alert.alert("Location Error", error);
} else {
setLocation(loc);
}
},
{
enableHighAccuracy: true,
interval: 1000,
priority: "high_accuracy",
}
);
setWatchId(id);
setIsWatching(true);
} catch (error) {
Alert.alert("Error", error.message || "Failed to start location watching");
}
};
const stopWatching = () => {
if (watchId) {
Geolocation.stopWatching(watchId);
setWatchId(null);
setIsWatching(false);
}
};
return (
<View style={{ flex: 1, padding: 20 }}>
<Text style={{ fontSize: 24, marginBottom: 20 }}>Geolocation Demo</Text>
<View style={{ marginBottom: 20 }}>
<Text>Fine Location: {permissions.fine ? "✅ Granted" : "❌ Denied"}</Text>
<Text>Background Location: {permissions.background ? "✅ Granted" : "❌ Denied"}</Text>
</View>
{!permissions.fine && (
<TouchableOpacity
onPress={requestPermissions}
style={{
backgroundColor: "#007AFF",
padding: 15,
borderRadius: 8,
marginBottom: 20,
}}
>
<Text style={{ color: "white", textAlign: "center", fontSize: 18 }}>Request Permissions</Text>
</TouchableOpacity>
)}
<TouchableOpacity
onPress={getCurrentLocation}
style={{
backgroundColor: "#34C759",
padding: 15,
borderRadius: 8,
marginBottom: 10,
}}
>
<Text style={{ color: "white", textAlign: "center", fontSize: 18 }}>Get Current Location</Text>
</TouchableOpacity>
<TouchableOpacity
onPress={isWatching ? stopWatching : startWatching}
style={{
backgroundColor: isWatching ? "#FF3B30" : "#FF9500",
padding: 15,
borderRadius: 8,
marginBottom: 20,
}}
>
<Text style={{ color: "white", textAlign: "center", fontSize: 18 }}>{isWatching ? "Stop Watching" : "Start Watching"}</Text>
</TouchableOpacity>
{location && (
<View style={{ backgroundColor: "#f0f0f0", padding: 15, borderRadius: 8 }}>
<Text style={{ fontSize: 18, marginBottom: 10 }}>Current Location:</Text>
<Text>Latitude: {location.latitude}</Text>
<Text>Longitude: {location.longitude}</Text>
<Text>Accuracy: {location.accuracy}m</Text>
<Text>Speed: {location.speed} m/s</Text>
<Text>Heading: {location.heading}°</Text>
<Text>Provider: {location.provider}</Text>
</View>
)}
</View>
);
};
export default App;⚠️ Important Notes
Android
- Uses Google's FusedLocationProviderClient for optimal battery usage
- Background location requires additional permission on Android 10+
- Location accuracy depends on GPS signal strength and device capabilities
iOS
- Uses CoreLocation framework for location services
- Background location is limited by iOS system policies
- Location services must be enabled by the user
🔧 Troubleshooting
Permission Denied Error
- Check if location permissions are granted
- Request permissions using
Geolocation.requestPermissions() - Guide user to app settings if permissions are denied
Location Services Disabled
- Check if location services are enabled using
Geolocation.isLocationEnabled() - Guide user to enable location services in device settings
No Location Updates
- Ensure permissions are granted
- Check if location services are enabled
- Verify GPS signal strength
- Try different priority levels
High Battery Usage
- Use
balanced_power_accuracyorlow_powerpriority - Increase
intervalandfastestIntervalvalues - Use
smallestDisplacementto reduce unnecessary updates
📋 Requirements
- React Native 0.60+
- Android API 21+ (Android 5.0+)
- iOS 10.0+
- Kotlin support (Android)
🤝 Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
📄 License
The MIT License
Copyright (c) 2024 Amr Shbib [email protected]
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
🔗 Links
Made with ❤️ for the React Native community
