BearND has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/247769

Change subject: 6.0 runtime permission for location
......................................................................

6.0 runtime permission for location

Added runtime permission checks for location in both NearbyFragments
(old and new one).

The runtime check are used once target SDK level is set to 23.
I'll let a later patch change this value, once we're done with all the
permission checks and the backup check.

Added @StringRes annotation in certain FeedbackUtil methods.

Bug: T113749
Change-Id: I8569f19dbcb98c2fe09c2b093c17130a47c4ab29
---
M app/src/main/java/org/wikipedia/nearby/NearbyFragment.java
M app/src/main/java/org/wikipedia/nearby/NearbyFragmentOld.java
M app/src/main/java/org/wikipedia/util/FeedbackUtil.java
M app/src/main/res/values-qq/strings.xml
M app/src/main/res/values/strings.xml
5 files changed, 154 insertions(+), 21 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/apps/android/wikipedia 
refs/changes/69/247769/1

diff --git a/app/src/main/java/org/wikipedia/nearby/NearbyFragment.java 
b/app/src/main/java/org/wikipedia/nearby/NearbyFragment.java
index 85a1669..b4010c9 100644
--- a/app/src/main/java/org/wikipedia/nearby/NearbyFragment.java
+++ b/app/src/main/java/org/wikipedia/nearby/NearbyFragment.java
@@ -1,14 +1,14 @@
 package org.wikipedia.nearby;
 
-import org.wikipedia.page.PageActivityLongPressHandler;
-import org.wikipedia.page.PageLongPressHandler;
-import org.wikipedia.page.PageTitle;
 import org.wikipedia.R;
 import org.wikipedia.Site;
 import org.wikipedia.Utils;
 import org.wikipedia.WikipediaApp;
 import org.wikipedia.history.HistoryEntry;
 import org.wikipedia.page.PageActivity;
+import org.wikipedia.page.PageActivityLongPressHandler;
+import org.wikipedia.page.PageLongPressHandler;
+import org.wikipedia.page.PageTitle;
 import org.wikipedia.util.FeedbackUtil;
 import org.wikipedia.util.log.L;
 
@@ -24,11 +24,13 @@
 import com.mapbox.mapboxsdk.views.MapView;
 import com.squareup.picasso.Picasso;
 
+import android.Manifest;
 import android.content.ActivityNotFoundException;
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.Intent;
 import android.content.SharedPreferences;
+import android.content.pm.PackageManager;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Paint;
@@ -65,6 +67,7 @@
 import android.widget.ListView;
 import android.widget.TextView;
 import android.widget.Toast;
+
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
@@ -83,6 +86,8 @@
     private static final int ONE_THOUSAND = 1000;
     private static final double METER_TO_FEET = 3.280839895;
     private static final int ONE_MILE = 5280;
+    private static final int INITIAL_LOCATION_PERMISSION_REQUEST = 50;
+    private static final int GO_TO_LOCATION_PERMISSION_REQUEST = 51;
 
     private final List<Marker> mMarkerList = new ArrayList<>();
     private View nearbyListContainer;
@@ -145,7 +150,7 @@
                 // don't change zoom level: 
https://github.com/mapbox/mapbox-android-sdk/issues/453
                 mapView.setUserLocationRequiredZoom(mapView.getZoomLevel());
 
-                mapView.goToUserLocation(true);
+                checkLocationPermissionsToGoToUserLocation();
             }
         });
 
@@ -210,6 +215,7 @@
 
         setRefreshingState(true);
         initializeMap();
+        checkInitialLocationPermissions();
     }
 
     @Override
@@ -249,17 +255,6 @@
         mapView.setTileSource(tileSource);
         mapView.setZoom(getResources().getInteger(R.integer.map_default_zoom));
         
mapView.setUserLocationTrackingMode(UserLocationOverlay.TrackingMode.FOLLOW_BEARING);
-        mapView.getUserLocationOverlay().runOnFirstFix(new Runnable() {
-            @Override
-            public void run() {
-                if (!isResumed()) {
-                    return;
-                }
-                currentLocation = 
mapView.getUserLocationOverlay().getLastFix();
-                makeUseOfNewLocation(currentLocation);
-                fetchNearbyPages();
-            }
-        });
 
         mapView.setMapViewListener(new DefaultMapViewListener() {
             @Override
@@ -290,6 +285,80 @@
         });
     }
 
