addCaptureRequestOptionsFuture =
+ pigeonInstance.addCaptureRequestOptions(bundle);
+
+ Futures.addCallback(
+ addCaptureRequestOptionsFuture,
+ new FutureCallback<>() {
+ @Override
+ public void onSuccess(Void voidResult) {
+ ResultCompat.success(null, callback);
+ }
+
+ @Override
+ public void onFailure(@NonNull Throwable t) {
+ ResultCompat.failure(t, callback);
+ }
+ },
+ ContextCompat.getMainExecutor(getPigeonRegistrar().getContext()));
+ }
+}
diff --git a/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/Camera2CameraInfoProxyApi.java b/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/Camera2CameraInfoProxyApi.java
new file mode 100644
index 0000000..8f64ad0
--- /dev/null
+++ b/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/Camera2CameraInfoProxyApi.java
@@ -0,0 +1,67 @@
+// Copyright 2013 The Flutter Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package io.flutter.plugins.camerax;
+
+import android.hardware.camera2.CameraCharacteristics;
+import android.hardware.camera2.CameraMetadata;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.OptIn;
+import androidx.camera.camera2.interop.Camera2CameraInfo;
+import androidx.camera.camera2.interop.ExperimentalCamera2Interop;
+import androidx.camera.core.CameraInfo;
+
+/**
+ * ProxyApi implementation for {@link Camera2CameraInfo}. This class may handle instantiating native
+ * object instances that are attached to a Dart instance or handle method calls on the associated
+ * native class or an instance of that class.
+ */
+@OptIn(markerClass = ExperimentalCamera2Interop.class)
+class Camera2CameraInfoProxyApi extends PigeonApiCamera2CameraInfo {
+ Camera2CameraInfoProxyApi(@NonNull ProxyApiRegistrar pigeonRegistrar) {
+ super(pigeonRegistrar);
+ }
+
+ @NonNull
+ @Override
+ public Camera2CameraInfo from(@NonNull CameraInfo cameraInfo) {
+ return Camera2CameraInfo.from(cameraInfo);
+ }
+
+ @NonNull
+ @Override
+ public String getCameraId(Camera2CameraInfo pigeonInstance) {
+ return pigeonInstance.getCameraId();
+ }
+
+ @Nullable
+ @Override
+ public Object getCameraCharacteristic(
+ Camera2CameraInfo pigeonInstance, @NonNull CameraCharacteristics.Key> key) {
+ final Object result = pigeonInstance.getCameraCharacteristic(key);
+ if (result == null) {
+ return null;
+ }
+
+ if (CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL.equals(key)) {
+ switch ((Integer) result) {
+ case CameraMetadata.INFO_SUPPORTED_HARDWARE_LEVEL_3:
+ return InfoSupportedHardwareLevel.LEVEL3;
+ case CameraMetadata.INFO_SUPPORTED_HARDWARE_LEVEL_EXTERNAL:
+ return InfoSupportedHardwareLevel.EXTERNAL;
+ case CameraMetadata.INFO_SUPPORTED_HARDWARE_LEVEL_FULL:
+ return InfoSupportedHardwareLevel.FULL;
+ case CameraMetadata.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY:
+ return InfoSupportedHardwareLevel.LEGACY;
+ case CameraMetadata.INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED:
+ return InfoSupportedHardwareLevel.LIMITED;
+ default:
+ // Fall through to return result.
+ break;
+ }
+ }
+ return result;
+ }
+}
diff --git a/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/CameraAndroidCameraxPlugin.java b/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/CameraAndroidCameraxPlugin.java
new file mode 100644
index 0000000..0391021
--- /dev/null
+++ b/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/CameraAndroidCameraxPlugin.java
@@ -0,0 +1,85 @@
+// Copyright 2013 The Flutter Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package io.flutter.plugins.camerax;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
+import io.flutter.embedding.engine.plugins.FlutterPlugin;
+import io.flutter.embedding.engine.plugins.activity.ActivityAware;
+import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding;
+
+/** Platform implementation of the camera_plugin implemented with the CameraX library. */
+public final class CameraAndroidCameraxPlugin implements FlutterPlugin, ActivityAware {
+ private FlutterPluginBinding pluginBinding;
+ @VisibleForTesting @Nullable ProxyApiRegistrar proxyApiRegistrar;
+
+ /**
+ * Initialize this within the {@code #configureFlutterEngine} of a Flutter activity or fragment.
+ *
+ * See {@code io.flutter.plugins.camera.MainActivity} for an example.
+ */
+ public CameraAndroidCameraxPlugin() {}
+
+ @Override
+ public void onAttachedToEngine(@NonNull FlutterPluginBinding binding) {
+ pluginBinding = binding;
+
+ proxyApiRegistrar =
+ new ProxyApiRegistrar(
+ binding.getBinaryMessenger(),
+ binding.getApplicationContext(),
+ binding.getTextureRegistry());
+ proxyApiRegistrar.setUp();
+ }
+
+ @Override
+ public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {
+ if (proxyApiRegistrar != null) {
+ proxyApiRegistrar.setIgnoreCallsToDart(true);
+ proxyApiRegistrar.tearDown();
+ proxyApiRegistrar.getInstanceManager().stopFinalizationListener();
+ proxyApiRegistrar = null;
+ }
+ }
+
+ // Activity Lifecycle methods:
+
+ @Override
+ public void onAttachedToActivity(@NonNull ActivityPluginBinding activityPluginBinding) {
+ if (proxyApiRegistrar != null) {
+ proxyApiRegistrar.setContext(activityPluginBinding.getActivity());
+ proxyApiRegistrar.setPermissionsRegistry(
+ activityPluginBinding::addRequestPermissionsResultListener);
+ }
+ }
+
+ @Override
+ public void onDetachedFromActivityForConfigChanges() {
+ if (proxyApiRegistrar != null) {
+ proxyApiRegistrar.setContext(pluginBinding.getApplicationContext());
+ proxyApiRegistrar.setPermissionsRegistry(null);
+ }
+ }
+
+ @Override
+ public void onReattachedToActivityForConfigChanges(
+ @NonNull ActivityPluginBinding activityPluginBinding) {
+ if (proxyApiRegistrar != null) {
+ proxyApiRegistrar.setContext(activityPluginBinding.getActivity());
+ proxyApiRegistrar.setPermissionsRegistry(
+ activityPluginBinding::addRequestPermissionsResultListener);
+ }
+ }
+
+ @Override
+ public void onDetachedFromActivity() {
+ // Clear any references to previously attached `ActivityPluginBinding`/`Activity`.
+ if (proxyApiRegistrar != null) {
+ proxyApiRegistrar.setContext(pluginBinding.getApplicationContext());
+ proxyApiRegistrar.setPermissionsRegistry(null);
+ }
+ }
+}
diff --git a/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/CameraCharacteristicsProxyApi.java b/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/CameraCharacteristicsProxyApi.java
new file mode 100644
index 0000000..d19d8bc
--- /dev/null
+++ b/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/CameraCharacteristicsProxyApi.java
@@ -0,0 +1,37 @@
+// Copyright 2013 The Flutter Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package io.flutter.plugins.camerax;
+
+import android.hardware.camera2.CameraCharacteristics;
+import androidx.annotation.NonNull;
+
+/**
+ * ProxyApi implementation for {@link CameraCharacteristics}. This class may handle instantiating
+ * native object instances that are attached to a Dart instance or handle method calls on the
+ * associated native class or an instance of that class.
+ */
+class CameraCharacteristicsProxyApi extends PigeonApiCameraCharacteristics {
+ CameraCharacteristicsProxyApi(@NonNull ProxyApiRegistrar pigeonRegistrar) {
+ super(pigeonRegistrar);
+ }
+
+ @NonNull
+ @Override
+ public CameraCharacteristics.Key> infoSupportedHardwareLevel() {
+ return CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL;
+ }
+
+ @NonNull
+ @Override
+ public CameraCharacteristics.Key> sensorOrientation() {
+ return CameraCharacteristics.SENSOR_ORIENTATION;
+ }
+
+ @NonNull
+ @Override
+ public CameraCharacteristics.Key> controlAvailableVideoStabilizationModes() {
+ return CameraCharacteristics.CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES;
+ }
+}
diff --git a/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/CameraControlProxyApi.java b/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/CameraControlProxyApi.java
new file mode 100644
index 0000000..a037297
--- /dev/null
+++ b/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/CameraControlProxyApi.java
@@ -0,0 +1,174 @@
+// Copyright 2013 The Flutter Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package io.flutter.plugins.camerax;
+
+import androidx.annotation.NonNull;
+import androidx.camera.core.CameraControl;
+import androidx.camera.core.FocusMeteringAction;
+import androidx.camera.core.FocusMeteringResult;
+import androidx.core.content.ContextCompat;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import kotlin.Result;
+import kotlin.Unit;
+import kotlin.jvm.functions.Function1;
+
+/**
+ * ProxyApi implementation for {@link CameraControl}. This class may handle instantiating native
+ * object instances that are attached to a Dart instance or handle method calls on the associated
+ * native class or an instance of that class.
+ */
+class CameraControlProxyApi extends PigeonApiCameraControl {
+ CameraControlProxyApi(@NonNull ProxyApiRegistrar pigeonRegistrar) {
+ super(pigeonRegistrar);
+ }
+
+ @NonNull
+ @Override
+ public ProxyApiRegistrar getPigeonRegistrar() {
+ return (ProxyApiRegistrar) super.getPigeonRegistrar();
+ }
+
+ @Override
+ public void enableTorch(
+ @NonNull CameraControl pigeonInstance,
+ boolean torch,
+ @NonNull Function1 super Result, Unit> callback) {
+ final ListenableFuture enableTorchFuture = pigeonInstance.enableTorch(torch);
+
+ Futures.addCallback(
+ enableTorchFuture,
+ new FutureCallback<>() {
+ @Override
+ public void onSuccess(Void voidResult) {
+ ResultCompat.success(null, callback);
+ }
+
+ @Override
+ public void onFailure(@NonNull Throwable t) {
+ ResultCompat.failure(t, callback);
+ }
+ },
+ ContextCompat.getMainExecutor(getPigeonRegistrar().getContext()));
+ }
+
+ @Override
+ public void setZoomRatio(
+ @NonNull CameraControl pigeonInstance,
+ double ratio,
+ @NonNull Function1 super Result, Unit> callback) {
+ float ratioAsFloat = (float) ratio;
+ final ListenableFuture setZoomRatioFuture = pigeonInstance.setZoomRatio(ratioAsFloat);
+
+ Futures.addCallback(
+ setZoomRatioFuture,
+ new FutureCallback<>() {
+ @Override
+ public void onSuccess(Void voidResult) {
+ ResultCompat.success(null, callback);
+ }
+
+ @Override
+ public void onFailure(@NonNull Throwable t) {
+ if (t instanceof CameraControl.OperationCanceledException) {
+ // Operation was canceled due to camera being closed or a new request was
+ // submitted, which is not actionable and should not block a new value from
+ // potentially being submitted.
+ ResultCompat.success(null, callback);
+ return;
+ }
+
+ ResultCompat.failure(t, callback);
+ }
+ },
+ ContextCompat.getMainExecutor(getPigeonRegistrar().getContext()));
+ }
+
+ @Override
+ public void startFocusAndMetering(
+ @NonNull CameraControl pigeonInstance,
+ @NonNull FocusMeteringAction action,
+ @NonNull Function1 super Result, Unit> callback) {
+ ListenableFuture focusMeteringResultFuture =
+ pigeonInstance.startFocusAndMetering(action);
+
+ Futures.addCallback(
+ focusMeteringResultFuture,
+ new FutureCallback<>() {
+ @Override
+ public void onSuccess(FocusMeteringResult focusMeteringResult) {
+ ResultCompat.success(focusMeteringResult, callback);
+ }
+
+ @Override
+ public void onFailure(@NonNull Throwable t) {
+ if (t instanceof CameraControl.OperationCanceledException) {
+ // Operation was canceled due to camera being closed or a new request was
+ // submitted, which is not actionable and should not block a new value from
+ // potentially being submitted.
+ ResultCompat.success(null, callback);
+ return;
+ }
+ ResultCompat.failure(t, callback);
+ }
+ },
+ ContextCompat.getMainExecutor(getPigeonRegistrar().getContext()));
+ }
+
+ @Override
+ public void cancelFocusAndMetering(
+ @NonNull CameraControl pigeonInstance,
+ @NonNull Function1 super Result, Unit> callback) {
+ final ListenableFuture