blob: dc62fce524d30bbc1d0d06bd95be74c206e72da4 [file] [log] [blame]
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package io.flutter.plugins.camera;
import android.os.Handler;
import android.text.TextUtils;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import io.flutter.embedding.engine.systemchannels.PlatformChannel;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugins.camera.features.autofocus.FocusMode;
import io.flutter.plugins.camera.features.exposurelock.ExposureMode;
import java.util.HashMap;
import java.util.Map;
/** Utility class that facilitates communication to the Flutter client */
public class DartMessenger {
@NonNull private final Handler handler;
@Nullable private MethodChannel cameraChannel;
@Nullable private MethodChannel deviceChannel;
/** Specifies the different device related message types. */
enum DeviceEventType {
/** Indicates the device's orientation has changed. */
ORIENTATION_CHANGED("orientation_changed");
private final String method;
DeviceEventType(String method) {
this.method = method;
}
}
/** Specifies the different camera related message types. */
enum CameraEventType {
/** Indicates that an error occurred while interacting with the camera. */
ERROR("error"),
/** Indicates that the camera is closing. */
CLOSING("camera_closing"),
/** Indicates that the camera is initialized. */
INITIALIZED("initialized");
private final String method;
/**
* Converts the supplied method name to the matching {@link CameraEventType}.
*
* @param method name to be converted into a {@link CameraEventType}.
*/
CameraEventType(String method) {
this.method = method;
}
}
/**
* Creates a new instance of the {@link DartMessenger} class.
*
* @param messenger is the {@link BinaryMessenger} that is used to communicate with Flutter.
* @param cameraId identifies the camera which is the source of the communication.
* @param handler the handler used to manage the thread's message queue. This should always be a
* handler managing the main thread since communication with Flutter should always happen on
* the main thread. The handler is mainly supplied so it will be easier test this class.
*/
DartMessenger(BinaryMessenger messenger, long cameraId, @NonNull Handler handler) {
cameraChannel = new MethodChannel(messenger, "flutter.io/cameraPlugin/camera" + cameraId);
deviceChannel = new MethodChannel(messenger, "flutter.io/cameraPlugin/device");
this.handler = handler;
}
/**
* Sends a message to the Flutter client informing the orientation of the device has been changed.
*
* @param orientation specifies the new orientation of the device.
*/
public void sendDeviceOrientationChangeEvent(PlatformChannel.DeviceOrientation orientation) {
assert (orientation != null);
this.send(
DeviceEventType.ORIENTATION_CHANGED,
new HashMap<String, Object>() {
{
put("orientation", CameraUtils.serializeDeviceOrientation(orientation));
}
});
}
/**
* Sends a message to the Flutter client informing that the camera has been initialized.
*
* @param previewWidth describes the preview width that is supported by the camera.
* @param previewHeight describes the preview height that is supported by the camera.
* @param exposureMode describes the current exposure mode that is set on the camera.
* @param focusMode describes the current focus mode that is set on the camera.
* @param exposurePointSupported indicates if the camera supports setting an exposure point.
* @param focusPointSupported indicates if the camera supports setting a focus point.
*/
void sendCameraInitializedEvent(
Integer previewWidth,
Integer previewHeight,
ExposureMode exposureMode,
FocusMode focusMode,
Boolean exposurePointSupported,
Boolean focusPointSupported) {
assert (previewWidth != null);
assert (previewHeight != null);
assert (exposureMode != null);
assert (focusMode != null);
assert (exposurePointSupported != null);
assert (focusPointSupported != null);
this.send(
CameraEventType.INITIALIZED,
new HashMap<String, Object>() {
{
put("previewWidth", previewWidth.doubleValue());
put("previewHeight", previewHeight.doubleValue());
put("exposureMode", exposureMode.toString());
put("focusMode", focusMode.toString());
put("exposurePointSupported", exposurePointSupported);
put("focusPointSupported", focusPointSupported);
}
});
}
/** Sends a message to the Flutter client informing that the camera is closing. */
void sendCameraClosingEvent() {
send(CameraEventType.CLOSING);
}
/**
* Sends a message to the Flutter client informing that an error occurred while interacting with
* the camera.
*
* @param description contains details regarding the error that occurred.
*/
void sendCameraErrorEvent(@Nullable String description) {
this.send(
CameraEventType.ERROR,
new HashMap<String, Object>() {
{
if (!TextUtils.isEmpty(description)) put("description", description);
}
});
}
private void send(CameraEventType eventType) {
send(eventType, new HashMap<>());
}
private void send(CameraEventType eventType, Map<String, Object> args) {
if (cameraChannel == null) {
return;
}
handler.post(
new Runnable() {
@Override
public void run() {
cameraChannel.invokeMethod(eventType.method, args);
}
});
}
private void send(DeviceEventType eventType) {
send(eventType, new HashMap<>());
}
private void send(DeviceEventType eventType, Map<String, Object> args) {
if (deviceChannel == null) {
return;
}
handler.post(
new Runnable() {
@Override
public void run() {
deviceChannel.invokeMethod(eventType.method, args);
}
});
}
/**
* Send a success payload to a {@link MethodChannel.Result} on the main thread.
*
* @param payload The payload to send.
*/
public void finish(MethodChannel.Result result, Object payload) {
handler.post(() -> result.success(payload));
}
/**
* Send an error payload to a {@link MethodChannel.Result} on the main thread.
*
* @param errorCode error code.
* @param errorMessage error message.
* @param errorDetails error details.
*/
public void error(
MethodChannel.Result result,
String errorCode,
@Nullable String errorMessage,
@Nullable Object errorDetails) {
handler.post(() -> result.error(errorCode, errorMessage, errorDetails));
}
}