From 49052be6273f6e0678204dc853cf48961b249bef Mon Sep 17 00:00:00 2001 From: goapunk Date: Sun, 19 Mar 2017 12:02:23 +0100 Subject: [PATCH 1/2] Add permission requests for Android 6+ * Add request for the camera Signed-off-by: goapunk --- .../briar/android/activity/RequestCodes.java | 1 + .../keyagreement/KeyAgreementActivity.java | 103 +++++++++++++++++- .../keyagreement/ShowQrCodeFragment.java | 6 +- .../briar/android/util/UiUtils.java | 24 +++- briar-android/src/main/res/values/strings.xml | 7 ++ 5 files changed, 136 insertions(+), 5 deletions(-) diff --git a/briar-android/src/main/java/org/briarproject/briar/android/activity/RequestCodes.java b/briar-android/src/main/java/org/briarproject/briar/android/activity/RequestCodes.java index 15f621107..131b2921b 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/activity/RequestCodes.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/activity/RequestCodes.java @@ -10,5 +10,6 @@ public interface RequestCodes { int REQUEST_WRITE_BLOG_POST = 6; int REQUEST_SHARE_BLOG = 7; int REQUEST_RINGTONE = 8; + int REQUEST_PERMISSION_CAMERA = 9; } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/keyagreement/KeyAgreementActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/keyagreement/KeyAgreementActivity.java index b66577b67..48e09c368 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/keyagreement/KeyAgreementActivity.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/keyagreement/KeyAgreementActivity.java @@ -1,6 +1,15 @@ package org.briarproject.briar.android.keyagreement; +import android.Manifest; +import android.Manifest.permission; +import android.content.DialogInterface; +import android.content.DialogInterface.OnClickListener; +import android.content.pm.PackageManager; import android.os.Bundle; +import android.support.annotation.UiThread; +import android.support.v4.app.ActivityCompat; +import android.support.v4.content.ContextCompat; +import android.support.v7.app.AlertDialog.Builder; import android.support.v7.widget.Toolbar; import android.view.MenuItem; import android.widget.Toast; @@ -19,19 +28,24 @@ import org.briarproject.bramble.api.keyagreement.event.KeyAgreementFinishedEvent import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault; import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault; import org.briarproject.briar.R; +import org.briarproject.briar.R.string; +import org.briarproject.briar.R.style; import org.briarproject.briar.android.activity.ActivityComponent; import org.briarproject.briar.android.activity.BriarActivity; import org.briarproject.briar.android.fragment.BaseFragment; import org.briarproject.briar.android.fragment.BaseFragment.BaseFragmentListener; import org.briarproject.briar.android.keyagreement.IntroFragment.IntroScreenSeenListener; +import org.briarproject.briar.android.util.UiUtils; import java.util.logging.Logger; import javax.annotation.Nullable; import javax.inject.Inject; +import static android.support.v4.content.PermissionChecker.PERMISSION_GRANTED; import static android.widget.Toast.LENGTH_LONG; import static java.util.logging.Level.WARNING; +import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_PERMISSION_CAMERA; @MethodsNotNullByDefault @ParametersNotNullByDefault @@ -51,6 +65,8 @@ public class KeyAgreementActivity extends BriarActivity implements @Inject volatile IdentityManager identityManager; + private boolean continueClicked, gotCameraPermission; + @Override public void injectActivity(ActivityComponent component) { component.inject(this); @@ -96,10 +112,26 @@ public class KeyAgreementActivity extends BriarActivity implements } } + @Override + protected void onPostResume() { + super.onPostResume(); + //Workaround for https://code.google.com/p/android/issues/detail?id=190966 + if (continueClicked && gotCameraPermission) { + showQrCodeFragment(); + } + } + @Override public void showNextScreen() { // FIXME #824 // showNextFragment(ShowQrCodeFragment.newInstance()); + continueClicked = true; + if (checkPermissions()) { + showQrCodeFragment(); + } + } + + private void showQrCodeFragment() { BaseFragment f = ShowQrCodeFragment.newInstance(); getSupportFragmentManager().beginTransaction() .replace(R.id.fragmentContainer, f, f.getUniqueTag()) @@ -107,6 +139,76 @@ public class KeyAgreementActivity extends BriarActivity implements .commit(); } + private boolean checkPermissions() { + if (ContextCompat.checkSelfPermission(this, permission.CAMERA) != + PackageManager.PERMISSION_GRANTED) { + // Should we show an explanation? + if (ActivityCompat.shouldShowRequestPermissionRationale(this, + permission.CAMERA)) { + OnClickListener proceedListener = new OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + requestPermission(); + } + }; + Builder builder = new Builder(this, style.BriarDialogTheme); + builder.setTitle(string.permission_camera_title); + builder.setMessage(string.permission_camera_request_text); + builder.setNeutralButton(string.continue_button, + proceedListener); + builder.show(); + } else { + requestPermission(); + } + return false; + } else { + return true; + } + } + + private void requestPermission() { + ActivityCompat.requestPermissions(this, + new String[] {permission.CAMERA}, + REQUEST_PERMISSION_CAMERA); + } + + @Override + @UiThread + public void onRequestPermissionsResult(int requestCode, + String permissions[], int[] grantResults) { + if (requestCode == REQUEST_PERMISSION_CAMERA) { + // If request is cancelled, the result arrays are empty. + if (grantResults.length > 0 && + grantResults[0] == PERMISSION_GRANTED) { + gotCameraPermission = true; + } else { + if (!ActivityCompat.shouldShowRequestPermissionRationale(this, + permission.CAMERA)) { + Builder builder = new Builder(this, style.BriarDialogTheme); + builder.setTitle(string.permission_camera_title); + builder.setMessage(string.permission_camera_perm_denied); + builder.setPositiveButton(string.open_settings, + UiUtils.getGoToSettingsListener( + this)); + builder.setNegativeButton(string.cancel, + new OnClickListener() { + @Override + public void onClick( + DialogInterface dialog, + int which) { + supportFinishAfterTransition(); + } + }); + builder.show(); + } else { + Toast.makeText(this, string.permission_camera_denied_toast, + LENGTH_LONG).show(); + supportFinishAfterTransition(); + } + } + } + } + @Override public void eventOccurred(Event e) { if (e instanceof KeyAgreementFinishedEvent) { @@ -189,5 +291,4 @@ public class KeyAgreementActivity extends BriarActivity implements } }); } - } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/keyagreement/ShowQrCodeFragment.java b/briar-android/src/main/java/org/briarproject/briar/android/keyagreement/ShowQrCodeFragment.java index 7a57a601b..93dd29144 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/keyagreement/ShowQrCodeFragment.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/keyagreement/ShowQrCodeFragment.java @@ -114,6 +114,7 @@ public class ShowQrCodeFragment extends BaseEventFragment public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + return inflater.inflate(R.layout.fragment_keyagreement_qr, container, false); } @@ -143,13 +144,11 @@ public class ShowQrCodeFragment extends BaseEventFragment @Override public void onStart() { super.onStart(); - try { cameraView.start(); } catch (CameraException e) { logCameraExceptionAndFinish(e); } - // Listen for changes to the Bluetooth state IntentFilter filter = new IntentFilter(); filter.addAction(ACTION_STATE_CHANGED); @@ -157,7 +156,8 @@ public class ShowQrCodeFragment extends BaseEventFragment getActivity().registerReceiver(receiver, filter); // Enable BT adapter if it is not already on. - final BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); + final BluetoothAdapter adapter = + BluetoothAdapter.getDefaultAdapter(); if (adapter != null && !adapter.isEnabled()) { waitingForBluetooth = true; androidExecutor.runOnBackgroundThread(new Runnable() { diff --git a/briar-android/src/main/java/org/briarproject/briar/android/util/UiUtils.java b/briar-android/src/main/java/org/briarproject/briar/android/util/UiUtils.java index 4543867fa..74f182cbc 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/util/UiUtils.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/util/UiUtils.java @@ -1,6 +1,11 @@ package org.briarproject.briar.android.util; import android.content.Context; + +import android.content.DialogInterface; +import android.content.DialogInterface.OnClickListener; +import android.content.Intent; +import android.net.Uri; import android.support.design.widget.TextInputLayout; import android.support.v4.app.FragmentManager; import android.support.v4.content.ContextCompat; @@ -18,12 +23,14 @@ import android.view.View; import android.widget.TextView; import org.briarproject.bramble.api.contact.ContactId; +import org.briarproject.briar.BuildConfig; import org.briarproject.briar.R; import org.briarproject.briar.android.view.ArticleMovementMethod; import org.briarproject.briar.android.widget.LinkDialogFragment; import javax.annotation.Nullable; +import static android.content.Intent.*; import static android.text.format.DateUtils.DAY_IN_MILLIS; import static android.text.format.DateUtils.FORMAT_ABBREV_MONTH; import static android.text.format.DateUtils.FORMAT_ABBREV_RELATIVE; @@ -31,6 +38,7 @@ import static android.text.format.DateUtils.FORMAT_ABBREV_TIME; import static android.text.format.DateUtils.FORMAT_SHOW_DATE; import static android.text.format.DateUtils.MINUTE_IN_MILLIS; import static android.text.format.DateUtils.WEEK_IN_MILLIS; +import static org.briarproject.briar.BuildConfig.*; import static org.briarproject.briar.android.BriarApplication.EXPIRY_DATE; public class UiUtils { @@ -126,5 +134,19 @@ public class UiUtils { public static String getBulbTransitionName(ContactId c) { return "bulb" + c.getInt(); } - + + public static OnClickListener getGoToSettingsListener( + final Context context) { + return new OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + Intent i = new Intent(); + i.setAction("android.settings.APPLICATION_DETAILS_SETTINGS"); + i.addCategory(CATEGORY_DEFAULT); + i.setData(Uri.parse("package:" + APPLICATION_ID)); + i.addFlags(FLAG_ACTIVITY_NEW_TASK); + context.startActivity(i); + } + }; + } } diff --git a/briar-android/src/main/res/values/strings.xml b/briar-android/src/main/res/values/strings.xml index d2dabb83f..7e85ec103 100644 --- a/briar-android/src/main/res/values/strings.xml +++ b/briar-android/src/main/res/values/strings.xml @@ -381,4 +381,11 @@ Screen overlay detected Another app is drawing on top of Briar. To protect your security, Briar will not respond to touches when another app is drawing on top.\n\nTry turning off the following apps when using Briar:\n\n%1$s + + Camera permission + To scan the QR code, Briar needs access to the camera. + You have denied access to the camera, but adding contacts requires using the camera. Please consider granting access. + Camera permission was not granted + Open Settings + From 8454b2d235fb8dd093e89741ab40ac340dbe46bf Mon Sep 17 00:00:00 2001 From: akwizgran Date: Tue, 10 Oct 2017 11:31:27 +0100 Subject: [PATCH 2/2] Code cleanup, shortened button text to help with layout. --- .../keyagreement/KeyAgreementActivity.java | 52 +++++++++---------- briar-android/src/main/res/values/strings.xml | 5 +- 2 files changed, 26 insertions(+), 31 deletions(-) diff --git a/briar-android/src/main/java/org/briarproject/briar/android/keyagreement/KeyAgreementActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/keyagreement/KeyAgreementActivity.java index 48e09c368..59203041a 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/keyagreement/KeyAgreementActivity.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/keyagreement/KeyAgreementActivity.java @@ -1,10 +1,7 @@ package org.briarproject.briar.android.keyagreement; -import android.Manifest; -import android.Manifest.permission; import android.content.DialogInterface; import android.content.DialogInterface.OnClickListener; -import android.content.pm.PackageManager; import android.os.Bundle; import android.support.annotation.UiThread; import android.support.v4.app.ActivityCompat; @@ -42,7 +39,8 @@ import java.util.logging.Logger; import javax.annotation.Nullable; import javax.inject.Inject; -import static android.support.v4.content.PermissionChecker.PERMISSION_GRANTED; +import static android.Manifest.permission.CAMERA; +import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.widget.Toast.LENGTH_LONG; import static java.util.logging.Level.WARNING; import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_PERMISSION_CAMERA; @@ -115,7 +113,8 @@ public class KeyAgreementActivity extends BriarActivity implements @Override protected void onPostResume() { super.onPostResume(); - //Workaround for https://code.google.com/p/android/issues/detail?id=190966 + // Workaround for + // https://code.google.com/p/android/issues/detail?id=190966 if (continueClicked && gotCameraPermission) { showQrCodeFragment(); } @@ -124,7 +123,7 @@ public class KeyAgreementActivity extends BriarActivity implements @Override public void showNextScreen() { // FIXME #824 -// showNextFragment(ShowQrCodeFragment.newInstance()); + // showNextFragment(ShowQrCodeFragment.newInstance()); continueClicked = true; if (checkPermissions()) { showQrCodeFragment(); @@ -140,12 +139,12 @@ public class KeyAgreementActivity extends BriarActivity implements } private boolean checkPermissions() { - if (ContextCompat.checkSelfPermission(this, permission.CAMERA) != - PackageManager.PERMISSION_GRANTED) { + if (ContextCompat.checkSelfPermission(this, CAMERA) != + PERMISSION_GRANTED) { // Should we show an explanation? if (ActivityCompat.shouldShowRequestPermissionRationale(this, - permission.CAMERA)) { - OnClickListener proceedListener = new OnClickListener() { + CAMERA)) { + OnClickListener continueListener = new OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { requestPermission(); @@ -153,9 +152,9 @@ public class KeyAgreementActivity extends BriarActivity implements }; Builder builder = new Builder(this, style.BriarDialogTheme); builder.setTitle(string.permission_camera_title); - builder.setMessage(string.permission_camera_request_text); + builder.setMessage(string.permission_camera_request_body); builder.setNeutralButton(string.continue_button, - proceedListener); + continueListener); builder.show(); } else { requestPermission(); @@ -167,8 +166,7 @@ public class KeyAgreementActivity extends BriarActivity implements } private void requestPermission() { - ActivityCompat.requestPermissions(this, - new String[] {permission.CAMERA}, + ActivityCompat.requestPermissions(this, new String[] {CAMERA}, REQUEST_PERMISSION_CAMERA); } @@ -183,22 +181,20 @@ public class KeyAgreementActivity extends BriarActivity implements gotCameraPermission = true; } else { if (!ActivityCompat.shouldShowRequestPermissionRationale(this, - permission.CAMERA)) { + CAMERA)) { + // The user has permanently denied the request + OnClickListener cancelListener = new OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + supportFinishAfterTransition(); + } + }; Builder builder = new Builder(this, style.BriarDialogTheme); builder.setTitle(string.permission_camera_title); - builder.setMessage(string.permission_camera_perm_denied); - builder.setPositiveButton(string.open_settings, - UiUtils.getGoToSettingsListener( - this)); - builder.setNegativeButton(string.cancel, - new OnClickListener() { - @Override - public void onClick( - DialogInterface dialog, - int which) { - supportFinishAfterTransition(); - } - }); + builder.setMessage(string.permission_camera_denied_body); + builder.setPositiveButton(string.ok, + UiUtils.getGoToSettingsListener(this)); + builder.setNegativeButton(string.cancel, cancelListener); builder.show(); } else { Toast.makeText(this, string.permission_camera_denied_toast, diff --git a/briar-android/src/main/res/values/strings.xml b/briar-android/src/main/res/values/strings.xml index 7e85ec103..25ef8b471 100644 --- a/briar-android/src/main/res/values/strings.xml +++ b/briar-android/src/main/res/values/strings.xml @@ -383,9 +383,8 @@ Camera permission - To scan the QR code, Briar needs access to the camera. - You have denied access to the camera, but adding contacts requires using the camera. Please consider granting access. + To scan the QR code, Briar needs access to the camera. + You have denied access to the camera, but adding contacts requires using the camera.\n\nPlease consider granting access. Camera permission was not granted - Open Settings