Fix permissions error

pull/356/head
Mattia Iavarone 7 years ago
parent 7a5e0b33e4
commit a7ef91cc78
  1. 2
      cameraview/src/androidTest/java/com/otaliastudios/cameraview/CameraViewCallbacksTest.java
  2. 2
      cameraview/src/androidTest/java/com/otaliastudios/cameraview/CameraViewTest.java
  3. 40
      cameraview/src/main/java/com/otaliastudios/cameraview/CameraView.java
  4. 9
      docs/_posts/2018-12-20-runtime-permissions.md

@ -62,7 +62,7 @@ public class CameraViewCallbacksTest extends BaseTest {
} }
@Override @Override
protected boolean checkPermissions(@NonNull Mode mode, @NonNull Audio audio) { protected boolean checkPermissions(@NonNull Audio audio) {
return true; return true;
} }
}; };

@ -50,7 +50,7 @@ public class CameraViewTest extends BaseTest {
} }
@Override @Override
protected boolean checkPermissions(@NonNull Mode mode, @NonNull Audio audio) { protected boolean checkPermissions(@NonNull Audio audio) {
return hasPermissions; return hasPermissions;
} }
}; };

@ -603,7 +603,7 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
if (!isEnabled()) return; if (!isEnabled()) return;
if (mCameraPreview != null) mCameraPreview.onResume(); if (mCameraPreview != null) mCameraPreview.onResume();
if (checkPermissions(getMode(), getAudio())) { if (checkPermissions(getAudio())) {
// Update display orientation for current CameraController // Update display orientation for current CameraController
mOrientationHelper.enable(getContext()); mOrientationHelper.enable(getContext());
mCameraController.setDisplayOffset(mOrientationHelper.getDisplayOffset()); mCameraController.setDisplayOffset(mOrientationHelper.getDisplayOffset());
@ -613,15 +613,15 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
/** /**
* Checks that we have appropriate permissions for this session type. * Checks that we have appropriate permissions.
* Throws if session = audio and manifest did not add the microphone permissions. * This means checking that we have audio permissions if audio = Audio.ON.
* @param mode the sessionType to be checked
* @param audio the audio setting to be checked * @param audio the audio setting to be checked
* @return true if we can go on, false otherwise. * @return true if we can go on, false otherwise.
*/ */
@SuppressWarnings("ConstantConditions")
@SuppressLint("NewApi") @SuppressLint("NewApi")
protected boolean checkPermissions(@NonNull Mode mode, @NonNull Audio audio) { protected boolean checkPermissions(@NonNull Audio audio) {
checkPermissionsManifestOrThrow(mode, audio); checkPermissionsManifestOrThrow(audio);
// Manifest is OK at this point. Let's check runtime permissions. // Manifest is OK at this point. Let's check runtime permissions.
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) return true; if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) return true;
@ -641,12 +641,11 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
/** /**
* If mSessionType == SESSION_TYPE_VIDEO we will ask for RECORD_AUDIO permission. * If audio is on we will ask for RECORD_AUDIO permission.
* If the developer did not add this to its manifest, throw and fire warnings. * If the developer did not add this to its manifest, throw and fire warnings.
* (Hoping this is not caught elsewhere... we should test).
*/ */
private void checkPermissionsManifestOrThrow(@NonNull Mode mode, @NonNull Audio audio) { private void checkPermissionsManifestOrThrow(@NonNull Audio audio) {
if (mode == Mode.VIDEO && audio == Audio.ON) { if (audio == Audio.ON) {
try { try {
PackageManager manager = getContext().getPackageManager(); PackageManager manager = getContext().getPackageManager();
PackageInfo info = manager.getPackageInfo(getContext().getPackageName(), PackageManager.GET_PERMISSIONS); PackageInfo info = manager.getPackageInfo(getContext().getPackageName(), PackageManager.GET_PERMISSIONS);
@ -655,7 +654,7 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
return; return;
} }
} }
LOG.e("Permission error:", "When the session type is set to video,", LOG.e("Permission error:", "When audio is enabled (Audio.ON),",
"the RECORD_AUDIO permission should be added to the app manifest file."); "the RECORD_AUDIO permission should be added to the app manifest file.");
throw new IllegalStateException(CameraLogger.lastMessage); throw new IllegalStateException(CameraLogger.lastMessage);
} catch (PackageManager.NameNotFoundException e) { } catch (PackageManager.NameNotFoundException e) {
@ -1027,7 +1026,7 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
// Check did took place, or will happen on start(). // Check did took place, or will happen on start().
mCameraController.setAudio(audio); mCameraController.setAudio(audio);
} else if (checkPermissions(getMode(), audio)) { } else if (checkPermissions(audio)) {
// Camera is running. Pass. // Camera is running. Pass.
mCameraController.setAudio(audio); mCameraController.setAudio(audio);
@ -1096,22 +1095,7 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
* @param mode desired session type. * @param mode desired session type.
*/ */
public void setMode(@NonNull Mode mode) { public void setMode(@NonNull Mode mode) {
mCameraController.setMode(mode);
if (mode == getMode() || isClosed()) {
// Check did took place, or will happen on start().
mCameraController.setMode(mode);
} else if (checkPermissions(mode, getAudio())) {
// Camera is running. CameraImpl setMode will do the trick.
mCameraController.setMode(mode);
} else {
// This means that the audio permission is being asked.
// Stop the camera so it can be restarted by the developer onPermissionResult.
// Developer must also set the session type again...
// Not ideal but good for now.
close();
}
} }

@ -41,8 +41,9 @@ device has cameras, and then start the camera view.
On Marshmallow+, the user must explicitly approve our permissions. You can On Marshmallow+, the user must explicitly approve our permissions. You can
- handle permissions yourself and then call `cameraView.start()` once they are acquired - handle permissions yourself and then call `open()` or `setLifecycleOwner()` once they are acquired
- or call `cameraView.start()` anyway: `CameraView` will present a permission request to the user based on - ignore this: `CameraView` will present a permission request to the user based on
whether they are needed or not with the current configuration. whether they are needed or not with the current configuration.
In the second case, you should restart the camera if you have a successful response from `onRequestPermissionResults()`. Note however, that this is done at the activity level, so the permission request callback
`onRequestPermissionResults()` will be invoked on the parent activity, not the fragment.
Loading…
Cancel
Save