I put "background" in quotes, because on Android it's actually using a "Foreground Service".
This project contains an Android Native Module so you'll have to have your project "ejected" (if you started with Expo). If you started with the React Native CLI (via react-native init
) you should be good to go.
- Uses APIs provided by Android (like: FusedLocationProviderClient and Foreground Service)
- Android Location query interval is customisable down to 1s (maybe faster? I haven't tested that yet...)
- Display's "Ongoing" notification to the user while the app is requesting location updates
- Communicates location to your ReactNative JS code while the app is closed and/or the phone screen is off for processing
- Ready to do work on the native side if you'd prefer to save the data directly to the device instead
This project was based on the combination of two other demo apps:
- https://github.com/comoser/rn-background-location (Uses "Background Service" for better power efficiency but is limited to locations updates down to 1 minute... I needed something faster)
- Android's LocationUpdatesForegroundService Example found in their Request Location Updates page.
I'm very much new to Android development so I had to stumble through parts of this... During development I was testing on device and in simulators using Android API 28 + 29. I have not done exaustive testing, nor know enough about Android to say with confidence how far back this code will support.
As listed above in the feature sections, iOS is taken care of by React Native Location. The core of this sample project is in the Android specific code. Most of the changes are rolled up into an Android Native Module, located here:
./android/app/src/main/java/com/mranderson/locationsample/location
However, a number of other changes also need to be made to the main React Native project:
- MainApplication.java (to include the location package in the project)
- MainActivity.java (to bind the MainActivity to the location forground service provided by the package mentioned above)
- AndroidManifest.xml (added the forground location service
<service>
and<uses-permission>
forACCESS_FINE_LOCATION
andFOREGROUND_SERVICE
) - strings.xml (added a number of text values used by the location service)
- multiple
ic_notify_icon.png
files found in thedrawable-...
folders inside res (used as the icon that shows in the system notification try while the forground service is active)
Hopefully that covers pretty much all of it. If I've missed any changes, I'll come back in here and update this list. I also tried to add comments to those files to indicate which changes or additions need to be made.
First and foremost, this sample project uses React Native Location. So, if you plan on trying to copy my changes into your own project, you may want to look over the docs for RNLocation
first.
On the iOS side of things, RNLocation
provides everything you need. It also works on the Android side, just not while the app is "in the background". On both platforms, RNLocation
is used to prompt the user for location access permission. To do this, you use RNLocation.requestPermission()
which, in this project, can be found in the <LocationAccessButton> component (or just read more about how it in the RNLocation
docs).
For iOS, you also need to initialize RNLocation
by calling RNLocation.configure()
which, in this project, can be found in the index.js. In this case, you'll see that I left in the "Android Only" configuration options, even though this sample project actually uses it's own Android Native Module mentioned above. Any options within the RNLocation.configure()
call will only effect iOS at this point. If you want to adjust the interval or anything on the Android side, you would need to make changes directly to the Android specific native module files.
Lastly, for this project, I chose to create a reducer and a couple of custom hooks to handle the location data and starting/stopping of the location tracking subscription. On iOS, the useLocationTracking()
hook is used to start and stop RNLocation.subscribeToLocationUpdates()
. On Android, the useNativeLocationTracking()
hook is used to start and stop background tracking as well as creates a native event listener which listens for location events that are emitted by the Android Native Module. Both of these hooks then fire an UpdatePosition
action to the reducer to handle the data provided by each and normalize them into a single usable format in the app.