+    private void checkInitialLocationPermissions() {
+        if (ContextCompat.checkSelfPermission(getActivity(),
+                Manifest.permission.ACCESS_FINE_LOCATION) != 
PackageManager.PERMISSION_GRANTED) {
+            
requestLocationRuntimePermissions(INITIAL_LOCATION_PERMISSION_REQUEST);
+        } else {
+            requestLocation();
+        }
+    }
+
+    private void checkLocationPermissionsToGoToUserLocation() {
+        if (ContextCompat.checkSelfPermission(getActivity(),
+                Manifest.permission.ACCESS_FINE_LOCATION) != 
PackageManager.PERMISSION_GRANTED) {
+            
requestLocationRuntimePermissions(GO_TO_LOCATION_PERMISSION_REQUEST);
+        } else {
+            goToUserLocation();
+        }
+    }
+
+    private void requestLocationRuntimePermissions(int requestCode) {
+        requestPermissions(new 
String[]{Manifest.permission.ACCESS_FINE_LOCATION}, requestCode);
+        // once permission is granted/denied it will continue with 
onRequestPermissionsResult
+    }
+
+    @Override
+    public void onRequestPermissionsResult(int requestCode,
+                                           @NonNull String permissions[],
+                                           @NonNull int[] grantResults) {
+        switch (requestCode) {
+            case INITIAL_LOCATION_PERMISSION_REQUEST: {
+                // If request is cancelled, the result arrays are empty.
+                if (grantResults.length > 0
+                        && grantResults[0] == 
PackageManager.PERMISSION_GRANTED) {
+                    requestLocation();
+                } else {
+                    setRefreshingState(false);
+                    FeedbackUtil.showMessage(getActivity(), 
R.string.nearby_zoom_to_location);
+                }
+                break;
+            }
+            case GO_TO_LOCATION_PERMISSION_REQUEST: {
+                // If request is cancelled, the result arrays are empty.
+                if (grantResults.length > 0
+                        && grantResults[0] == 
PackageManager.PERMISSION_GRANTED) {
+                    mapView.goToUserLocation(true);
+                } else {
+                    setRefreshingState(false);
+                    FeedbackUtil.showMessage(getActivity(), 
R.string.nearby_zoom_to_location);
+                }
+                break;
+            }
+        }
+    }
+
+    private void requestLocation() {
+        if (mapView == null || mapView.getUserLocationOverlay() == null) {
+            return;
+        }
+        mapView.getUserLocationOverlay().runOnFirstFix(new Runnable() {
+            @Override
+            public void run() {
+                if (!isResumed()) {
+                    return;
+                }
+                currentLocation = 
mapView.getUserLocationOverlay().getLastFix();
+                makeUseOfNewLocation(currentLocation);
+                fetchNearbyPages();
+            }
+        });
+    }
+
+    private void goToUserLocation() {
+        mapView.goToUserLocation(true);
+    }
+
     private Icon makeMarkerIcon(boolean isActive) {
         int iconSize = (int) 
getResources().getDimension(R.dimen.map_marker_icon_size);
         Bitmap bmp = Bitmap.createBitmap(iconSize, iconSize, 
Bitmap.Config.ARGB_8888);
diff --git a/app/src/main/java/org/wikipedia/nearby/NearbyFragmentOld.java 
b/app/src/main/java/org/wikipedia/nearby/NearbyFragmentOld.java
index 69c8632..14625d7 100644
--- a/app/src/main/java/org/wikipedia/nearby/NearbyFragmentOld.java
+++ b/app/src/main/java/org/wikipedia/nearby/NearbyFragmentOld.java
@@ -12,11 +12,14 @@
 import org.wikipedia.util.FeedbackUtil;
 
 import com.squareup.picasso.Picasso;
+
+import android.Manifest;
 import android.content.ActivityNotFoundException;
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.Intent;
 import android.content.SharedPreferences;
+import android.content.pm.PackageManager;
 import android.hardware.GeomagneticField;
 import android.hardware.Sensor;
 import android.hardware.SensorEvent;
@@ -31,6 +34,7 @@
 import android.provider.Settings;
 import android.support.annotation.NonNull;
 import android.support.v4.app.Fragment;
+import android.support.v4.content.ContextCompat;
 import android.support.v4.widget.SwipeRefreshLayout;
 import android.support.v7.app.AlertDialog;
 import android.text.TextUtils;
@@ -71,6 +75,7 @@
     private static final double ONE_THOUSAND_D = 1000.0d;
     private static final double METER_TO_FEET = 3.280839895;
     private static final int ONE_MILE = 5280;
+    private static final int LOCATION_PERMISSION_REQUEST = 49;
 
     private ListView nearbyList;
     private View nearbyEmptyContainer;
@@ -111,6 +116,9 @@
     //whether to display distances in imperial units (feet/miles) instead of 
metric
     private boolean showImperial = false;
 
+    // if the user has already denied the location permission
+    private boolean locationPermissionDenied;
+
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
@@ -132,7 +140,7 @@
             @Override
             public void onRefresh() {
                 setRefreshingState(true);
-                requestLocationUpdates();
+                checkLocationPermissions();
                 refreshView.setRefreshing(false);
             }
         });
