[camera] Fix event type check (#2123)
Trivial change to properly check if the type of an event is an error, so a description can be added.
diff --git a/packages/camera/CHANGELOG.md b/packages/camera/CHANGELOG.md
index c32ef10..2fe0e44 100644
--- a/packages/camera/CHANGELOG.md
+++ b/packages/camera/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 0.5.5+1
+
+* Fix event type check
+
## 0.5.5
* Define clang modules for iOS.
diff --git a/packages/camera/android/build.gradle b/packages/camera/android/build.gradle
index dd544c0..ab2fc8f 100644
--- a/packages/camera/android/build.gradle
+++ b/packages/camera/android/build.gradle
@@ -52,4 +52,11 @@
implementation 'androidx.annotation:annotation:1.0.0'
implementation 'androidx.core:core:1.0.0'
}
+ testOptions {
+ unitTests.returnDefaultValues = true
+ }
+}
+
+dependencies {
+ testImplementation 'junit:junit:4.12'
}
diff --git a/packages/camera/android/src/main/java/io/flutter/plugins/camera/Camera.java b/packages/camera/android/src/main/java/io/flutter/plugins/camera/Camera.java
index 80da644..754a157 100644
--- a/packages/camera/android/src/main/java/io/flutter/plugins/camera/Camera.java
+++ b/packages/camera/android/src/main/java/io/flutter/plugins/camera/Camera.java
@@ -28,7 +28,6 @@
import androidx.annotation.NonNull;
import io.flutter.plugin.common.EventChannel;
import io.flutter.plugin.common.MethodChannel.Result;
-import io.flutter.view.FlutterView;
import io.flutter.view.TextureRegistry.SurfaceTextureEntry;
import java.io.File;
import java.io.FileOutputStream;
@@ -55,7 +54,7 @@
private CameraCaptureSession cameraCaptureSession;
private ImageReader pictureImageReader;
private ImageReader imageStreamReader;
- private EventChannel.EventSink eventSink;
+ private DartMessenger dartMessenger;
private CaptureRequest.Builder captureRequestBuilder;
private MediaRecorder mediaRecorder;
private boolean recordingVideo;
@@ -74,7 +73,8 @@
public Camera(
final Activity activity,
- final FlutterView flutterView,
+ final SurfaceTextureEntry flutterTexture,
+ final DartMessenger dartMessenger,
final String cameraName,
final String resolutionPreset,
final boolean enableAudio)
@@ -85,7 +85,8 @@
this.cameraName = cameraName;
this.enableAudio = enableAudio;
- this.flutterTexture = flutterView.createSurfaceTexture();
+ this.flutterTexture = flutterTexture;
+ this.dartMessenger = dartMessenger;
this.cameraManager = (CameraManager) activity.getSystemService(Context.CAMERA_SERVICE);
orientationEventListener =
new OrientationEventListener(activity.getApplicationContext()) {
@@ -115,21 +116,6 @@
previewSize = computeBestPreviewSize(cameraName, preset);
}
- public void setupCameraEventChannel(EventChannel cameraEventChannel) {
- cameraEventChannel.setStreamHandler(
- new EventChannel.StreamHandler() {
- @Override
- public void onListen(Object arguments, EventChannel.EventSink sink) {
- eventSink = sink;
- }
-
- @Override
- public void onCancel(Object arguments) {
- eventSink = null;
- }
- });
- }
-
private void prepareMediaRecorder(String outputFilePath) throws IOException {
if (mediaRecorder != null) {
mediaRecorder.release();
@@ -186,14 +172,14 @@
@Override
public void onClosed(@NonNull CameraDevice camera) {
- sendEvent(EventType.CAMERA_CLOSING);
+ dartMessenger.sendCameraClosingEvent();
super.onClosed(camera);
}
@Override
public void onDisconnected(@NonNull CameraDevice cameraDevice) {
close();
- sendEvent(EventType.ERROR, "The camera was disconnected.");
+ dartMessenger.send(DartMessenger.EventType.ERROR, "The camera was disconnected.");
}
@Override
@@ -219,7 +205,7 @@
default:
errorDescription = "Unknown camera error";
}
- sendEvent(EventType.ERROR, errorDescription);
+ dartMessenger.send(DartMessenger.EventType.ERROR, errorDescription);
}
},
null);
@@ -327,7 +313,8 @@
public void onConfigured(@NonNull CameraCaptureSession session) {
try {
if (cameraDevice == null) {
- sendEvent(EventType.ERROR, "The camera was closed during configuration.");
+ dartMessenger.send(
+ DartMessenger.EventType.ERROR, "The camera was closed during configuration.");
return;
}
cameraCaptureSession = session;
@@ -338,13 +325,14 @@
onSuccessCallback.run();
}
} catch (CameraAccessException | IllegalStateException | IllegalArgumentException e) {
- sendEvent(EventType.ERROR, e.getMessage());
+ dartMessenger.send(DartMessenger.EventType.ERROR, e.getMessage());
}
}
@Override
public void onConfigureFailed(@NonNull CameraCaptureSession cameraCaptureSession) {
- sendEvent(EventType.ERROR, "Failed to configure camera session.");
+ dartMessenger.send(
+ DartMessenger.EventType.ERROR, "Failed to configure camera session.");
}
};
@@ -487,22 +475,6 @@
null);
}
- private void sendEvent(EventType eventType) {
- sendEvent(eventType, null);
- }
-
- private void sendEvent(EventType eventType, String description) {
- if (eventSink != null) {
- Map<String, String> event = new HashMap<>();
- event.put("eventType", eventType.toString().toLowerCase());
- // Only errors have description
- if (eventType != EventType.ERROR) {
- event.put("errorDescription", description);
- }
- eventSink.success(event);
- }
- }
-
private void closeCaptureSession() {
if (cameraCaptureSession != null) {
cameraCaptureSession.close();
@@ -545,9 +517,4 @@
: (isFrontFacing) ? -currentOrientation : currentOrientation;
return (sensorOrientationOffset + sensorOrientation + 360) % 360;
}
-
- private enum EventType {
- ERROR,
- CAMERA_CLOSING,
- }
}
diff --git a/packages/camera/android/src/main/java/io/flutter/plugins/camera/CameraPlugin.java b/packages/camera/android/src/main/java/io/flutter/plugins/camera/CameraPlugin.java
index b3a1da8..b504f03 100644
--- a/packages/camera/android/src/main/java/io/flutter/plugins/camera/CameraPlugin.java
+++ b/packages/camera/android/src/main/java/io/flutter/plugins/camera/CameraPlugin.java
@@ -14,6 +14,7 @@
import io.flutter.plugin.common.MethodChannel.Result;
import io.flutter.plugin.common.PluginRegistry.Registrar;
import io.flutter.view.FlutterView;
+import io.flutter.view.TextureRegistry;
public class CameraPlugin implements MethodCallHandler {
@@ -48,13 +49,17 @@
String cameraName = call.argument("cameraName");
String resolutionPreset = call.argument("resolutionPreset");
boolean enableAudio = call.argument("enableAudio");
- camera = new Camera(registrar.activity(), view, cameraName, resolutionPreset, enableAudio);
-
- EventChannel cameraEventChannel =
- new EventChannel(
- registrar.messenger(),
- "flutter.io/cameraPlugin/cameraEvents" + camera.getFlutterTexture().id());
- camera.setupCameraEventChannel(cameraEventChannel);
+ TextureRegistry.SurfaceTextureEntry flutterSurfaceTexture = view.createSurfaceTexture();
+ DartMessenger dartMessenger =
+ new DartMessenger(registrar.messenger(), flutterSurfaceTexture.id());
+ camera =
+ new Camera(
+ registrar.activity(),
+ flutterSurfaceTexture,
+ dartMessenger,
+ cameraName,
+ resolutionPreset,
+ enableAudio);
camera.open(result);
}
diff --git a/packages/camera/android/src/main/java/io/flutter/plugins/camera/DartMessenger.java b/packages/camera/android/src/main/java/io/flutter/plugins/camera/DartMessenger.java
new file mode 100644
index 0000000..fe385be
--- /dev/null
+++ b/packages/camera/android/src/main/java/io/flutter/plugins/camera/DartMessenger.java
@@ -0,0 +1,51 @@
+package io.flutter.plugins.camera;
+
+import android.text.TextUtils;
+import androidx.annotation.Nullable;
+import io.flutter.plugin.common.BinaryMessenger;
+import io.flutter.plugin.common.EventChannel;
+import java.util.HashMap;
+import java.util.Map;
+
+class DartMessenger {
+ @Nullable private EventChannel.EventSink eventSink;
+
+ enum EventType {
+ ERROR,
+ CAMERA_CLOSING,
+ }
+
+ DartMessenger(BinaryMessenger messenger, long eventChannelId) {
+ new EventChannel(messenger, "flutter.io/cameraPlugin/cameraEvents" + eventChannelId)
+ .setStreamHandler(
+ new EventChannel.StreamHandler() {
+ @Override
+ public void onListen(Object arguments, EventChannel.EventSink sink) {
+ eventSink = sink;
+ }
+
+ @Override
+ public void onCancel(Object arguments) {
+ eventSink = null;
+ }
+ });
+ }
+
+ void sendCameraClosingEvent() {
+ send(EventType.CAMERA_CLOSING, null);
+ }
+
+ void send(EventType eventType, @Nullable String description) {
+ if (eventSink == null) {
+ return;
+ }
+
+ Map<String, String> event = new HashMap<>();
+ event.put("eventType", eventType.toString().toLowerCase());
+ // Only errors have a description.
+ if (eventType == EventType.ERROR && !TextUtils.isEmpty(description)) {
+ event.put("errorDescription", description);
+ }
+ eventSink.success(event);
+ }
+}
diff --git a/packages/camera/android/src/test/java/io/flutter/plugins/camera/DartMessengerTest.java b/packages/camera/android/src/test/java/io/flutter/plugins/camera/DartMessengerTest.java
new file mode 100644
index 0000000..db89eb2
--- /dev/null
+++ b/packages/camera/android/src/test/java/io/flutter/plugins/camera/DartMessengerTest.java
@@ -0,0 +1,107 @@
+package io.flutter.plugins.camera;
+
+import static junit.framework.TestCase.assertNull;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import io.flutter.plugin.common.BinaryMessenger;
+import io.flutter.plugin.common.MethodCall;
+import io.flutter.plugin.common.StandardMethodCodec;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import org.junit.Before;
+import org.junit.Test;
+
+public class DartMessengerTest {
+ /** A {@link BinaryMessenger} implementation that does nothing but save its messages. */
+ private static class FakeBinaryMessenger implements BinaryMessenger {
+ private BinaryMessageHandler handler;
+ private final List<ByteBuffer> sentMessages = new ArrayList<>();
+
+ @Override
+ public void send(String channel, ByteBuffer message) {
+ sentMessages.add(message);
+ }
+
+ @Override
+ public void send(String channel, ByteBuffer message, BinaryReply callback) {
+ send(channel, message);
+ }
+
+ @Override
+ public void setMessageHandler(String channel, BinaryMessageHandler handler) {
+ this.handler = handler;
+ }
+
+ BinaryMessageHandler getMessageHandler() {
+ return handler;
+ }
+
+ List<ByteBuffer> getMessages() {
+ return new ArrayList<>(sentMessages);
+ }
+ }
+
+ private DartMessenger dartMessenger;
+ private FakeBinaryMessenger fakeBinaryMessenger;
+
+ @Before
+ public void setUp() {
+ fakeBinaryMessenger = new FakeBinaryMessenger();
+ dartMessenger = new DartMessenger(fakeBinaryMessenger, 0);
+ }
+
+ @Test
+ public void setsStreamHandler() {
+ assertNotNull(fakeBinaryMessenger.getMessageHandler());
+ }
+
+ @Test
+ public void send_handlesNullEventSinks() {
+ dartMessenger.send(DartMessenger.EventType.ERROR, "error description");
+
+ List<ByteBuffer> sentMessages = fakeBinaryMessenger.getMessages();
+ assertEquals(0, sentMessages.size());
+ }
+
+ @Test
+ public void send_includesErrorDescriptions() {
+ initializeEventSink();
+
+ dartMessenger.send(DartMessenger.EventType.ERROR, "error description");
+
+ List<ByteBuffer> sentMessages = fakeBinaryMessenger.getMessages();
+ assertEquals(1, sentMessages.size());
+ Map<String, String> event = decodeSentMessage(sentMessages.get(0));
+ assertEquals(DartMessenger.EventType.ERROR.toString().toLowerCase(), event.get("eventType"));
+ assertEquals("error description", event.get("errorDescription"));
+ }
+
+ @Test
+ public void sendCameraClosingEvent() {
+ initializeEventSink();
+
+ dartMessenger.sendCameraClosingEvent();
+
+ List<ByteBuffer> sentMessages = fakeBinaryMessenger.getMessages();
+ assertEquals(1, sentMessages.size());
+ Map<String, String> event = decodeSentMessage(sentMessages.get(0));
+ assertEquals(
+ DartMessenger.EventType.CAMERA_CLOSING.toString().toLowerCase(), event.get("eventType"));
+ assertNull(event.get("errorDescription"));
+ }
+
+ private Map<String, String> decodeSentMessage(ByteBuffer sentMessage) {
+ sentMessage.position(0);
+ return (Map<String, String>) StandardMethodCodec.INSTANCE.decodeEnvelope(sentMessage);
+ }
+
+ private void initializeEventSink() {
+ MethodCall call = new MethodCall("listen", null);
+ ByteBuffer encodedCall = StandardMethodCodec.INSTANCE.encodeMethodCall(call);
+ encodedCall.position(0);
+ fakeBinaryMessenger.getMessageHandler().onMessage(encodedCall, reply -> {});
+ }
+}
diff --git a/packages/camera/pubspec.yaml b/packages/camera/pubspec.yaml
index 9ed9b55..0906f17 100644
--- a/packages/camera/pubspec.yaml
+++ b/packages/camera/pubspec.yaml
@@ -2,7 +2,7 @@
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.5
+version: 0.5.5+1
authors:
- Flutter Team <flutter-dev@googlegroups.com>