Ask for coarse location permission before adding a contact.

This commit is contained in:
akwizgran
2018-01-11 12:14:23 +00:00
parent 3192015cfd
commit bd00fb1c04
4 changed files with 76 additions and 47 deletions

View File

@@ -7,6 +7,7 @@
<uses-feature android:name="android.hardware.camera" android:required="false"/> <uses-feature android:name="android.hardware.camera" android:required="false"/>
<uses-feature android:name="android.hardware.touchscreen" android:required="false" /> <uses-feature android:name="android.hardware.touchscreen" android:required="false" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.BLUETOOTH" /> <uses-permission android:name="android.permission.BLUETOOTH" />

View File

@@ -9,7 +9,7 @@ public interface RequestCodes {
int REQUEST_WRITE_BLOG_POST = 5; int REQUEST_WRITE_BLOG_POST = 5;
int REQUEST_SHARE_BLOG = 6; int REQUEST_SHARE_BLOG = 6;
int REQUEST_RINGTONE = 7; int REQUEST_RINGTONE = 7;
int REQUEST_PERMISSION_CAMERA = 8; int REQUEST_PERMISSION_CAMERA_LOCATION = 8;
int REQUEST_DOZE_WHITELISTING = 9; int REQUEST_DOZE_WHITELISTING = 9;
int REQUEST_BLUETOOTH_DISCOVERABLE = 10; int REQUEST_BLUETOOTH_DISCOVERABLE = 10;
int REQUEST_UNLOCK = 11; int REQUEST_UNLOCK = 11;

View File

@@ -3,7 +3,6 @@ package org.briarproject.briar.android.keyagreement;
import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothAdapter;
import android.content.BroadcastReceiver; import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent; import android.content.Intent;
import android.content.IntentFilter; import android.content.IntentFilter;
import android.os.Bundle; import android.os.Bundle;
@@ -37,19 +36,21 @@ import java.util.logging.Logger;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import javax.inject.Inject; import javax.inject.Inject;
import static android.Manifest.permission.ACCESS_COARSE_LOCATION;
import static android.Manifest.permission.CAMERA; import static android.Manifest.permission.CAMERA;
import static android.bluetooth.BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE; import static android.bluetooth.BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE;
import static android.bluetooth.BluetoothAdapter.ACTION_SCAN_MODE_CHANGED; import static android.bluetooth.BluetoothAdapter.ACTION_SCAN_MODE_CHANGED;
import static android.bluetooth.BluetoothAdapter.ACTION_STATE_CHANGED; import static android.bluetooth.BluetoothAdapter.ACTION_STATE_CHANGED;
import static android.bluetooth.BluetoothAdapter.EXTRA_SCAN_MODE; import static android.bluetooth.BluetoothAdapter.EXTRA_SCAN_MODE;
import static android.bluetooth.BluetoothAdapter.EXTRA_STATE; import static android.bluetooth.BluetoothAdapter.EXTRA_STATE;
import static android.bluetooth.BluetoothAdapter.SCAN_MODE_CONNECTABLE;
import static android.bluetooth.BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE; import static android.bluetooth.BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE;
import static android.bluetooth.BluetoothAdapter.STATE_ON; import static android.bluetooth.BluetoothAdapter.STATE_ON;
import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.os.Build.VERSION.SDK_INT; import static android.os.Build.VERSION.SDK_INT;
import static android.widget.Toast.LENGTH_LONG; import static android.widget.Toast.LENGTH_LONG;
import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_BLUETOOTH_DISCOVERABLE; import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_BLUETOOTH_DISCOVERABLE;
import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_PERMISSION_CAMERA; import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_PERMISSION_CAMERA_LOCATION;
@MethodsNotNullByDefault @MethodsNotNullByDefault
@ParametersNotNullByDefault @ParametersNotNullByDefault
@@ -68,7 +69,7 @@ public abstract class KeyAgreementActivity extends BriarActivity implements
EventBus eventBus; EventBus eventBus;
private boolean isResumed = false, wasAdapterEnabled = false; private boolean isResumed = false, wasAdapterEnabled = false;
private boolean continueClicked, gotCameraPermission; private boolean continueClicked, gotCameraPermission, gotLocationPermission;
private BluetoothState bluetoothState = BluetoothState.UNKNOWN; private BluetoothState bluetoothState = BluetoothState.UNKNOWN;
private BroadcastReceiver bluetoothReceiver = null; private BroadcastReceiver bluetoothReceiver = null;
@@ -155,12 +156,12 @@ public abstract class KeyAgreementActivity extends BriarActivity implements
BluetoothAdapter bt = BluetoothAdapter.getDefaultAdapter(); BluetoothAdapter bt = BluetoothAdapter.getDefaultAdapter();
if (bt == null) { if (bt == null) {
setBluetoothState(BluetoothState.NO_ADAPTER); setBluetoothState(BluetoothState.NO_ADAPTER);
return; } else {
setBluetoothState(BluetoothState.WAITING);
wasAdapterEnabled = bt.isEnabled();
Intent i = new Intent(ACTION_REQUEST_DISCOVERABLE);
startActivityForResult(i, REQUEST_BLUETOOTH_DISCOVERABLE);
} }
setBluetoothState(BluetoothState.WAITING);
wasAdapterEnabled = bt.isEnabled();
Intent i = new Intent(ACTION_REQUEST_DISCOVERABLE);
startActivityForResult(i, REQUEST_BLUETOOTH_DISCOVERABLE);
} }
private void setBluetoothState(BluetoothState bluetoothState) { private void setBluetoothState(BluetoothState bluetoothState) {
@@ -202,62 +203,83 @@ public abstract class KeyAgreementActivity extends BriarActivity implements
} }
private boolean checkPermissions() { private boolean checkPermissions() {
if (ContextCompat.checkSelfPermission(this, CAMERA) != gotCameraPermission = checkPermission(CAMERA);
PERMISSION_GRANTED) { gotLocationPermission = checkPermission(ACCESS_COARSE_LOCATION);
// Should we show an explanation? if (gotCameraPermission && gotLocationPermission) return true;
if (ActivityCompat.shouldShowRequestPermissionRationale(this, // Should we show an explanation for one or both permissions?
CAMERA)) { boolean cameraRationale = shouldShowRationale(CAMERA);
OnClickListener continueListener = boolean locationRationale = shouldShowRationale(ACCESS_COARSE_LOCATION);
(dialog, which) -> requestPermission(); if (cameraRationale && locationRationale) {
Builder builder = new Builder(this, style.BriarDialogTheme); showRationale(string.permission_camera_location_title,
builder.setTitle(string.permission_camera_title); string.permission_camera_location_request_body);
builder.setMessage(string.permission_camera_request_body); } else if (cameraRationale) {
builder.setNeutralButton(string.continue_button, showRationale(string.permission_camera_title,
continueListener); string.permission_camera_request_body);
builder.show(); } else if (locationRationale) {
} else { showRationale(string.permission_location_title,
requestPermission(); string.permission_location_request_body);
} } else if (gotCameraPermission) {
gotCameraPermission = false; // Location permission has been permanently denied but we can
return false; // continue without it
} else {
gotCameraPermission = true;
return true; return true;
} else {
requestPermissions();
} }
return false;
} }
private void requestPermission() { private boolean checkPermission(String permission) {
ActivityCompat.requestPermissions(this, new String[] {CAMERA}, return ContextCompat.checkSelfPermission(this, permission)
REQUEST_PERMISSION_CAMERA); == PERMISSION_GRANTED;
}
private boolean shouldShowRationale(String permission) {
return ActivityCompat.shouldShowRequestPermissionRationale(this,
permission);
}
private void showRationale(@StringRes int title, @StringRes int body) {
Builder builder = new Builder(this, style.BriarDialogTheme);
builder.setTitle(title);
builder.setMessage(body);
builder.setNeutralButton(string.continue_button,
(dialog, which) -> requestPermissions());
builder.show();
}
private void requestPermissions() {
ActivityCompat.requestPermissions(this,
new String[] {CAMERA, ACCESS_COARSE_LOCATION},
REQUEST_PERMISSION_CAMERA_LOCATION);
} }
@Override @Override
@UiThread @UiThread
public void onRequestPermissionsResult(int requestCode, public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) { String permissions[], int[] grantResults) {
if (requestCode == REQUEST_PERMISSION_CAMERA) { if (requestCode == REQUEST_PERMISSION_CAMERA_LOCATION) {
// If request is cancelled, the result arrays are empty. // If request is cancelled, the result arrays are empty
if (grantResults.length > 0 && gotCameraPermission = grantResults.length > 0
grantResults[0] == PERMISSION_GRANTED) { && grantResults[0] == PERMISSION_GRANTED;
gotCameraPermission = true; gotLocationPermission = grantResults.length > 1
&& grantResults[1] == PERMISSION_GRANTED;
if (gotCameraPermission) {
showNextScreen(); showNextScreen();
} else { } else {
if (!ActivityCompat.shouldShowRequestPermissionRationale(this, if (shouldShowRationale(CAMERA)) {
CAMERA)) { Toast.makeText(this, string.permission_camera_denied_toast,
LENGTH_LONG).show();
supportFinishAfterTransition();
} else {
// The user has permanently denied the request // The user has permanently denied the request
OnClickListener cancelListener =
(dialog, which) -> supportFinishAfterTransition();
Builder builder = new Builder(this, style.BriarDialogTheme); Builder builder = new Builder(this, style.BriarDialogTheme);
builder.setTitle(string.permission_camera_title); builder.setTitle(string.permission_camera_title);
builder.setMessage(string.permission_camera_denied_body); builder.setMessage(string.permission_camera_denied_body);
builder.setPositiveButton(string.ok, builder.setPositiveButton(string.ok,
UiUtils.getGoToSettingsListener(this)); UiUtils.getGoToSettingsListener(this));
builder.setNegativeButton(string.cancel, cancelListener); builder.setNegativeButton(string.cancel,
(dialog, which) -> supportFinishAfterTransition());
builder.show(); builder.show();
} else {
Toast.makeText(this, string.permission_camera_denied_toast,
LENGTH_LONG).show();
supportFinishAfterTransition();
} }
} }
} }
@@ -274,9 +296,11 @@ public abstract class KeyAgreementActivity extends BriarActivity implements
setBluetoothState(BluetoothState.ENABLED); setBluetoothState(BluetoothState.ENABLED);
else setBluetoothState(BluetoothState.UNKNOWN); else setBluetoothState(BluetoothState.UNKNOWN);
} else if (ACTION_SCAN_MODE_CHANGED.equals(action)) { } else if (ACTION_SCAN_MODE_CHANGED.equals(action)) {
int scanMode = intent.getIntExtra(EXTRA_SCAN_MODE, -1); int scanMode = intent.getIntExtra(EXTRA_SCAN_MODE, 0);
if (scanMode == SCAN_MODE_CONNECTABLE_DISCOVERABLE) if (scanMode == SCAN_MODE_CONNECTABLE_DISCOVERABLE)
setBluetoothState(BluetoothState.DISCOVERABLE); setBluetoothState(BluetoothState.DISCOVERABLE);
else if (scanMode == SCAN_MODE_CONNECTABLE)
setBluetoothState(BluetoothState.ENABLED);
else setBluetoothState(BluetoothState.UNKNOWN); else setBluetoothState(BluetoothState.UNKNOWN);
} }
} }

