Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
package com.airbnb.android.airmapview;

import android.support.annotation.NonNull;

import com.airbnb.android.airmapview.listeners.InfoWindowCreator;
import com.airbnb.android.airmapview.listeners.OnCameraChangeListener;
import com.airbnb.android.airmapview.listeners.OnInfoWindowClickListener;
import com.airbnb.android.airmapview.listeners.OnLatLngScreenLocationCallback;
import com.airbnb.android.airmapview.listeners.OnLocationPermissionListener;
import com.airbnb.android.airmapview.listeners.OnMapBoundsCallback;
import com.airbnb.android.airmapview.listeners.OnMapClickListener;
import com.airbnb.android.airmapview.listeners.OnMapLoadedListener;
Expand Down Expand Up @@ -58,6 +61,23 @@ public interface AirMapInterface {
*/
void setOnInfoWindowClickListener(OnInfoWindowClickListener listener);

/**
* Set the callback for permission request
*
* @param listener {@link com.airbnb.android.airmapview.listeners.OnLocationPermissionListener}
* instance
*/
void setOnLocationPermissionListener(OnLocationPermissionListener listener);

/**
* Check the result of location permission request
*
* @param requestCode
* @param permissions
* @param grantResults
*/
void onCheckLocationPermissionResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults);

/**
* Specific to Google Play Services maps. Sets the {@link GoogleMap.InfoWindowAdapter} and {@link
* com.airbnb.android.airmapview.listeners.InfoWindowCreator}
Expand Down Expand Up @@ -190,6 +210,16 @@ public interface AirMapInterface {
*/
void onLocationPermissionsGranted();

/**
* Getting called when runtime location permissions got denied.
*/
void onLocationPermissionsDenied();

/**
* Getting called when runtime location permissions got denied and checked the box of 'Never Ask Again'.
*/
void onLocationPermissionsNeverAskAgain();

