Skip to content
This repository has been archived by the owner on Feb 22, 2023. It is now read-only.

Commit

Permalink
[camera] Fix crash from changing permissions (#2447)
Browse files Browse the repository at this point in the history
Our listeners are called for every single permissions change, not just
the first one. This resulted in multiple replies being sent to Dart and
fatal crashes. Change to instead manually keep track of responses and
only respond to the first call.
  • Loading branch information
Michael Klimushyn committed Jan 10, 2020
1 parent a1a4f21 commit 868bc6a
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 14 deletions.
4 changes: 4 additions & 0 deletions packages/camera/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 0.5.7+3

* Fix an Android crash when permissions are requested multiple times.

## 0.5.7+2

* Remove the deprecated `author:` field from pubspec.yaml
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import android.Manifest.permission;
import android.app.Activity;
import android.content.pm.PackageManager;
import androidx.annotation.VisibleForTesting;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import io.flutter.plugin.common.PluginRegistry;
Expand Down Expand Up @@ -59,29 +60,38 @@ private boolean hasAudioPermission(Activity activity) {
== PackageManager.PERMISSION_GRANTED;
}

private static class CameraRequestPermissionsListener
@VisibleForTesting
static final class CameraRequestPermissionsListener
implements PluginRegistry.RequestPermissionsResultListener {

// There's no way to unregister permission listeners in the v1 embedding, so we'll be called
// duplicate times in cases where the user denies and then grants a permission. Keep track of if
// we've responded before and bail out of handling the callback manually if this is a repeat
// call.
boolean alreadyCalled = false;

final ResultCallback callback;

private CameraRequestPermissionsListener(ResultCallback callback) {
@VisibleForTesting
CameraRequestPermissionsListener(ResultCallback callback) {
this.callback = callback;
}

@Override
public boolean onRequestPermissionsResult(int id, String[] permissions, int[] grantResults) {
if (id == CAMERA_REQUEST_ID) {
if (grantResults[0] != PackageManager.PERMISSION_GRANTED) {
callback.onResult("cameraPermission", "MediaRecorderCamera permission not granted");
} else if (grantResults.length > 1
&& grantResults[1] != PackageManager.PERMISSION_GRANTED) {
callback.onResult("cameraPermission", "MediaRecorderAudio permission not granted");
} else {
callback.onResult(null, null);
}
return true;
if (alreadyCalled || id != CAMERA_REQUEST_ID) {
return false;
}

alreadyCalled = true;
if (grantResults[0] != PackageManager.PERMISSION_GRANTED) {
callback.onResult("cameraPermission", "MediaRecorderCamera permission not granted");
} else if (grantResults.length > 1 && grantResults[1] != PackageManager.PERMISSION_GRANTED) {
callback.onResult("cameraPermission", "MediaRecorderAudio permission not granted");
} else {
callback.onResult(null, null);
}
return false;
return true;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package io.flutter.plugins.camera;

import static junit.framework.TestCase.assertEquals;

import android.content.pm.PackageManager;
import io.flutter.plugins.camera.CameraPermissions.CameraRequestPermissionsListener;
import org.junit.Test;

public class CameraPermissionsTest {
@Test
public void listener_respondsOnce() {
final int[] calledCounter = {0};
CameraRequestPermissionsListener permissionsListener =
new CameraRequestPermissionsListener((String code, String desc) -> calledCounter[0]++);

permissionsListener.onRequestPermissionsResult(
9796, null, new int[] {PackageManager.PERMISSION_DENIED});
permissionsListener.onRequestPermissionsResult(
9796, null, new int[] {PackageManager.PERMISSION_GRANTED});

assertEquals(1, calledCounter[0]);
}
}
2 changes: 1 addition & 1 deletion packages/camera/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: camera
description: A Flutter plugin for getting information about and controlling the
camera on Android and iOS. Supports previewing the camera feed, capturing images, capturing video,
and streaming image buffers to dart.
version: 0.5.7+2
version: 0.5.7+3

homepage: https://github.com/flutter/plugins/tree/master/packages/camera

Expand Down

0 comments on commit 868bc6a

Please sign in to comment.