@@ -242,7 +250,9 @@
         super.onResume();
         mSensorManager.registerListener(this, mAccelerometer, 
SensorManager.SENSOR_DELAY_UI);
         mSensorManager.registerListener(this, mMagnetometer, 
SensorManager.SENSOR_DELAY_UI);
-        requestLocationUpdates();
+        if (!locationPermissionDenied) {
+            checkLocationPermissions();
+        }
     }
 
     @Override
@@ -255,7 +265,10 @@
 
     private void stopLocationUpdates() {
         setRefreshingState(false);
-        locationManager.removeUpdates(locationListener);
+        if (ContextCompat.checkSelfPermission(getActivity(),
+                Manifest.permission.ACCESS_FINE_LOCATION) == 
PackageManager.PERMISSION_GRANTED) {
+            locationManager.removeUpdates(locationListener);
+        }
     }
 
     private void requestLocationUpdates() {
@@ -285,11 +298,57 @@
         }
     }
 
+    private void checkLocationPermissions() {
+        if (ContextCompat.checkSelfPermission(getActivity(),
+                Manifest.permission.ACCESS_FINE_LOCATION) != 
PackageManager.PERMISSION_GRANTED) {
+            requestLocationRuntimePermissions(LOCATION_PERMISSION_REQUEST);
+        } else {
+            requestLocationUpdates();
+        }
+    }
+
+    private void requestLocationRuntimePermissions(int requestCode) {
+        requestPermissions(new 
String[]{Manifest.permission.ACCESS_FINE_LOCATION}, requestCode);
+        // once permission is granted/denied it will continue with 
onRequestPermissionsResult
+    }
+
+    @Override
+    public void onRequestPermissionsResult(int requestCode,
+                                           @NonNull String permissions[],
+                                           @NonNull int[] grantResults) {
+        switch (requestCode) {
+            case LOCATION_PERMISSION_REQUEST: {
+                // If request is cancelled, the result arrays are empty.
+                if (grantResults.length > 0
+                        && grantResults[0] == 
PackageManager.PERMISSION_GRANTED) {
+                    requestLocationUpdates();
+                } else {
+                    locationPermissionDenied = true;
+                    showDialogPermissionDenied();
+                }
+                break;
+            }
+        }
+    }
+
     private void requestLocation(String provider) {
-        locationManager.requestLocationUpdates(provider, MIN_TIME_MILLIS, 
MIN_DISTANCE_METERS, locationListener);
+        if (ContextCompat.checkSelfPermission(getActivity(),
+                Manifest.permission.ACCESS_FINE_LOCATION) == 
PackageManager.PERMISSION_GRANTED) {
+            locationManager.requestLocationUpdates(provider, MIN_TIME_MILLIS, 
MIN_DISTANCE_METERS,
+                    locationListener);
+        }
+    }
+
+    private void showDialogPermissionDenied() {
+        AlertDialog.Builder alert = new AlertDialog.Builder(getActivity());
+        alert.setMessage(R.string.nearby_requires_location);
+        alert.setCancelable(true);
+        AlertDialog ad = alert.create();
+        ad.show();
     }
 
     private void showDialogForSettings() {
+        setRefreshingState(false);
         AlertDialog.Builder alert = new AlertDialog.Builder(getActivity());
         alert.setMessage(R.string.nearby_dialog_goto_settings);
         alert.setPositiveButton(android.R.string.ok, new 
DialogInterface.OnClickListener() {
diff --git a/app/src/main/java/org/wikipedia/util/FeedbackUtil.java 
b/app/src/main/java/org/wikipedia/util/FeedbackUtil.java
index 0e9063b..8c47ece 100644
--- a/app/src/main/java/org/wikipedia/util/FeedbackUtil.java
+++ b/app/src/main/java/org/wikipedia/util/FeedbackUtil.java
@@ -1,6 +1,7 @@
 package org.wikipedia.util;
 
 import android.app.Activity;
+import android.support.annotation.StringRes;
 import android.support.design.widget.Snackbar;
 import android.text.Html;
 import android.view.View;
@@ -36,7 +37,7 @@
         makeSnackbar(containerView, text, duration).show();
     }
 
-    public static void showMessage(Activity activity, int resId) {
+    public static void showMessage(Activity activity, @StringRes int resId) {
         showMessage(activity, activity.getString(resId), Snackbar.LENGTH_LONG);
     }
 
@@ -44,7 +45,7 @@
         showMessage(findBestView(activity), text, Snackbar.LENGTH_LONG);
     }
 
-    public static void showMessage(Activity activity, int resId, int duration) 
{
+    public static void showMessage(Activity activity, @StringRes int resId, 
int duration) {
         showMessage(activity, activity.getString(resId), duration);
     }
 
diff --git a/app/src/main/res/values-qq/strings.xml 
b/app/src/main/res/values-qq/strings.xml
index 7b51f22..2179011 100644
--- a/app/src/main/res/values-qq/strings.xml
+++ b/app/src/main/res/values-qq/strings.xml
@@ -78,6 +78,8 @@
   <string name="nearby_set_metric">Menu item for displaying distances in 
metric units (meters and kilometers).</string>
   <string name="nearby_set_imperial">Menu item for displaying distances in 
imperial units (feet and miles).</string>
   <string name="nearby_view_on_map">Hint for button that pinpoints the 
selected Nearby item on a map (will open external app, e.g. Google 
Maps).</string>
+  <string name="nearby_zoom_to_location">Small toast (popup) message on Nearby 
screen saying that the current location of the device was not 
available.</string>
+  <string name="nearby_requires_location">Dialog message saying that the 
Nearby feature requires the location permission. This is shown after the user 
taps on "deny" location permission. (First generation of Nearby feature 
only.)</string>
   <string name="last_updated_text">Message in footer of article indicating 
when the article was last updated. \'%s\' is substituted with the appropriately 
formatted human-readable timestamp, such as \"seven days ago\".</string>
   <string name="content_license_html">HTML specifying license of the Wiki and 
link to appropriate CC page</string>
   <string name="edit_save_action_license_logged_in">HTML specifying Terms of 
Use and CC license before saving edits</string>
diff --git a/app/src/main/res/values/strings.xml 
b/app/src/main/res/values/strings.xml
index 42191ca..07b9652 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -62,6 +62,8 @@
     <string name="nearby_set_metric">Show meters/km</string>
     <string name="nearby_set_imperial">Show feet/miles</string>
     <string name="nearby_view_on_map">View place on map</string>
+    <string name="nearby_zoom_to_location">Zoom to a location on the 
map</string>
+    <string name="nearby_requires_location">The Nearby feature requires the 
location permission.</string>
 
     <string name="last_updated_text">Last updated %s</string>
     <string name="content_license_html"><![CDATA[Content is available under <a 
href=\"//creativecommons.org/licenses/by-sa/3.0/\">CC BY-SA 3.0</a> unless 
otherwise noted]]></string>

-- 
To view, visit https://gerrit.wikimedia.org/r/247769
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I8569f19dbcb98c2fe09c2b093c17130a47c4ab29
Gerrit-PatchSet: 1
Gerrit-Project: apps/android/wikipedia
Gerrit-Branch: master
Gerrit-Owner: BearND <[email protected]>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to