/**
* Add the given polygon to the map
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import com.airbnb.android.airmapview.listeners.OnCameraMoveListener;
import com.airbnb.android.airmapview.listeners.OnInfoWindowClickListener;
import com.airbnb.android.airmapview.listeners.OnLatLngScreenLocationCallback;
import com.airbnb.android.airmapview.listeners.OnLocationPermissionListener;
import com.airbnb.android.airmapview.listeners.OnMapBoundsCallback;
import com.airbnb.android.airmapview.listeners.OnMapClickListener;
import com.airbnb.android.airmapview.listeners.OnMapInitializedListener;
Expand Down Expand Up @@ -41,6 +42,7 @@ public class AirMapView extends FrameLayout
private OnMapMarkerDragListener onMapMarkerDragListener;
private OnMapClickListener onMapClickListener;
private OnInfoWindowClickListener onInfoWindowClickListener;
private OnLocationPermissionListener onLocationPermissionListener;

public AirMapView(Context context) {
super(context);
Expand Down Expand Up @@ -348,6 +350,14 @@ public void setMyLocationEnabled(boolean trackUserLocation) {
mapInterface.setMyLocationEnabled(trackUserLocation);
}

public void setOnLocationPermissionListener(OnLocationPermissionListener listener) {
onLocationPermissionListener = listener;
}

public void onCheckLocationPermissionResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
mapInterface.onCheckLocationPermissionResult(requestCode, permissions, grantResults);
}

@Override public void onCameraChanged(LatLng latLng, int zoom) {
if (onCameraChangeListener != null) {
onCameraChangeListener.onCameraChanged(latLng, zoom);
Expand Down Expand Up @@ -409,6 +419,7 @@ public void setMyLocationEnabled(boolean trackUserLocation) {
mapInterface.setOnMarkerClickListener(this);
mapInterface.setOnMarkerDragListener(this);
mapInterface.setOnInfoWindowClickListener(this);
mapInterface.setOnLocationPermissionListener(onLocationPermissionListener);

if (onMapInitializedListener != null) {
// only send map Initialized callback if map initialized successfully
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import com.airbnb.android.airmapview.listeners.OnCameraChangeListener;
import com.airbnb.android.airmapview.listeners.OnInfoWindowClickListener;
import com.airbnb.android.airmapview.listeners.OnLatLngScreenLocationCallback;
import com.airbnb.android.airmapview.listeners.OnLocationPermissionListener;
import com.airbnb.android.airmapview.listeners.OnMapBoundsCallback;
import com.airbnb.android.airmapview.listeners.OnMapClickListener;
import com.airbnb.android.airmapview.listeners.OnMapLoadedListener;
Expand Down Expand Up @@ -42,6 +43,7 @@
public class NativeGoogleMapFragment extends SupportMapFragment implements AirMapInterface {
private GoogleMap googleMap;
private OnMapLoadedListener onMapLoadedListener;
private OnLocationPermissionListener onLocationPermissionListener;
private boolean myLocationEnabled;
private GeoJsonLayer layerOnMap;
private final Map<Marker, AirMapMarker<?>> markers = new HashMap<>();
Expand Down Expand Up @@ -121,6 +123,10 @@ public void init() {
});
}

@Override public void setOnLocationPermissionListener(final OnLocationPermissionListener listener) {
this.onLocationPermissionListener = listener;
}

@Override public void setInfoWindowCreator(GoogleMap.InfoWindowAdapter adapter,
InfoWindowCreator creator) {
googleMap.setInfoWindowAdapter(adapter);
Expand Down Expand Up @@ -267,22 +273,46 @@ public void onMapClick(LatLng latLng) {
}

@Override public void setMyLocationEnabled(boolean enabled) {
if (myLocationEnabled != enabled) {
if (RuntimePermissionUtils.checkLocationPermissions(getActivity(), this)) {
myLocationEnabled = enabled;
}
myLocationEnabled = enabled;
if (enabled) {
RuntimePermissionUtils.checkLocationPermissions(getActivity(), this);
}
}

@Override public void onLocationPermissionsGranted() {
myLocationEnabled = true;
//noinspection MissingPermission
googleMap.setMyLocationEnabled(myLocationEnabled);
googleMap.setMyLocationEnabled(true);
if (onLocationPermissionListener != null) {
onLocationPermissionListener.onLocationPermissionGranted();
}
}

@Override
public void onLocationPermissionsDenied() {
myLocationEnabled = false;
if (onLocationPermissionListener != null) {
onLocationPermissionListener.onLocationPermissionDenied();
}
}

@Override
public void onLocationPermissionsNeverAskAgain() {
myLocationEnabled = false;
if (onLocationPermissionListener != null) {
onLocationPermissionListener.onLocationPermissionPermanentlyDenied();
}
}

@Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
@NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
RuntimePermissionUtils.onRequestPermissionsResult(this, requestCode, grantResults);
RuntimePermissionUtils.onRequestPermissionsResult(this.getActivity(), this, requestCode, permissions, grantResults);
}

@Override
public void onCheckLocationPermissionResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
RuntimePermissionUtils.onRequestPermissionsResult(this.getActivity(), this, requestCode, permissions, grantResults);
}

@Override public boolean isMyLocationEnabled() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@
import android.os.Build;
import android.support.v4.app.ActivityCompat;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

import static android.support.v4.content.PermissionChecker.checkSelfPermission;

/**
Expand Down Expand Up @@ -35,6 +39,27 @@ private static boolean verifyPermissions(int... grantResults) {
return true;
}

/**
* Check the permissions are the requested permissions
*
* @param permissions
* @return true if the permissions are matched perfectly
*/
static boolean isRequestedPermission(String[] permissions) {
if (permissions.length != LOCATION_PERMISSIONS.length) {
return false;
}

final Set<String> requestPermissions = new HashSet<>(Arrays.asList(LOCATION_PERMISSIONS));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's not clear to me why you're creating this set with a single item inside?
can you just check if permission.equals(LOCATION_PERMISSIONS) on line 55?

for (String permission : permissions) {
if (!requestPermissions.contains(permission)) {
return false;
}
}

return true;
}

