diff --git a/packages/camera/camera_android_camerax/android/build.gradle b/packages/camera/camera_android_camerax/android/build.gradle index a3f20e236a3d..2a9c3905efd4 100644 --- a/packages/camera/camera_android_camerax/android/build.gradle +++ b/packages/camera/camera_android_camerax/android/build.gradle @@ -68,4 +68,5 @@ dependencies { testImplementation 'org.mockito:mockito-inline:5.0.0' testImplementation 'androidx.test:core:1.4.0' testImplementation 'org.robolectric:robolectric:4.10.3' + implementation "androidx.camera:camera-view:${camerax_version}" } diff --git a/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/CameraAndroidCameraxPlugin.java b/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/CameraAndroidCameraxPlugin.java index 42e5df0f32c1..139d5621991d 100644 --- a/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/CameraAndroidCameraxPlugin.java +++ b/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/CameraAndroidCameraxPlugin.java @@ -15,6 +15,9 @@ import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding; import io.flutter.plugin.common.BinaryMessenger; import io.flutter.view.TextureRegistry; +import androidx.camera.view.PreviewView; + +import android.util.Log; /** Platform implementation of the camera_plugin implemented with the CameraX library. */ public final class CameraAndroidCameraxPlugin implements FlutterPlugin, ActivityAware { @@ -40,6 +43,8 @@ public final class CameraAndroidCameraxPlugin implements FlutterPlugin, Activity @VisibleForTesting public @Nullable LiveDataHostApiImpl liveDataHostApiImpl; + public NativeViewFactory nativeViewFactory; + /** * Initialize this within the {@code #configureFlutterEngine} of a Flutter activity or fragment. * @@ -83,7 +88,7 @@ public void setUp( GeneratedCameraXLibrary.DeviceOrientationManagerHostApi.setup( binaryMessenger, deviceOrientationManagerHostApiImpl); GeneratedCameraXLibrary.PreviewHostApi.setup( - binaryMessenger, new PreviewHostApiImpl(binaryMessenger, instanceManager, textureRegistry)); + binaryMessenger, new PreviewHostApiImpl(binaryMessenger, instanceManager, textureRegistry, nativeViewFactory)); imageCaptureHostApiImpl = new ImageCaptureHostApiImpl(binaryMessenger, instanceManager, context); GeneratedCameraXLibrary.ImageCaptureHostApi.setup(binaryMessenger, imageCaptureHostApiImpl); @@ -143,6 +148,11 @@ public void setUp( @Override public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBinding) { pluginBinding = flutterPluginBinding; + Log.e("CAMILLE", "hey"); + nativeViewFactory = new NativeViewFactory(); + flutterPluginBinding + .getPlatformViewRegistry() + .registerViewFactory("", nativeViewFactory); } @Override @@ -168,7 +178,7 @@ public void onAttachedToActivity(@NonNull ActivityPluginBinding activityPluginBi // Set permissions registry reference. systemServicesHostApiImpl.setPermissionsRegistry( activityPluginBinding::addRequestPermissionsResultListener); - } +} @Override public void onDetachedFromActivityForConfigChanges() { diff --git a/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/NativeView.java b/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/NativeView.java new file mode 100644 index 000000000000..ca76ea8934b3 --- /dev/null +++ b/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/NativeView.java @@ -0,0 +1,36 @@ +package io.flutter.plugins.camerax; + +import android.content.Context; +import android.graphics.Color; +import android.view.View; +import android.widget.TextView; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import io.flutter.plugin.platform.PlatformView; +import java.util.Map; +import androidx.camera.view.PreviewView; +import androidx.annotation.Nullable; + + +class NativeView implements PlatformView { + @NonNull private final TextView textView; + @NonNull private final PreviewView previewView; + + NativeView(@NonNull Context context, int id, @Nullable Map creationParams) { + textView = new TextView(context); + textView.setTextSize(72); + textView.setBackgroundColor(Color.rgb(255, 255, 255)); + textView.setText("Rendered on a native Android view (id: " + id + ")"); + + previewView = new PreviewView(context); + } + + @NonNull + @Override + public View getView() { + return previewView; + } + + @Override + public void dispose() {} +} \ No newline at end of file diff --git a/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/NativeViewFactory.java b/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/NativeViewFactory.java new file mode 100644 index 000000000000..16a489479c6f --- /dev/null +++ b/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/NativeViewFactory.java @@ -0,0 +1,32 @@ +package io.flutter.plugins.camerax; + +import android.content.Context; +import androidx.annotation.Nullable; +import androidx.annotation.NonNull; +import io.flutter.plugin.common.StandardMessageCodec; +import io.flutter.plugin.platform.PlatformView; +import io.flutter.plugin.platform.PlatformViewFactory; +import java.util.Map; +import android.view.View; + +class NativeViewFactory extends PlatformViewFactory { + + NativeViewFactory() { + super(StandardMessageCodec.INSTANCE); + } + + NativeView view2; + + @NonNull + @Override + @SuppressWarnings("unchecked") + public PlatformView create(@NonNull Context context, int id, @Nullable Object args) { + final Map creationParams = (Map) args; + view2 = new NativeView(context, id, creationParams); + return view2; + } + + public View getView2() { + return view2.getView(); + } +} \ No newline at end of file diff --git a/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/PreviewHostApiImpl.java b/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/PreviewHostApiImpl.java index 92202dd74dcf..0f43b80bff85 100644 --- a/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/PreviewHostApiImpl.java +++ b/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/PreviewHostApiImpl.java @@ -17,6 +17,7 @@ import io.flutter.view.TextureRegistry; import java.util.Objects; import java.util.concurrent.Executors; +import androidx.camera.view.PreviewView; public class PreviewHostApiImpl implements PreviewHostApi { final BinaryMessenger binaryMessenger; @@ -25,14 +26,17 @@ public class PreviewHostApiImpl implements PreviewHostApi { @VisibleForTesting public @NonNull CameraXProxy cameraXProxy = new CameraXProxy(); @VisibleForTesting public @Nullable TextureRegistry.SurfaceProducer flutterSurfaceProducer; + public NativeViewFactory nativeViewFactory; public PreviewHostApiImpl( @NonNull BinaryMessenger binaryMessenger, @NonNull InstanceManager instanceManager, - @NonNull TextureRegistry textureRegistry) { + @NonNull TextureRegistry textureRegistry, + NativeViewFactory nativeViewFactory) { this.binaryMessenger = binaryMessenger; this.instanceManager = instanceManager; this.textureRegistry = textureRegistry; + this.nativeViewFactory = nativeViewFactory; } /** Creates a {@link Preview} with the target rotation and resolution if specified. */ @@ -61,11 +65,14 @@ public void create( @Override public @NonNull Long setSurfaceProvider(@NonNull Long identifier) { Preview preview = getPreviewInstance(identifier); - flutterSurfaceProducer = textureRegistry.createSurfaceProducer(); - Preview.SurfaceProvider surfaceProvider = createSurfaceProvider(flutterSurfaceProducer); - preview.setSurfaceProvider(surfaceProvider); - - return flutterSurfaceProducer.id(); + // flutterSurfaceProducer = textureRegistry.createSurfaceProducer(); + // Preview.SurfaceProvider surfaceProvider = createSurfaceProvider(flutterSurfaceProducer); + // preview.setSurfaceProvider(surfaceProvider); + PreviewView previewView = (PreviewView) nativeViewFactory.getView2(); + preview.setSurfaceProvider(previewView.getSurfaceProvider()); + + return 3L; + // return flutterSurfaceProducer.id(); } /** diff --git a/packages/camera/camera_android_camerax/example/android/app/build.gradle b/packages/camera/camera_android_camerax/example/android/app/build.gradle index aa54980dd3ba..b68640c5263d 100644 --- a/packages/camera/camera_android_camerax/example/android/app/build.gradle +++ b/packages/camera/camera_android_camerax/example/android/app/build.gradle @@ -55,8 +55,15 @@ flutter { } dependencies { + def camerax_version = "1.4.1" testImplementation 'junit:junit:4.13.2' androidTestImplementation 'androidx.test:runner:1.2.0' androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' api 'androidx.test:core:1.4.0' + implementation "androidx.camera:camera-core:${camerax_version}" + implementation "androidx.camera:camera-camera2:${camerax_version}" + implementation "androidx.camera:camera-lifecycle:${camerax_version}" + implementation "androidx.camera:camera-video:${camerax_version}" + implementation "androidx.camera:camera-view:${camerax_version}" + } diff --git a/packages/camera/camera_android_camerax/example/android/app/src/main/java/io/flutter/plugins/cameraxexample/MainActivity.java b/packages/camera/camera_android_camerax/example/android/app/src/main/java/io/flutter/plugins/cameraxexample/MainActivity.java index 5e2a10f1555a..2db772e1fd6a 100644 --- a/packages/camera/camera_android_camerax/example/android/app/src/main/java/io/flutter/plugins/cameraxexample/MainActivity.java +++ b/packages/camera/camera_android_camerax/example/android/app/src/main/java/io/flutter/plugins/cameraxexample/MainActivity.java @@ -4,6 +4,63 @@ package io.flutter.plugins.cameraxexample; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import io.flutter.embedding.android.FlutterActivity; +import io.flutter.embedding.engine.FlutterEngine; +import androidx.camera.lifecycle.ProcessCameraProvider; +import com.google.common.util.concurrent.ListenableFuture; +import android.os.Bundle; +import androidx.lifecycle.LifecycleOwner; +import androidx.camera.core.CameraSelector; +import androidx.core.content.ContextCompat; +import java.util.concurrent.ExecutionException; +import androidx.camera.core.Preview; +import androidx.camera.view.PreviewView; +import android.util.Log; -public class MainActivity extends FlutterActivity {} +public class MainActivity extends FlutterActivity { + // private ListenableFuture cameraProviderFuture; + // NativeViewFactory nativeViewFactory; + + @Override + public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) { + // nativeViewFactory = new NativeViewFactory(); + // flutterEngine + // .getPlatformViewsController() + // .getRegistry() + // .registerViewFactory("", nativeViewFactory); + } + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + // Log.e("CAMILLE", "oncreate!"); + // cameraProviderFuture = ProcessCameraProvider.getInstance(this); + // cameraProviderFuture.addListener(() -> { + // try { + // ProcessCameraProvider cameraProvider = cameraProviderFuture.get(); + // bindPreview(cameraProvider); + // } catch (ExecutionException | InterruptedException e) { + // // No errors need to be handled for this Future. + // // This should never be reached. + // } + // }, ContextCompat.getMainExecutor(this)); + + } + +// void bindPreview(@NonNull ProcessCameraProvider cameraProvider) { +// Preview preview = new Preview.Builder() +// .build(); + +// CameraSelector cameraSelector = new CameraSelector.Builder() +// .requireLensFacing(CameraSelector.LENS_FACING_BACK) +// .build(); + +// PreviewView previewView = (PreviewView) nativeViewFactory.getView2(); +// preview.setSurfaceProvider(previewView.getSurfaceProvider()); + +// cameraProvider.bindToLifecycle((LifecycleOwner)this, cameraSelector, preview); +// } +} diff --git a/packages/camera/camera_android_camerax/example/lib/camera_preview.dart b/packages/camera/camera_android_camerax/example/lib/camera_preview.dart index 3baaaf8b1fa1..82fba13d9cff 100644 --- a/packages/camera/camera_android_camerax/example/lib/camera_preview.dart +++ b/packages/camera/camera_android_camerax/example/lib/camera_preview.dart @@ -47,7 +47,6 @@ class CameraPreview extends StatelessWidget { if (kIsWeb || defaultTargetPlatform != TargetPlatform.android) { return child; } - return RotatedBox( quarterTurns: _getQuarterTurns(), child: child, diff --git a/packages/camera/camera_android_camerax/lib/src/android_camera_camerax.dart b/packages/camera/camera_android_camerax/lib/src/android_camera_camerax.dart index 31cde2fa0fcb..30f0fe261e0e 100644 --- a/packages/camera/camera_android_camerax/lib/src/android_camera_camerax.dart +++ b/packages/camera/camera_android_camerax/lib/src/android_camera_camerax.dart @@ -7,11 +7,14 @@ import 'dart:math' show Point; import 'package:async/async.dart'; import 'package:camera_platform_interface/camera_platform_interface.dart'; -import 'package:flutter/services.dart' - show DeviceOrientation, PlatformException; +import 'package:flutter/services.dart'; + // show DeviceOrientation, PlatformException; import 'package:flutter/widgets.dart' show Size, Texture, Widget, visibleForTesting; import 'package:stream_transform/stream_transform.dart'; +import 'package:flutter/foundation.dart'; +// import 'package:flutter/services.dart'; +import 'package:flutter/material.dart' show AndroidView; import 'analyzer.dart'; import 'aspect_ratio_strategy.dart'; @@ -836,8 +839,18 @@ class AndroidCameraCameraX extends CameraPlatform { ); } - return Texture(textureId: cameraId); - } + // This is used in the platform side to register the view. + const String viewType = ''; + // Pass parameters to the platform side. + final Map creationParams = {}; + + return AndroidView( + viewType: viewType, + layoutDirection: TextDirection.ltr, + creationParams: creationParams, + creationParamsCodec: const StandardMessageCodec(), + ); + } /// Captures an image and returns the file where it was saved. ///