View File

@@ -467,6 +467,10 @@
<!-- Permission Requests --> <!-- Permission Requests -->
<string name="permission_camera_title">Camera permission</string> <string name="permission_camera_title">Camera permission</string>
<string name="permission_camera_request_body">To scan the QR code, Briar needs access to the camera.</string> <string name="permission_camera_request_body">To scan the QR code, Briar needs access to the camera.</string>
<string name="permission_location_title">Location permission</string>
<string name="permission_location_request_body">To discover Bluetooth devices, Briar needs permission to access your location.\n\nBriar does not store your location or share it with anyone.</string>
<string name="permission_camera_location_title">Camera and location</string>
<string name="permission_camera_location_request_body">To scan the QR code, Briar needs access to the camera.\n\nTo discover Bluetooth devices, Briar needs permission to access your location.\n\nBriar does not store your location or share it with anyone.</string>
<string name="permission_camera_denied_body">You have denied access to the camera, but adding contacts requires using the camera.\n\nPlease consider granting access.</string> <string name="permission_camera_denied_body">You have denied access to the camera, but adding contacts requires using the camera.\n\nPlease consider granting access.</string>
<string name="permission_camera_denied_toast">Camera permission was not granted</string> <string name="permission_camera_denied_toast">Camera permission was not granted</string>
<string name="qr_code">QR code</string> <string name="qr_code">QR code</string>