/**
* Returns true if the context has access to any given permissions.
*/
Expand Down Expand Up @@ -68,31 +93,41 @@ static boolean shouldShowRequestPermissionRationale(Activity activity, String...
*
* @param airMapInterface the callback interface if permission is granted.
*/
static boolean checkLocationPermissions(Activity targetActivity, AirMapInterface airMapInterface) {
static void checkLocationPermissions(Activity targetActivity, AirMapInterface airMapInterface) {
if (hasSelfPermissions(targetActivity, LOCATION_PERMISSIONS)) {
airMapInterface.onLocationPermissionsGranted();
return true;
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
targetActivity.requestPermissions(LOCATION_PERMISSIONS, LOCATION_PERMISSION_REQUEST_CODE);
} else {
airMapInterface.onLocationPermissionsDenied();
}
//else don't have location permissions in pre M, don't do anything.
return false;
}

/**
* Dispatch actions based off requested permission results.<br />
* Dispatch actions based off requested permission results.
* The activity or fragment must call this function in onRequestPermissionsResult
* {@link android.support.v4.app.Fragment#onRequestPermissionsResult(int, String[], int[])}
* {@link android.app.Activity#onRequestPermissionsResult(int, String[], int[])}<br />
* Further actions like
* 1> Rationale: showing a snack bar to explain why the permissions are needed and
* 2> Denied: adding airMapInterface.onLocationPermissionsDenied()
* should be added here if needed.
*
*/
static void onRequestPermissionsResult(AirMapInterface airMapInterface, int requestCode,
int[] grantResults) {
static void onRequestPermissionsResult(Activity activity, AirMapInterface airMapInterface, int requestCode,
String[] permissions, int[] grantResults) {
switch (requestCode) {
case LOCATION_PERMISSION_REQUEST_CODE:
if (!isRequestedPermission(permissions)) {
break;
}

if (verifyPermissions(grantResults)) {
airMapInterface.onLocationPermissionsGranted();
} else if (!shouldShowRequestPermissionRationale(activity, LOCATION_PERMISSIONS)) {
airMapInterface.onLocationPermissionsNeverAskAgain();
} else {
airMapInterface.onLocationPermissionsDenied();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

indentation is still 4 spaces here

}
break;
default:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import com.airbnb.android.airmapview.listeners.OnCameraChangeListener;
import com.airbnb.android.airmapview.listeners.OnInfoWindowClickListener;
import com.airbnb.android.airmapview.listeners.OnLatLngScreenLocationCallback;
import com.airbnb.android.airmapview.listeners.OnLocationPermissionListener;
import com.airbnb.android.airmapview.listeners.OnMapBoundsCallback;
import com.airbnb.android.airmapview.listeners.OnMapClickListener;
import com.airbnb.android.airmapview.listeners.OnMapLoadedListener;
Expand Down Expand Up @@ -53,6 +54,7 @@ public abstract class WebViewMapFragment extends Fragment implements AirMapInter
private InfoWindowCreator infoWindowCreator;
private OnMapBoundsCallback onMapBoundsCallback;
private OnLatLngScreenLocationCallback onLatLngScreenLocationCallback;
private OnLocationPermissionListener onLocationPermissionListener;
private LatLng center;
private int zoom;
private boolean loaded;
Expand Down Expand Up @@ -218,23 +220,52 @@ public void setOnMarkerClickListener(OnMapMarkerClickListener listener) {
// no-op
}

@Override public void setOnLocationPermissionListener(final OnLocationPermissionListener listener) {
this.onLocationPermissionListener = listener;
}

@Override public void setMyLocationEnabled(boolean trackUserLocationEnabled) {
trackUserLocation = trackUserLocationEnabled;
if (trackUserLocationEnabled) {
RuntimePermissionUtils.checkLocationPermissions(getActivity(), this);
} else {
webView.loadUrl("javascript:stopTrackingUserLocation();");
}
}

@Override public void onLocationPermissionsGranted() {
trackUserLocation = true;
webView.loadUrl("javascript:startTrackingUserLocation();");
if (onLocationPermissionListener != null) {
onLocationPermissionListener.onLocationPermissionGranted();
}
}

@Override
public void onLocationPermissionsDenied() {
trackUserLocation = false;
webView.loadUrl("javascript:stopTrackingUserLocation();");
if (onLocationPermissionListener != null) {
onLocationPermissionListener.onLocationPermissionDenied();
}
}

@Override
public void onLocationPermissionsNeverAskAgain() {
trackUserLocation = false;
webView.loadUrl("javascript:stopTrackingUserLocation();");
if (onLocationPermissionListener != null) {
onLocationPermissionListener.onLocationPermissionPermanentlyDenied();
}
}

@Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
@NonNull int[] grantResults) {
@NonNull int[] grantResults) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

formatting

super.onRequestPermissionsResult(requestCode, permissions, grantResults);
RuntimePermissionUtils.onRequestPermissionsResult(this, requestCode, grantResults);
RuntimePermissionUtils.onRequestPermissionsResult(this.getActivity(), this, requestCode, permissions, grantResults);
}

@Override
public void onCheckLocationPermissionResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
RuntimePermissionUtils.onRequestPermissionsResult(this.getActivity(), this, requestCode, permissions, grantResults);
}

@Override public boolean isMyLocationEnabled() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.airbnb.android.airmapview.listeners;

/**
* Interface which supplies callbacks when showing dynamic permission request dialogs
* Location permission is requested when enable 'my location'.
* {@link com.airbnb.android.airmapview.AirMapInterface#setMyLocationEnabled(boolean)}
*/
public interface OnLocationPermissionListener {
/**
* Called when location permission is granted
*/
void onLocationPermissionGranted();

/**
* Called when location permission is denied
*/
void onLocationPermissionDenied();

/**
* Called when location permission is denied, and the checkbox of 'Never Ask Again' is checked
*/
void onLocationPermissionPermanentlyDenied();
}
1 change: 1 addition & 0 deletions sample/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

<!-- not needed as of api 23 -->
<!--
Expand Down
Loading