Skip to content

Commit bf03246

Browse files
funkyfourierjmrhvl
andauthored
Improved user location on Android (react-native-maps#2993)
* Use custom made LocationSource * Added property to set priority for user location * Property for setting priority of user location * Property for update interval of user location * Changed default update interval for user location to 5000 ms * Property for setting fastest interval for user location updates * Updated documentation * Fixed documentation update * Fixed documentation update * Fixed documentation update * Fixed documentation update * Fixed documentation update * Set fields to final where possible * Merged changes for AndroidX Co-authored-by: jmrhvl <45755981+jmrhvl@users.noreply.github.com>
1 parent d1c79d2 commit bf03246

File tree

3 files changed

+90
-0
lines changed

3 files changed

+90
-0
lines changed

docs/mapview.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@
1515
| `mapType` | `String` | `"standard"` | The map type to be displayed. <br/><br/> - standard: standard road map (default)<br/> - none: no map **Note** Not available on MapKit<br/> - satellite: satellite view<br/> - hybrid: satellite view with roads and points of interest overlayed<br/> - terrain: (Android only) topographic view<br/> - mutedStandard: more subtle, makes markers/lines pop more (iOS 11.0+ only)
1616
| `customMapStyle` | `Array` | | Adds custom styling to the map component. See [README](https://github.com/react-native-community/react-native-maps#customizing-the-map-style) for more information.
1717
| `showsUserLocation` | `Boolean` | `false` | If `true` the app will ask for the user's location. **NOTE**: You need to add `NSLocationWhenInUseUsageDescription` key in Info.plist to enable geolocation, otherwise it is going to *fail silently*! You will also need to add an explanation for why you need the users location against `NSLocationWhenInUseUsageDescription` in Info.plist. Otherwise Apple may reject your app submission.
18+
| `userLocationPriority` | 'balanced'\|'high'\|'low'\|'passive' | 'high' | Set power priority of user location tracking. See [Google APIs documentation](https://developers.google.com/android/reference/com/google/android/gms/location/LocationRequest.html). **Note:** Android only.
19+
| `userLocationUpdateInterval` | `Number` | 5000 | Interval of user location updates in milliseconds. See [Google APIs documentation](https://developers.google.com/android/reference/com/google/android/gms/location/LocationRequest.html). **Note:** Android only.
20+
| `userLocationFastestInterval` | `Number` | | Fastest interval the application will actively acquire locations. See [Google APIs documentation](https://developers.google.com/android/reference/com/google/android/gms/location/LocationRequest.html). **Note:** Android only.
1821
| `userLocationAnnotationTitle` | `String` | | The title of the annotation for current user location. This only works if `showsUserLocation` is true. There is a default value `My Location` set by MapView. **Note**: iOS only.
1922
| `followsUserLocation` | `Boolean` | `false` | If `true` the map will focus on the user's location. This only works if `showsUserLocation` is true and the user has shared their location. **Note**: iOS only.
2023
| `showsMyLocationButton` | `Boolean` | `true` | If `false` hide the button to move map to the current user's location.

lib/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import com.facebook.react.uimanager.ViewGroupManager;
1515
import com.facebook.react.uimanager.annotations.ReactProp;
1616
import com.facebook.react.uimanager.events.RCTEventEmitter;
17+
import com.google.android.gms.location.LocationRequest;
1718
import com.google.android.gms.maps.GoogleMap;
1819
import com.google.android.gms.maps.GoogleMapOptions;
1920
import com.google.android.gms.maps.model.LatLng;
@@ -50,6 +51,13 @@ public class AirMapManager extends ViewGroupManager<AirMapView> {
5051
"none", GoogleMap.MAP_TYPE_NONE
5152
);
5253

54+
private final Map<String, Integer> MY_LOCATION_PRIORITY = MapBuilder.of(
55+
"balanced", LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY,
56+
"high", LocationRequest.PRIORITY_HIGH_ACCURACY,
57+
"low", LocationRequest.PRIORITY_LOW_POWER,
58+
"passive", LocationRequest.PRIORITY_NO_POWER
59+
);
60+
5361
private final ReactApplicationContext appContext;
5462
private AirMapMarkerManager markerManager;
5563

@@ -152,6 +160,21 @@ public void setShowsUserLocation(AirMapView view, boolean showUserLocation) {
152160
view.setShowsUserLocation(showUserLocation);
153161
}
154162

163+
@ReactProp(name = "userLocationPriority")
164+
public void setUserLocationPriority(AirMapView view, @Nullable String accuracy) {
165+
view.setUserLocationPriority(MY_LOCATION_PRIORITY.get(accuracy));
166+
}
167+
168+
@ReactProp(name = "userLocationUpdateInterval", defaultInt = 5000)
169+
public void setUserLocationUpdateInterval(AirMapView view, int updateInterval) {
170+
view.setUserLocationUpdateInterval(updateInterval);
171+
}
172+
173+
@ReactProp(name = "userLocationFastestInterval", defaultInt = 5000)
174+
public void setUserLocationFastestInterval(AirMapView view, int fastestInterval) {
175+
view.setUserLocationFastestInterval(fastestInterval);
176+
}
177+
155178
@ReactProp(name = "showsMyLocationButton", defaultBoolean = true)
156179
public void setShowsMyLocationButton(AirMapView view, boolean showMyLocationButton) {
157180
view.setShowsMyLocationButton(showMyLocationButton);
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package com.airbnb.android.react.maps;
2+
3+
import android.content.Context;
4+
import android.location.Location;
5+
import android.os.Looper;
6+
7+
import com.google.android.gms.location.FusedLocationProviderClient;
8+
import com.google.android.gms.location.LocationCallback;
9+
import com.google.android.gms.location.LocationRequest;
10+
import com.google.android.gms.location.LocationResult;
11+
import com.google.android.gms.location.LocationServices;
12+
import com.google.android.gms.maps.LocationSource;
13+
import com.google.android.gms.tasks.OnSuccessListener;
14+
15+
public class FusedLocationSource implements LocationSource {
16+
17+
private final FusedLocationProviderClient fusedLocationClientProviderClient;
18+
private final LocationRequest locationRequest;
19+
private LocationCallback locationCallback;
20+
21+
public FusedLocationSource(Context context){
22+
fusedLocationClientProviderClient =
23+
LocationServices.getFusedLocationProviderClient(context);
24+
locationRequest = LocationRequest.create();
25+
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
26+
locationRequest.setInterval(5000);
27+
}
28+
29+
public void setPriority(int priority){
30+
locationRequest.setPriority(priority);
31+
}
32+
33+
public void setInterval(int interval){
34+
locationRequest.setInterval(interval);
35+
}
36+
37+
public void setFastestInterval(int fastestInterval){
38+
locationRequest.setFastestInterval(fastestInterval);
39+
}
40+
41+
@Override
42+
public void activate(final OnLocationChangedListener onLocationChangedListener) {
43+
fusedLocationClientProviderClient.getLastLocation().addOnSuccessListener(new OnSuccessListener<Location>() {
44+
@Override
45+
public void onSuccess(Location location) {
46+
onLocationChangedListener.onLocationChanged(location);
47+
}
48+
});
49+
locationCallback = new LocationCallback() {
50+
@Override
51+
public void onLocationResult(LocationResult locationResult) {
52+
for (Location location : locationResult.getLocations()) {
53+
onLocationChangedListener.onLocationChanged(location);
54+
}
55+
}
56+
};
57+
fusedLocationClientProviderClient.requestLocationUpdates(locationRequest, locationCallback, Looper.myLooper());
58+
}
59+
60+
@Override
61+
public void deactivate() {
62+
fusedLocationClientProviderClient.removeLocationUpdates(locationCallback);
63+
}
64+
}

0 commit comments

Comments
 (0)