mirror of
https://github.com/flutter/packages.git
synced 2025-06-29 14:18:54 +08:00
[camerax] Wrap classes to implement resolution configuration for image capture, image analysis, and preview (#4523)
Wraps classes to implement resolution configuration for image capture, image analysis, and preview. Also bumps CameraX version to latest and removes the deprecated classes used previously. No functionality changes. Also thanks to @bparrishMines who did majority of the work here! Part of https://github.com/flutter/flutter/issues/120462
This commit is contained in:
@ -1,3 +1,9 @@
|
||||
## 0.5.0+12
|
||||
|
||||
* Wraps classes needed to implement resolution configuration for image capture, image analysis, and preview.
|
||||
* Removes usages of deprecated APIs for resolution configuration.
|
||||
* Bumps CameraX version to 1.3.0-beta01.
|
||||
|
||||
## 0.5.0+11
|
||||
|
||||
* Fixes issue with image data not being emitted after relistening to stream returned by `onStreamedFrameAvailable`.
|
||||
|
@ -61,7 +61,7 @@ android {
|
||||
|
||||
dependencies {
|
||||
// CameraX core library using the camera2 implementation must use same version number.
|
||||
def camerax_version = "1.3.0-alpha05"
|
||||
def camerax_version = "1.3.0-beta01"
|
||||
implementation "androidx.camera:camera-core:${camerax_version}"
|
||||
implementation "androidx.camera:camera-camera2:${camerax_version}"
|
||||
implementation "androidx.camera:camera-lifecycle:${camerax_version}"
|
||||
|
@ -0,0 +1,65 @@
|
||||
// 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.camerax;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.camera.core.resolutionselector.AspectRatioStrategy;
|
||||
import io.flutter.plugins.camerax.GeneratedCameraXLibrary.AspectRatioStrategyHostApi;
|
||||
|
||||
/**
|
||||
* Host API implementation for {@link AspectRatioStrategy}.
|
||||
*
|
||||
* <p>This class handles instantiating and adding native object instances that are attached to a
|
||||
* Dart instance or handle method calls on the associated native class or an instance of the class.
|
||||
*/
|
||||
public class AspectRatioStrategyHostApiImpl implements AspectRatioStrategyHostApi {
|
||||
private final InstanceManager instanceManager;
|
||||
private final AspectRatioStrategyProxy proxy;
|
||||
|
||||
/** Proxy for constructors and static method of {@link AspectRatioStrategy}. */
|
||||
@VisibleForTesting
|
||||
public static class AspectRatioStrategyProxy {
|
||||
/** Creates an instance of {@link AspectRatioStrategy}. */
|
||||
@NonNull
|
||||
public AspectRatioStrategy create(
|
||||
@NonNull Long preferredAspectRatio, @NonNull Long fallbackRule) {
|
||||
return new AspectRatioStrategy(preferredAspectRatio.intValue(), fallbackRule.intValue());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an {@link AspectRatioStrategyHostApiImpl}.
|
||||
*
|
||||
* @param instanceManager maintains instances stored to communicate with attached Dart objects
|
||||
*/
|
||||
public AspectRatioStrategyHostApiImpl(@NonNull InstanceManager instanceManager) {
|
||||
this(instanceManager, new AspectRatioStrategyProxy());
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an {@link AspectRatioStrategyHostApiImpl}.
|
||||
*
|
||||
* @param instanceManager maintains instances stored to communicate with attached Dart objects
|
||||
* @param proxy proxy for constructors and static method of {@link AspectRatioStrategy}
|
||||
*/
|
||||
@VisibleForTesting
|
||||
AspectRatioStrategyHostApiImpl(
|
||||
@NonNull InstanceManager instanceManager, @NonNull AspectRatioStrategyProxy proxy) {
|
||||
this.instanceManager = instanceManager;
|
||||
this.proxy = proxy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an {@link AspectRatioStrategy} instance with the preferred aspect ratio and fallback
|
||||
* rule specified.
|
||||
*/
|
||||
@Override
|
||||
public void create(
|
||||
@NonNull Long identifier, @NonNull Long preferredAspectRatio, @NonNull Long fallbackRule) {
|
||||
instanceManager.addDartCreatedInstance(
|
||||
proxy.create(preferredAspectRatio, fallbackRule), identifier);
|
||||
}
|
||||
}
|
@ -97,6 +97,12 @@ public final class CameraAndroidCameraxPlugin implements FlutterPlugin, Activity
|
||||
binaryMessenger, pendingRecordingHostApiImpl);
|
||||
videoCaptureHostApiImpl = new VideoCaptureHostApiImpl(binaryMessenger, instanceManager);
|
||||
GeneratedCameraXLibrary.VideoCaptureHostApi.setup(binaryMessenger, videoCaptureHostApiImpl);
|
||||
GeneratedCameraXLibrary.ResolutionSelectorHostApi.setup(
|
||||
binaryMessenger, new ResolutionSelectorHostApiImpl(instanceManager));
|
||||
GeneratedCameraXLibrary.ResolutionStrategyHostApi.setup(
|
||||
binaryMessenger, new ResolutionStrategyHostApiImpl(instanceManager));
|
||||
GeneratedCameraXLibrary.AspectRatioStrategyHostApi.setup(
|
||||
binaryMessenger, new AspectRatioStrategyHostApiImpl(instanceManager));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -76,6 +76,23 @@ public class GeneratedCameraXLibrary {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The types (T) properly wrapped to be used as a LiveData<T>.
|
||||
*
|
||||
* <p>If you need to add another type to support a type S to use a LiveData<S> in this plugin,
|
||||
* ensure the following is done on the Dart side:
|
||||
*
|
||||
* <p>* In `../lib/src/live_data.dart`, add new cases for S in
|
||||
* `_LiveDataHostApiImpl#getValueFromInstances` to get the current value of type S from a
|
||||
* LiveData<S> instance and in `LiveDataFlutterApiImpl#create` to create the expected type of
|
||||
* LiveData<S> when requested.
|
||||
*
|
||||
* <p>On the native side, ensure the following is done:
|
||||
*
|
||||
* <p>* Update `LiveDataHostApiImpl#getValue` is updated to properly return identifiers for
|
||||
* instances of type S. * Update `ObserverFlutterApiWrapper#onChanged` to properly handle
|
||||
* receiving calls with instances of type S if a LiveData<S> instance is observed.
|
||||
*/
|
||||
public enum LiveDataSupportedType {
|
||||
CAMERA_STATE(0),
|
||||
ZOOM_STATE(1);
|
||||
@ -1297,8 +1314,6 @@ public class GeneratedCameraXLibrary {
|
||||
switch (type) {
|
||||
case (byte) 128:
|
||||
return ResolutionInfo.fromList((ArrayList<Object>) readValue(buffer));
|
||||
case (byte) 129:
|
||||
return ResolutionInfo.fromList((ArrayList<Object>) readValue(buffer));
|
||||
default:
|
||||
return super.readValueOfType(type, buffer);
|
||||
}
|
||||
@ -1309,9 +1324,6 @@ public class GeneratedCameraXLibrary {
|
||||
if (value instanceof ResolutionInfo) {
|
||||
stream.write(128);
|
||||
writeValue(stream, ((ResolutionInfo) value).toList());
|
||||
} else if (value instanceof ResolutionInfo) {
|
||||
stream.write(129);
|
||||
writeValue(stream, ((ResolutionInfo) value).toList());
|
||||
} else {
|
||||
super.writeValue(stream, value);
|
||||
}
|
||||
@ -1322,9 +1334,7 @@ public class GeneratedCameraXLibrary {
|
||||
public interface PreviewHostApi {
|
||||
|
||||
void create(
|
||||
@NonNull Long identifier,
|
||||
@Nullable Long rotation,
|
||||
@Nullable ResolutionInfo targetResolution);
|
||||
@NonNull Long identifier, @Nullable Long rotation, @Nullable Long resolutionSelectorId);
|
||||
|
||||
@NonNull
|
||||
Long setSurfaceProvider(@NonNull Long identifier);
|
||||
@ -1351,12 +1361,14 @@ public class GeneratedCameraXLibrary {
|
||||
ArrayList<Object> args = (ArrayList<Object>) message;
|
||||
Number identifierArg = (Number) args.get(0);
|
||||
Number rotationArg = (Number) args.get(1);
|
||||
ResolutionInfo targetResolutionArg = (ResolutionInfo) args.get(2);
|
||||
Number resolutionSelectorIdArg = (Number) args.get(2);
|
||||
try {
|
||||
api.create(
|
||||
(identifierArg == null) ? null : identifierArg.longValue(),
|
||||
(rotationArg == null) ? null : rotationArg.longValue(),
|
||||
targetResolutionArg);
|
||||
(resolutionSelectorIdArg == null)
|
||||
? null
|
||||
: resolutionSelectorIdArg.longValue());
|
||||
wrapped.add(0, null);
|
||||
} catch (Throwable exception) {
|
||||
ArrayList<Object> wrappedError = wrapError(exception);
|
||||
@ -1911,40 +1923,11 @@ public class GeneratedCameraXLibrary {
|
||||
channelReply -> callback.reply(null));
|
||||
}
|
||||
}
|
||||
|
||||
private static class ImageCaptureHostApiCodec extends StandardMessageCodec {
|
||||
public static final ImageCaptureHostApiCodec INSTANCE = new ImageCaptureHostApiCodec();
|
||||
|
||||
private ImageCaptureHostApiCodec() {}
|
||||
|
||||
@Override
|
||||
protected Object readValueOfType(byte type, @NonNull ByteBuffer buffer) {
|
||||
switch (type) {
|
||||
case (byte) 128:
|
||||
return ResolutionInfo.fromList((ArrayList<Object>) readValue(buffer));
|
||||
default:
|
||||
return super.readValueOfType(type, buffer);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeValue(@NonNull ByteArrayOutputStream stream, Object value) {
|
||||
if (value instanceof ResolutionInfo) {
|
||||
stream.write(128);
|
||||
writeValue(stream, ((ResolutionInfo) value).toList());
|
||||
} else {
|
||||
super.writeValue(stream, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Generated interface from Pigeon that represents a handler of messages from Flutter. */
|
||||
public interface ImageCaptureHostApi {
|
||||
|
||||
void create(
|
||||
@NonNull Long identifier,
|
||||
@Nullable Long flashMode,
|
||||
@Nullable ResolutionInfo targetResolution);
|
||||
@NonNull Long identifier, @Nullable Long flashMode, @Nullable Long resolutionSelectorId);
|
||||
|
||||
void setFlashMode(@NonNull Long identifier, @NonNull Long flashMode);
|
||||
|
||||
@ -1952,7 +1935,7 @@ public class GeneratedCameraXLibrary {
|
||||
|
||||
/** The codec used by ImageCaptureHostApi. */
|
||||
static @NonNull MessageCodec<Object> getCodec() {
|
||||
return ImageCaptureHostApiCodec.INSTANCE;
|
||||
return new StandardMessageCodec();
|
||||
}
|
||||
/**
|
||||
* Sets up an instance of `ImageCaptureHostApi` to handle messages through the
|
||||
@ -1970,12 +1953,14 @@ public class GeneratedCameraXLibrary {
|
||||
ArrayList<Object> args = (ArrayList<Object>) message;
|
||||
Number identifierArg = (Number) args.get(0);
|
||||
Number flashModeArg = (Number) args.get(1);
|
||||
ResolutionInfo targetResolutionArg = (ResolutionInfo) args.get(2);
|
||||
Number resolutionSelectorIdArg = (Number) args.get(2);
|
||||
try {
|
||||
api.create(
|
||||
(identifierArg == null) ? null : identifierArg.longValue(),
|
||||
(flashModeArg == null) ? null : flashModeArg.longValue(),
|
||||
targetResolutionArg);
|
||||
(resolutionSelectorIdArg == null)
|
||||
? null
|
||||
: resolutionSelectorIdArg.longValue());
|
||||
wrapped.add(0, null);
|
||||
} catch (Throwable exception) {
|
||||
ArrayList<Object> wrappedError = wrapError(exception);
|
||||
@ -2046,6 +2031,182 @@ public class GeneratedCameraXLibrary {
|
||||
}
|
||||
}
|
||||
|
||||
private static class ResolutionStrategyHostApiCodec extends StandardMessageCodec {
|
||||
public static final ResolutionStrategyHostApiCodec INSTANCE =
|
||||
new ResolutionStrategyHostApiCodec();
|
||||
|
||||
private ResolutionStrategyHostApiCodec() {}
|
||||
|
||||
@Override
|
||||
protected Object readValueOfType(byte type, @NonNull ByteBuffer buffer) {
|
||||
switch (type) {
|
||||
case (byte) 128:
|
||||
return ResolutionInfo.fromList((ArrayList<Object>) readValue(buffer));
|
||||
default:
|
||||
return super.readValueOfType(type, buffer);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeValue(@NonNull ByteArrayOutputStream stream, Object value) {
|
||||
if (value instanceof ResolutionInfo) {
|
||||
stream.write(128);
|
||||
writeValue(stream, ((ResolutionInfo) value).toList());
|
||||
} else {
|
||||
super.writeValue(stream, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Generated interface from Pigeon that represents a handler of messages from Flutter. */
|
||||
public interface ResolutionStrategyHostApi {
|
||||
|
||||
void create(
|
||||
@NonNull Long identifier, @Nullable ResolutionInfo boundSize, @Nullable Long fallbackRule);
|
||||
|
||||
/** The codec used by ResolutionStrategyHostApi. */
|
||||
static @NonNull MessageCodec<Object> getCodec() {
|
||||
return ResolutionStrategyHostApiCodec.INSTANCE;
|
||||
}
|
||||
/**
|
||||
* Sets up an instance of `ResolutionStrategyHostApi` to handle messages through the
|
||||
* `binaryMessenger`.
|
||||
*/
|
||||
static void setup(
|
||||
@NonNull BinaryMessenger binaryMessenger, @Nullable ResolutionStrategyHostApi api) {
|
||||
{
|
||||
BasicMessageChannel<Object> channel =
|
||||
new BasicMessageChannel<>(
|
||||
binaryMessenger, "dev.flutter.pigeon.ResolutionStrategyHostApi.create", getCodec());
|
||||
if (api != null) {
|
||||
channel.setMessageHandler(
|
||||
(message, reply) -> {
|
||||
ArrayList<Object> wrapped = new ArrayList<Object>();
|
||||
ArrayList<Object> args = (ArrayList<Object>) message;
|
||||
Number identifierArg = (Number) args.get(0);
|
||||
ResolutionInfo boundSizeArg = (ResolutionInfo) args.get(1);
|
||||
Number fallbackRuleArg = (Number) args.get(2);
|
||||
try {
|
||||
api.create(
|
||||
(identifierArg == null) ? null : identifierArg.longValue(),
|
||||
boundSizeArg,
|
||||
(fallbackRuleArg == null) ? null : fallbackRuleArg.longValue());
|
||||
wrapped.add(0, null);
|
||||
} catch (Throwable exception) {
|
||||
ArrayList<Object> wrappedError = wrapError(exception);
|
||||
wrapped = wrappedError;
|
||||
}
|
||||
reply.reply(wrapped);
|
||||
});
|
||||
} else {
|
||||
channel.setMessageHandler(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/** Generated interface from Pigeon that represents a handler of messages from Flutter. */
|
||||
public interface ResolutionSelectorHostApi {
|
||||
|
||||
void create(
|
||||
@NonNull Long identifier,
|
||||
@Nullable Long resolutionStrategyIdentifier,
|
||||
@Nullable Long aspectRatioStrategyIdentifier);
|
||||
|
||||
/** The codec used by ResolutionSelectorHostApi. */
|
||||
static @NonNull MessageCodec<Object> getCodec() {
|
||||
return new StandardMessageCodec();
|
||||
}
|
||||
/**
|
||||
* Sets up an instance of `ResolutionSelectorHostApi` to handle messages through the
|
||||
* `binaryMessenger`.
|
||||
*/
|
||||
static void setup(
|
||||
@NonNull BinaryMessenger binaryMessenger, @Nullable ResolutionSelectorHostApi api) {
|
||||
{
|
||||
BasicMessageChannel<Object> channel =
|
||||
new BasicMessageChannel<>(
|
||||
binaryMessenger, "dev.flutter.pigeon.ResolutionSelectorHostApi.create", getCodec());
|
||||
if (api != null) {
|
||||
channel.setMessageHandler(
|
||||
(message, reply) -> {
|
||||
ArrayList<Object> wrapped = new ArrayList<Object>();
|
||||
ArrayList<Object> args = (ArrayList<Object>) message;
|
||||
Number identifierArg = (Number) args.get(0);
|
||||
Number resolutionStrategyIdentifierArg = (Number) args.get(1);
|
||||
Number aspectRatioStrategyIdentifierArg = (Number) args.get(2);
|
||||
try {
|
||||
api.create(
|
||||
(identifierArg == null) ? null : identifierArg.longValue(),
|
||||
(resolutionStrategyIdentifierArg == null)
|
||||
? null
|
||||
: resolutionStrategyIdentifierArg.longValue(),
|
||||
(aspectRatioStrategyIdentifierArg == null)
|
||||
? null
|
||||
: aspectRatioStrategyIdentifierArg.longValue());
|
||||
wrapped.add(0, null);
|
||||
} catch (Throwable exception) {
|
||||
ArrayList<Object> wrappedError = wrapError(exception);
|
||||
wrapped = wrappedError;
|
||||
}
|
||||
reply.reply(wrapped);
|
||||
});
|
||||
} else {
|
||||
channel.setMessageHandler(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/** Generated interface from Pigeon that represents a handler of messages from Flutter. */
|
||||
public interface AspectRatioStrategyHostApi {
|
||||
|
||||
void create(
|
||||
@NonNull Long identifier, @NonNull Long preferredAspectRatio, @NonNull Long fallbackRule);
|
||||
|
||||
/** The codec used by AspectRatioStrategyHostApi. */
|
||||
static @NonNull MessageCodec<Object> getCodec() {
|
||||
return new StandardMessageCodec();
|
||||
}
|
||||
/**
|
||||
* Sets up an instance of `AspectRatioStrategyHostApi` to handle messages through the
|
||||
* `binaryMessenger`.
|
||||
*/
|
||||
static void setup(
|
||||
@NonNull BinaryMessenger binaryMessenger, @Nullable AspectRatioStrategyHostApi api) {
|
||||
{
|
||||
BasicMessageChannel<Object> channel =
|
||||
new BasicMessageChannel<>(
|
||||
binaryMessenger,
|
||||
"dev.flutter.pigeon.AspectRatioStrategyHostApi.create",
|
||||
getCodec());
|
||||
if (api != null) {
|
||||
channel.setMessageHandler(
|
||||
(message, reply) -> {
|
||||
ArrayList<Object> wrapped = new ArrayList<Object>();
|
||||
ArrayList<Object> args = (ArrayList<Object>) message;
|
||||
Number identifierArg = (Number) args.get(0);
|
||||
Number preferredAspectRatioArg = (Number) args.get(1);
|
||||
Number fallbackRuleArg = (Number) args.get(2);
|
||||
try {
|
||||
api.create(
|
||||
(identifierArg == null) ? null : identifierArg.longValue(),
|
||||
(preferredAspectRatioArg == null)
|
||||
? null
|
||||
: preferredAspectRatioArg.longValue(),
|
||||
(fallbackRuleArg == null) ? null : fallbackRuleArg.longValue());
|
||||
wrapped.add(0, null);
|
||||
} catch (Throwable exception) {
|
||||
ArrayList<Object> wrappedError = wrapError(exception);
|
||||
wrapped = wrappedError;
|
||||
}
|
||||
reply.reply(wrapped);
|
||||
});
|
||||
} else {
|
||||
channel.setMessageHandler(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class CameraStateFlutterApiCodec extends StandardMessageCodec {
|
||||
public static final CameraStateFlutterApiCodec INSTANCE = new CameraStateFlutterApiCodec();
|
||||
|
||||
@ -2194,37 +2355,10 @@ public class GeneratedCameraXLibrary {
|
||||
channelReply -> callback.reply(null));
|
||||
}
|
||||
}
|
||||
|
||||
private static class ImageAnalysisHostApiCodec extends StandardMessageCodec {
|
||||
public static final ImageAnalysisHostApiCodec INSTANCE = new ImageAnalysisHostApiCodec();
|
||||
|
||||
private ImageAnalysisHostApiCodec() {}
|
||||
|
||||
@Override
|
||||
protected Object readValueOfType(byte type, @NonNull ByteBuffer buffer) {
|
||||
switch (type) {
|
||||
case (byte) 128:
|
||||
return ResolutionInfo.fromList((ArrayList<Object>) readValue(buffer));
|
||||
default:
|
||||
return super.readValueOfType(type, buffer);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeValue(@NonNull ByteArrayOutputStream stream, Object value) {
|
||||
if (value instanceof ResolutionInfo) {
|
||||
stream.write(128);
|
||||
writeValue(stream, ((ResolutionInfo) value).toList());
|
||||
} else {
|
||||
super.writeValue(stream, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Generated interface from Pigeon that represents a handler of messages from Flutter. */
|
||||
public interface ImageAnalysisHostApi {
|
||||
|
||||
void create(@NonNull Long identifier, @Nullable ResolutionInfo targetResolutionIdentifier);
|
||||
void create(@NonNull Long identifier, @Nullable Long resolutionSelectorId);
|
||||
|
||||
void setAnalyzer(@NonNull Long identifier, @NonNull Long analyzerIdentifier);
|
||||
|
||||
@ -2232,7 +2366,7 @@ public class GeneratedCameraXLibrary {
|
||||
|
||||
/** The codec used by ImageAnalysisHostApi. */
|
||||
static @NonNull MessageCodec<Object> getCodec() {
|
||||
return ImageAnalysisHostApiCodec.INSTANCE;
|
||||
return new StandardMessageCodec();
|
||||
}
|
||||
/**
|
||||
* Sets up an instance of `ImageAnalysisHostApi` to handle messages through the
|
||||
@ -2250,11 +2384,13 @@ public class GeneratedCameraXLibrary {
|
||||
ArrayList<Object> wrapped = new ArrayList<Object>();
|
||||
ArrayList<Object> args = (ArrayList<Object>) message;
|
||||
Number identifierArg = (Number) args.get(0);
|
||||
ResolutionInfo targetResolutionIdentifierArg = (ResolutionInfo) args.get(1);
|
||||
Number resolutionSelectorIdArg = (Number) args.get(1);
|
||||
try {
|
||||
api.create(
|
||||
(identifierArg == null) ? null : identifierArg.longValue(),
|
||||
targetResolutionIdentifierArg);
|
||||
(resolutionSelectorIdArg == null)
|
||||
? null
|
||||
: resolutionSelectorIdArg.longValue());
|
||||
wrapped.add(0, null);
|
||||
} catch (Throwable exception) {
|
||||
ArrayList<Object> wrappedError = wrapError(exception);
|
||||
|
@ -9,10 +9,10 @@ import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.camera.core.ImageAnalysis;
|
||||
import androidx.camera.core.resolutionselector.ResolutionSelector;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import io.flutter.plugin.common.BinaryMessenger;
|
||||
import io.flutter.plugins.camerax.GeneratedCameraXLibrary.ImageAnalysisHostApi;
|
||||
import io.flutter.plugins.camerax.GeneratedCameraXLibrary.ResolutionInfo;
|
||||
import java.util.Objects;
|
||||
|
||||
public class ImageAnalysisHostApiImpl implements ImageAnalysisHostApi {
|
||||
@ -38,11 +38,13 @@ public class ImageAnalysisHostApiImpl implements ImageAnalysisHostApi {
|
||||
|
||||
/** Creates an {@link ImageAnalysis} instance with the target resolution if specified. */
|
||||
@Override
|
||||
public void create(@NonNull Long identifier, @Nullable ResolutionInfo targetResolution) {
|
||||
public void create(@NonNull Long identifier, @Nullable Long resolutionSelectorId) {
|
||||
ImageAnalysis.Builder imageAnalysisBuilder = cameraXProxy.createImageAnalysisBuilder();
|
||||
|
||||
if (targetResolution != null) {
|
||||
imageAnalysisBuilder.setTargetResolution(CameraXProxy.sizeFromResolution(targetResolution));
|
||||
if (resolutionSelectorId != null) {
|
||||
ResolutionSelector resolutionSelector =
|
||||
Objects.requireNonNull(instanceManager.getInstance(resolutionSelectorId));
|
||||
imageAnalysisBuilder.setResolutionSelector(resolutionSelector);
|
||||
}
|
||||
|
||||
ImageAnalysis imageAnalysis = imageAnalysisBuilder.build();
|
||||
|
@ -10,6 +10,7 @@ import androidx.annotation.Nullable;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.camera.core.ImageCapture;
|
||||
import androidx.camera.core.ImageCaptureException;
|
||||
import androidx.camera.core.resolutionselector.ResolutionSelector;
|
||||
import io.flutter.plugin.common.BinaryMessenger;
|
||||
import io.flutter.plugins.camerax.GeneratedCameraXLibrary.ImageCaptureHostApi;
|
||||
import java.io.File;
|
||||
@ -52,17 +53,19 @@ public class ImageCaptureHostApiImpl implements ImageCaptureHostApi {
|
||||
*/
|
||||
@Override
|
||||
public void create(
|
||||
@NonNull Long identifier,
|
||||
@Nullable Long flashMode,
|
||||
@Nullable GeneratedCameraXLibrary.ResolutionInfo targetResolution) {
|
||||
@NonNull Long identifier, @Nullable Long flashMode, @Nullable Long resolutionSelectorId) {
|
||||
ImageCapture.Builder imageCaptureBuilder = cameraXProxy.createImageCaptureBuilder();
|
||||
|
||||
if (flashMode != null) {
|
||||
// This sets the requested flash mode, but may fail silently.
|
||||
imageCaptureBuilder.setFlashMode(flashMode.intValue());
|
||||
}
|
||||
if (targetResolution != null) {
|
||||
imageCaptureBuilder.setTargetResolution(CameraXProxy.sizeFromResolution(targetResolution));
|
||||
if (resolutionSelectorId != null) {
|
||||
ResolutionSelector resolutionSelector =
|
||||
Objects.requireNonNull(instanceManager.getInstance(resolutionSelectorId));
|
||||
imageCaptureBuilder.setResolutionSelector(resolutionSelector);
|
||||
}
|
||||
|
||||
ImageCapture imageCapture = imageCaptureBuilder.build();
|
||||
instanceManager.addDartCreatedInstance(imageCapture, identifier);
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ import androidx.annotation.Nullable;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.camera.core.Preview;
|
||||
import androidx.camera.core.SurfaceRequest;
|
||||
import androidx.camera.core.resolutionselector.ResolutionSelector;
|
||||
import io.flutter.plugin.common.BinaryMessenger;
|
||||
import io.flutter.plugins.camerax.GeneratedCameraXLibrary.PreviewHostApi;
|
||||
import io.flutter.view.TextureRegistry;
|
||||
@ -38,16 +39,18 @@ public class PreviewHostApiImpl implements PreviewHostApi {
|
||||
/** Creates a {@link Preview} with the target rotation and resolution if specified. */
|
||||
@Override
|
||||
public void create(
|
||||
@NonNull Long identifier,
|
||||
@Nullable Long rotation,
|
||||
@Nullable GeneratedCameraXLibrary.ResolutionInfo targetResolution) {
|
||||
@NonNull Long identifier, @Nullable Long rotation, @Nullable Long resolutionSelectorId) {
|
||||
Preview.Builder previewBuilder = cameraXProxy.createPreviewBuilder();
|
||||
|
||||
if (rotation != null) {
|
||||
previewBuilder.setTargetRotation(rotation.intValue());
|
||||
}
|
||||
if (targetResolution != null) {
|
||||
previewBuilder.setTargetResolution(CameraXProxy.sizeFromResolution(targetResolution));
|
||||
if (resolutionSelectorId != null) {
|
||||
ResolutionSelector resolutionSelector =
|
||||
Objects.requireNonNull(instanceManager.getInstance(resolutionSelectorId));
|
||||
previewBuilder.setResolutionSelector(resolutionSelector);
|
||||
}
|
||||
|
||||
Preview preview = previewBuilder.build();
|
||||
instanceManager.addDartCreatedInstance(preview, identifier);
|
||||
}
|
||||
|
@ -0,0 +1,87 @@
|
||||
// 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.camerax;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.camera.core.resolutionselector.AspectRatioStrategy;
|
||||
import androidx.camera.core.resolutionselector.ResolutionSelector;
|
||||
import androidx.camera.core.resolutionselector.ResolutionStrategy;
|
||||
import io.flutter.plugins.camerax.GeneratedCameraXLibrary.ResolutionSelectorHostApi;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Host API implementation for {@link ResolutionSelector}.
|
||||
*
|
||||
* <p>This class handles instantiating and adding native object instances that are attached to a
|
||||
* Dart instance or handle method calls on the associated native class or an instance of the class.
|
||||
*/
|
||||
public class ResolutionSelectorHostApiImpl implements ResolutionSelectorHostApi {
|
||||
private final InstanceManager instanceManager;
|
||||
private final ResolutionSelectorProxy proxy;
|
||||
|
||||
/** Proxy for constructors and static method of {@link ResolutionSelector}. */
|
||||
@VisibleForTesting
|
||||
public static class ResolutionSelectorProxy {
|
||||
/** Creates an instance of {@link ResolutionSelector}. */
|
||||
@NonNull
|
||||
public ResolutionSelector create(
|
||||
@Nullable ResolutionStrategy resolutionStrategy,
|
||||
@Nullable AspectRatioStrategy aspectRatioStrategy) {
|
||||
final ResolutionSelector.Builder builder = new ResolutionSelector.Builder();
|
||||
if (resolutionStrategy != null) {
|
||||
builder.setResolutionStrategy(resolutionStrategy);
|
||||
}
|
||||
if (aspectRatioStrategy != null) {
|
||||
builder.setAspectRatioStrategy(aspectRatioStrategy);
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a {@link ResolutionSelectorHostApiImpl}.
|
||||
*
|
||||
* @param instanceManager maintains instances stored to communicate with attached Dart objects
|
||||
*/
|
||||
public ResolutionSelectorHostApiImpl(@NonNull InstanceManager instanceManager) {
|
||||
this(instanceManager, new ResolutionSelectorProxy());
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a {@link ResolutionSelectorHostApiImpl}.
|
||||
*
|
||||
* @param instanceManager maintains instances stored to communicate with attached Dart objects
|
||||
* @param proxy proxy for constructors and static method of {@link ResolutionSelector}
|
||||
*/
|
||||
@VisibleForTesting
|
||||
ResolutionSelectorHostApiImpl(
|
||||
@NonNull InstanceManager instanceManager, @NonNull ResolutionSelectorProxy proxy) {
|
||||
this.instanceManager = instanceManager;
|
||||
this.proxy = proxy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link ResolutionSelector} instance with the {@link ResolutionStrategy} and {@link
|
||||
* AspectRatio} that have the identifiers specified if provided.
|
||||
*/
|
||||
@Override
|
||||
public void create(
|
||||
@NonNull Long identifier,
|
||||
@Nullable Long resolutionStrategyIdentifier,
|
||||
@Nullable Long aspectRatioStrategyIdentifier) {
|
||||
instanceManager.addDartCreatedInstance(
|
||||
proxy.create(
|
||||
resolutionStrategyIdentifier == null
|
||||
? null
|
||||
: Objects.requireNonNull(instanceManager.getInstance(resolutionStrategyIdentifier)),
|
||||
aspectRatioStrategyIdentifier == null
|
||||
? null
|
||||
: Objects.requireNonNull(
|
||||
instanceManager.getInstance(aspectRatioStrategyIdentifier))),
|
||||
identifier);
|
||||
}
|
||||
}
|
@ -0,0 +1,81 @@
|
||||
// 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.camerax;
|
||||
|
||||
import android.util.Size;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.camera.core.resolutionselector.ResolutionStrategy;
|
||||
import io.flutter.plugins.camerax.GeneratedCameraXLibrary.ResolutionStrategyHostApi;
|
||||
|
||||
/**
|
||||
* Host API implementation for {@link ResolutionStrategy}.
|
||||
*
|
||||
* <p>This class handles instantiating and adding native object instances that are attached to a
|
||||
* Dart instance or handle method calls on the associated native class or an instance of the class.
|
||||
*/
|
||||
public class ResolutionStrategyHostApiImpl implements ResolutionStrategyHostApi {
|
||||
private final InstanceManager instanceManager;
|
||||
private final ResolutionStrategyProxy proxy;
|
||||
|
||||
/** Proxy for constructors and static method of {@link ResolutionStrategy}. */
|
||||
@VisibleForTesting
|
||||
public static class ResolutionStrategyProxy {
|
||||
|
||||
/** Creates an instance of {@link ResolutionStrategy}. */
|
||||
@NonNull
|
||||
public ResolutionStrategy create(@NonNull Size boundSize, @NonNull Long fallbackRule) {
|
||||
return new ResolutionStrategy(boundSize, fallbackRule.intValue());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a {@link ResolutionStrategyHostApiImpl}.
|
||||
*
|
||||
* @param instanceManager maintains instances stored to communicate with attached Dart objects
|
||||
*/
|
||||
public ResolutionStrategyHostApiImpl(@NonNull InstanceManager instanceManager) {
|
||||
this(instanceManager, new ResolutionStrategyProxy());
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a {@link ResolutionStrategyHostApiImpl}.
|
||||
*
|
||||
* @param instanceManager maintains instances stored to communicate with attached Dart objects
|
||||
* @param proxy proxy for constructors and static method of {@link ResolutionStrategy}
|
||||
*/
|
||||
@VisibleForTesting
|
||||
ResolutionStrategyHostApiImpl(
|
||||
@NonNull InstanceManager instanceManager, @NonNull ResolutionStrategyProxy proxy) {
|
||||
this.instanceManager = instanceManager;
|
||||
this.proxy = proxy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link ResolutionStrategy} instance with the {@link
|
||||
* GeneratedCameraXLibrary.ResolutionInfo} bound size and {@code fallbackRule} if specified.
|
||||
*/
|
||||
@Override
|
||||
public void create(
|
||||
@NonNull Long identifier,
|
||||
@Nullable GeneratedCameraXLibrary.ResolutionInfo boundSize,
|
||||
@Nullable Long fallbackRule) {
|
||||
ResolutionStrategy resolutionStrategy;
|
||||
if (boundSize == null && fallbackRule == null) {
|
||||
// Strategy that chooses the highest available resolution does not have a bound size or fallback rule.
|
||||
resolutionStrategy = ResolutionStrategy.HIGHEST_AVAILABLE_STRATEGY;
|
||||
} else if (boundSize == null) {
|
||||
throw new IllegalArgumentException(
|
||||
"A bound size must be specified if a non-null fallback rule is specified to create a valid ResolutionStrategy.");
|
||||
} else {
|
||||
resolutionStrategy =
|
||||
proxy.create(
|
||||
new Size(boundSize.getWidth().intValue(), boundSize.getHeight().intValue()),
|
||||
fallbackRule);
|
||||
}
|
||||
instanceManager.addDartCreatedInstance(resolutionStrategy, identifier);
|
||||
}
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
// 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.camerax;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import androidx.camera.core.resolutionselector.AspectRatioStrategy;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnit;
|
||||
import org.mockito.junit.MockitoRule;
|
||||
|
||||
public class AspectRatioStrategyTest {
|
||||
@Rule public MockitoRule mockitoRule = MockitoJUnit.rule();
|
||||
@Mock public AspectRatioStrategy mockAspectRatioStrategy;
|
||||
@Mock public AspectRatioStrategyHostApiImpl.AspectRatioStrategyProxy mockProxy;
|
||||
|
||||
InstanceManager instanceManager;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
instanceManager = InstanceManager.create(identifier -> {});
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
instanceManager.stopFinalizationListener();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hostApiCreate_createsExpectedAspectRatioStrategyInstance() {
|
||||
final Long preferredAspectRatio = 0L;
|
||||
final Long fallbackRule = 1L;
|
||||
|
||||
when(mockProxy.create(preferredAspectRatio, fallbackRule)).thenReturn(mockAspectRatioStrategy);
|
||||
|
||||
final AspectRatioStrategyHostApiImpl hostApi =
|
||||
new AspectRatioStrategyHostApiImpl(instanceManager, mockProxy);
|
||||
|
||||
final long instanceIdentifier = 0;
|
||||
hostApi.create(instanceIdentifier, preferredAspectRatio, fallbackRule);
|
||||
|
||||
assertEquals(instanceManager.getInstance(instanceIdentifier), mockAspectRatioStrategy);
|
||||
}
|
||||
}
|
@ -12,18 +12,16 @@ import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.Size;
|
||||
import androidx.camera.core.ImageAnalysis;
|
||||
import androidx.camera.core.resolutionselector.ResolutionSelector;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
import io.flutter.plugin.common.BinaryMessenger;
|
||||
import io.flutter.plugins.camerax.GeneratedCameraXLibrary.ResolutionInfo;
|
||||
import java.util.concurrent.Executor;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnit;
|
||||
import org.mockito.junit.MockitoRule;
|
||||
@ -55,27 +53,19 @@ public class ImageAnalysisTest {
|
||||
new ImageAnalysisHostApiImpl(mockBinaryMessenger, instanceManager);
|
||||
final CameraXProxy mockCameraXProxy = mock(CameraXProxy.class);
|
||||
final ImageAnalysis.Builder mockImageAnalysisBuilder = mock(ImageAnalysis.Builder.class);
|
||||
final int targetResolutionWidth = 10;
|
||||
final int targetResolutionHeight = 50;
|
||||
final ResolutionInfo resolutionInfo =
|
||||
new ResolutionInfo.Builder()
|
||||
.setWidth(Long.valueOf(targetResolutionWidth))
|
||||
.setHeight(Long.valueOf(targetResolutionHeight))
|
||||
.build();
|
||||
final ResolutionSelector mockResolutionSelector = mock(ResolutionSelector.class);
|
||||
final long instanceIdentifier = 0;
|
||||
final long mockResolutionSelectorId = 25;
|
||||
|
||||
hostApi.cameraXProxy = mockCameraXProxy;
|
||||
|
||||
final ArgumentCaptor<Size> sizeCaptor = ArgumentCaptor.forClass(Size.class);
|
||||
instanceManager.addDartCreatedInstance(mockResolutionSelector, mockResolutionSelectorId);
|
||||
|
||||
when(mockCameraXProxy.createImageAnalysisBuilder()).thenReturn(mockImageAnalysisBuilder);
|
||||
when(mockImageAnalysisBuilder.build()).thenReturn(mockImageAnalysis);
|
||||
|
||||
hostApi.create(instanceIdentifier, resolutionInfo);
|
||||
hostApi.create(instanceIdentifier, mockResolutionSelectorId);
|
||||
|
||||
verify(mockImageAnalysisBuilder).setTargetResolution(sizeCaptor.capture());
|
||||
assertEquals(sizeCaptor.getValue().getWidth(), targetResolutionWidth);
|
||||
assertEquals(sizeCaptor.getValue().getHeight(), targetResolutionHeight);
|
||||
verify(mockImageAnalysisBuilder).setResolutionSelector(mockResolutionSelector);
|
||||
assertEquals(instanceManager.getInstance(instanceIdentifier), mockImageAnalysis);
|
||||
}
|
||||
|
||||
|
@ -4,7 +4,6 @@
|
||||
|
||||
package io.flutter.plugins.camerax;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
@ -15,9 +14,9 @@ import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.Size;
|
||||
import androidx.camera.core.ImageCapture;
|
||||
import androidx.camera.core.ImageCaptureException;
|
||||
import androidx.camera.core.resolutionselector.ResolutionSelector;
|
||||
import io.flutter.plugin.common.BinaryMessenger;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
@ -27,7 +26,6 @@ import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockedStatic;
|
||||
import org.mockito.junit.MockitoJUnit;
|
||||
@ -66,26 +64,18 @@ public class ImageCaptureTest {
|
||||
final ImageCapture.Builder mockImageCaptureBuilder = mock(ImageCapture.Builder.class);
|
||||
final Long imageCaptureIdentifier = 74L;
|
||||
final Long flashMode = Long.valueOf(ImageCapture.FLASH_MODE_ON);
|
||||
final int targetResolutionWidth = 10;
|
||||
final int targetResolutionHeight = 50;
|
||||
final GeneratedCameraXLibrary.ResolutionInfo resolutionInfo =
|
||||
new GeneratedCameraXLibrary.ResolutionInfo.Builder()
|
||||
.setWidth(Long.valueOf(targetResolutionWidth))
|
||||
.setHeight(Long.valueOf(targetResolutionHeight))
|
||||
.build();
|
||||
final ResolutionSelector mockResolutionSelector = mock(ResolutionSelector.class);
|
||||
final long mockResolutionSelectorId = 77;
|
||||
|
||||
imageCaptureHostApiImpl.cameraXProxy = mockCameraXProxy;
|
||||
testInstanceManager.addDartCreatedInstance(mockResolutionSelector, mockResolutionSelectorId);
|
||||
when(mockCameraXProxy.createImageCaptureBuilder()).thenReturn(mockImageCaptureBuilder);
|
||||
when(mockImageCaptureBuilder.build()).thenReturn(mockImageCapture);
|
||||
|
||||
final ArgumentCaptor<Size> sizeCaptor = ArgumentCaptor.forClass(Size.class);
|
||||
|
||||
imageCaptureHostApiImpl.create(imageCaptureIdentifier, flashMode, resolutionInfo);
|
||||
imageCaptureHostApiImpl.create(imageCaptureIdentifier, flashMode, mockResolutionSelectorId);
|
||||
|
||||
verify(mockImageCaptureBuilder).setFlashMode(flashMode.intValue());
|
||||
verify(mockImageCaptureBuilder).setTargetResolution(sizeCaptor.capture());
|
||||
assertEquals(sizeCaptor.getValue().getWidth(), targetResolutionWidth);
|
||||
assertEquals(sizeCaptor.getValue().getHeight(), targetResolutionHeight);
|
||||
verify(mockImageCaptureBuilder).setResolutionSelector(mockResolutionSelector);
|
||||
verify(mockImageCaptureBuilder).build();
|
||||
verify(testInstanceManager).addDartCreatedInstance(mockImageCapture, imageCaptureIdentifier);
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ import android.util.Size;
|
||||
import android.view.Surface;
|
||||
import androidx.camera.core.Preview;
|
||||
import androidx.camera.core.SurfaceRequest;
|
||||
import androidx.camera.core.resolutionselector.ResolutionSelector;
|
||||
import androidx.core.util.Consumer;
|
||||
import io.flutter.plugin.common.BinaryMessenger;
|
||||
import io.flutter.plugins.camerax.GeneratedCameraXLibrary.ResolutionInfo;
|
||||
@ -63,27 +64,20 @@ public class PreviewTest {
|
||||
new PreviewHostApiImpl(mockBinaryMessenger, testInstanceManager, mockTextureRegistry);
|
||||
final Preview.Builder mockPreviewBuilder = mock(Preview.Builder.class);
|
||||
final int targetRotation = 90;
|
||||
final int targetResolutionWidth = 10;
|
||||
final int targetResolutionHeight = 50;
|
||||
final Long previewIdentifier = 3L;
|
||||
final GeneratedCameraXLibrary.ResolutionInfo resolutionInfo =
|
||||
new GeneratedCameraXLibrary.ResolutionInfo.Builder()
|
||||
.setWidth(Long.valueOf(targetResolutionWidth))
|
||||
.setHeight(Long.valueOf(targetResolutionHeight))
|
||||
.build();
|
||||
final ResolutionSelector mockResolutionSelector = mock(ResolutionSelector.class);
|
||||
final long mockResolutionSelectorId = 90;
|
||||
|
||||
previewHostApi.cameraXProxy = mockCameraXProxy;
|
||||
testInstanceManager.addDartCreatedInstance(mockResolutionSelector, mockResolutionSelectorId);
|
||||
when(mockCameraXProxy.createPreviewBuilder()).thenReturn(mockPreviewBuilder);
|
||||
when(mockPreviewBuilder.build()).thenReturn(mockPreview);
|
||||
|
||||
final ArgumentCaptor<Size> sizeCaptor = ArgumentCaptor.forClass(Size.class);
|
||||
|
||||
previewHostApi.create(previewIdentifier, Long.valueOf(targetRotation), resolutionInfo);
|
||||
previewHostApi.create(
|
||||
previewIdentifier, Long.valueOf(targetRotation), mockResolutionSelectorId);
|
||||
|
||||
verify(mockPreviewBuilder).setTargetRotation(targetRotation);
|
||||
verify(mockPreviewBuilder).setTargetResolution(sizeCaptor.capture());
|
||||
assertEquals(sizeCaptor.getValue().getWidth(), targetResolutionWidth);
|
||||
assertEquals(sizeCaptor.getValue().getHeight(), targetResolutionHeight);
|
||||
verify(mockPreviewBuilder).setResolutionSelector(mockResolutionSelector);
|
||||
verify(mockPreviewBuilder).build();
|
||||
verify(testInstanceManager).addDartCreatedInstance(mockPreview, previewIdentifier);
|
||||
}
|
||||
|
@ -0,0 +1,59 @@
|
||||
// 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.camerax;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import androidx.camera.core.resolutionselector.AspectRatioStrategy;
|
||||
import androidx.camera.core.resolutionselector.ResolutionSelector;
|
||||
import androidx.camera.core.resolutionselector.ResolutionStrategy;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnit;
|
||||
import org.mockito.junit.MockitoRule;
|
||||
|
||||
public class ResolutionSelectorTest {
|
||||
@Rule public MockitoRule mockitoRule = MockitoJUnit.rule();
|
||||
@Mock public ResolutionSelector mockResolutionSelector;
|
||||
@Mock public ResolutionSelectorHostApiImpl.ResolutionSelectorProxy mockProxy;
|
||||
|
||||
InstanceManager instanceManager;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
instanceManager = InstanceManager.create(identifier -> {});
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
instanceManager.stopFinalizationListener();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hostApiCreate_createsExpectedResolutionSelectorInstance() {
|
||||
final ResolutionStrategy mockResolutionStrategy = mock(ResolutionStrategy.class);
|
||||
final long resolutionStrategyIdentifier = 14;
|
||||
instanceManager.addDartCreatedInstance(mockResolutionStrategy, resolutionStrategyIdentifier);
|
||||
|
||||
final AspectRatioStrategy mockAspectRatioStrategy = mock(AspectRatioStrategy.class);
|
||||
final long aspectRatioStrategyIdentifier = 15;
|
||||
instanceManager.addDartCreatedInstance(mockAspectRatioStrategy, aspectRatioStrategyIdentifier);
|
||||
|
||||
when(mockProxy.create(mockResolutionStrategy, mockAspectRatioStrategy))
|
||||
.thenReturn(mockResolutionSelector);
|
||||
final ResolutionSelectorHostApiImpl hostApi =
|
||||
new ResolutionSelectorHostApiImpl(instanceManager, mockProxy);
|
||||
|
||||
final long instanceIdentifier = 0;
|
||||
hostApi.create(instanceIdentifier, resolutionStrategyIdentifier, aspectRatioStrategyIdentifier);
|
||||
|
||||
assertEquals(instanceManager.getInstance(instanceIdentifier), mockResolutionSelector);
|
||||
}
|
||||
}
|
@ -0,0 +1,71 @@
|
||||
// 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.camerax;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertThrows;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.util.Size;
|
||||
import androidx.camera.core.resolutionselector.ResolutionStrategy;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnit;
|
||||
import org.mockito.junit.MockitoRule;
|
||||
|
||||
public class ResolutionStrategyTest {
|
||||
@Rule public MockitoRule mockitoRule = MockitoJUnit.rule();
|
||||
@Mock public ResolutionStrategy mockResolutionStrategy;
|
||||
@Mock public ResolutionStrategyHostApiImpl.ResolutionStrategyProxy mockProxy;
|
||||
|
||||
InstanceManager instanceManager;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
instanceManager = InstanceManager.create(identifier -> {});
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
instanceManager.stopFinalizationListener();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hostApiCreate_createsExpectedResolutionStrategyInstanceWhenArgumentsValid() {
|
||||
final GeneratedCameraXLibrary.ResolutionInfo boundSize =
|
||||
new GeneratedCameraXLibrary.ResolutionInfo.Builder().setWidth(50L).setHeight(30L).build();
|
||||
|
||||
final Long fallbackRule = 0L;
|
||||
|
||||
when(mockProxy.create(any(Size.class), eq(fallbackRule))).thenReturn(mockResolutionStrategy);
|
||||
|
||||
final ResolutionStrategyHostApiImpl hostApi =
|
||||
new ResolutionStrategyHostApiImpl(instanceManager, mockProxy);
|
||||
|
||||
final long instanceIdentifier = 0;
|
||||
hostApi.create(instanceIdentifier, boundSize, fallbackRule);
|
||||
|
||||
assertEquals(instanceManager.getInstance(instanceIdentifier), mockResolutionStrategy);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hostApiCreate_throwsAssertionErrorWhenArgumentsInvalid() {
|
||||
final Long fallbackRule = 8L;
|
||||
final long instanceIdentifier = 0;
|
||||
|
||||
final ResolutionStrategyHostApiImpl hostApi =
|
||||
new ResolutionStrategyHostApiImpl(instanceManager, mockProxy);
|
||||
|
||||
// We expect an exception to be thrown if fallback rule is specified but bound size is not.
|
||||
assertThrows(
|
||||
IllegalArgumentException.class,
|
||||
() -> hostApi.create(instanceIdentifier, null, fallbackRule));
|
||||
}
|
||||
}
|
@ -116,10 +116,6 @@ class AndroidCameraCameraX extends CameraPlatform {
|
||||
@visibleForTesting
|
||||
CameraSelector? cameraSelector;
|
||||
|
||||
/// The resolution preset used to create a camera that should be used for
|
||||
/// capturing still images and recording video.
|
||||
ResolutionPreset? _resolutionPreset;
|
||||
|
||||
/// The controller we need to broadcast the different camera events.
|
||||
///
|
||||
/// It is a `broadcast` because multiple controllers will connect to
|
||||
@ -233,19 +229,17 @@ class AndroidCameraCameraX extends CameraPlatform {
|
||||
processCameraProvider ??= await ProcessCameraProvider.getInstance();
|
||||
processCameraProvider!.unbindAll();
|
||||
|
||||
// TODO(camsim99): Implement resolution configuration for UseCases
|
||||
// configured here. https://github.com/flutter/flutter/issues/120462
|
||||
|
||||
// Configure Preview instance.
|
||||
_resolutionPreset = resolutionPreset;
|
||||
final int targetRotation =
|
||||
_getTargetRotation(cameraDescription.sensorOrientation);
|
||||
final ResolutionInfo? previewTargetResolution =
|
||||
_getTargetResolutionForPreview(resolutionPreset);
|
||||
preview = createPreview(targetRotation, previewTargetResolution);
|
||||
preview = createPreview(targetRotation);
|
||||
final int flutterSurfaceTextureId = await preview!.setSurfaceProvider();
|
||||
|
||||
// Configure ImageCapture instance.
|
||||
final ResolutionInfo? imageCaptureTargetResolution =
|
||||
_getTargetResolutionForImageCapture(_resolutionPreset);
|
||||
imageCapture = createImageCapture(null, imageCaptureTargetResolution);
|
||||
imageCapture = createImageCapture(null);
|
||||
|
||||
// Configure VideoCapture and Recorder instances.
|
||||
// TODO(gmackall): Enable video capture resolution configuration in createRecorder().
|
||||
@ -642,7 +636,7 @@ class AndroidCameraCameraX extends CameraPlatform {
|
||||
|
||||
// TODO(camsim99): Support resolution configuration.
|
||||
// Defaults to YUV_420_888 image format.
|
||||
imageAnalysis ??= createImageAnalysis(null);
|
||||
imageAnalysis ??= createImageAnalysis();
|
||||
unawaited(imageAnalysis!.setAnalyzer(analyzer));
|
||||
|
||||
if (await processCameraProvider!.isBound(imageAnalysis!)) {
|
||||
@ -780,23 +774,6 @@ class AndroidCameraCameraX extends CameraPlatform {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns [ResolutionInfo] that maps to the specified resolution preset for
|
||||
/// a camera preview.
|
||||
ResolutionInfo? _getTargetResolutionForPreview(ResolutionPreset? resolution) {
|
||||
// TODO(camsim99): Implement resolution configuration.
|
||||
// https://github.com/flutter/flutter/issues/120462
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Returns [ResolutionInfo] that maps to the specified resolution preset for
|
||||
/// image capture.
|
||||
ResolutionInfo? _getTargetResolutionForImageCapture(
|
||||
ResolutionPreset? resolution) {
|
||||
// TODO(camsim99): Implement resolution configuration.
|
||||
// https://github.com/flutter/flutter/issues/120462
|
||||
return null;
|
||||
}
|
||||
|
||||
// Methods for calls that need to be tested:
|
||||
|
||||
/// Requests camera permissions.
|
||||
@ -829,18 +806,15 @@ class AndroidCameraCameraX extends CameraPlatform {
|
||||
/// Returns a [Preview] configured with the specified target rotation and
|
||||
/// resolution.
|
||||
@visibleForTesting
|
||||
Preview createPreview(int targetRotation, ResolutionInfo? targetResolution) {
|
||||
return Preview(
|
||||
targetRotation: targetRotation, targetResolution: targetResolution);
|
||||
Preview createPreview(int targetRotation) {
|
||||
return Preview(targetRotation: targetRotation);
|
||||
}
|
||||
|
||||
/// Returns an [ImageCapture] configured with specified flash mode and
|
||||
/// target resolution.
|
||||
@visibleForTesting
|
||||
ImageCapture createImageCapture(
|
||||
int? flashMode, ResolutionInfo? targetResolution) {
|
||||
return ImageCapture(
|
||||
targetFlashMode: flashMode, targetResolution: targetResolution);
|
||||
ImageCapture createImageCapture(int? flashMode) {
|
||||
return ImageCapture(targetFlashMode: flashMode);
|
||||
}
|
||||
|
||||
/// Returns a [Recorder] for use in video capture.
|
||||
@ -857,7 +831,7 @@ class AndroidCameraCameraX extends CameraPlatform {
|
||||
|
||||
/// Returns an [ImageAnalysis] configured with specified target resolution.
|
||||
@visibleForTesting
|
||||
ImageAnalysis createImageAnalysis(ResolutionInfo? targetResolution) {
|
||||
return ImageAnalysis(targetResolution: targetResolution);
|
||||
ImageAnalysis createImageAnalysis() {
|
||||
return ImageAnalysis();
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,138 @@
|
||||
// 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.
|
||||
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:meta/meta.dart' show immutable;
|
||||
|
||||
import 'camerax_library.g.dart';
|
||||
import 'instance_manager.dart';
|
||||
import 'java_object.dart';
|
||||
|
||||
/// The aspect ratio of a UseCase.
|
||||
///
|
||||
/// Aspect ratio is the ratio of width to height.
|
||||
///
|
||||
/// See https://developer.android.com/reference/androidx/camera/core/AspectRatio.
|
||||
class AspectRatio {
|
||||
AspectRatio._();
|
||||
|
||||
/// 4:3 standard aspect ratio.
|
||||
///
|
||||
/// See https://developer.android.com/reference/androidx/camera/core/AspectRatio#RATIO_4_3().
|
||||
static const int ratio4To3 = 0;
|
||||
|
||||
/// 16:9 standard aspect ratio.
|
||||
///
|
||||
/// See https://developer.android.com/reference/androidx/camera/core/AspectRatio#RATIO_16_9().
|
||||
static const int ratio16To9 = 1;
|
||||
|
||||
/// The aspect ratio representing no preference for aspect ratio.
|
||||
///
|
||||
/// See https://developer.android.com/reference/androidx/camera/core/AspectRatio#RATIO_DEFAULT().
|
||||
static const int ratioDefault = -1;
|
||||
}
|
||||
|
||||
/// The aspect ratio strategy defines the sequence of aspect ratios that are
|
||||
/// used to select the best size for a particular image.
|
||||
///
|
||||
/// See https://developer.android.com/reference/androidx/camera/core/resolutionselector/AspectRatioStrategy.
|
||||
@immutable
|
||||
class AspectRatioStrategy extends JavaObject {
|
||||
/// Construct a [AspectRatioStrategy].
|
||||
AspectRatioStrategy({
|
||||
required this.preferredAspectRatio,
|
||||
required this.fallbackRule,
|
||||
super.binaryMessenger,
|
||||
super.instanceManager,
|
||||
}) : _api = _AspectRatioStrategyHostApiImpl(
|
||||
instanceManager: instanceManager,
|
||||
binaryMessenger: binaryMessenger,
|
||||
),
|
||||
super.detached() {
|
||||
_api.createFromInstances(this, preferredAspectRatio, fallbackRule);
|
||||
}
|
||||
|
||||
/// Instantiates a [AspectRatioStrategy] without creating and attaching to an
|
||||
/// instance of the associated native class.
|
||||
///
|
||||
/// This should only be used outside of tests by subclasses created by this
|
||||
/// library or to create a copy for an [InstanceManager].
|
||||
AspectRatioStrategy.detached({
|
||||
required this.preferredAspectRatio,
|
||||
required this.fallbackRule,
|
||||
super.binaryMessenger,
|
||||
super.instanceManager,
|
||||
}) : _api = _AspectRatioStrategyHostApiImpl(
|
||||
instanceManager: instanceManager,
|
||||
binaryMessenger: binaryMessenger,
|
||||
),
|
||||
super.detached();
|
||||
|
||||
/// CameraX doesn't fall back to select sizes of any other aspect ratio when
|
||||
/// this fallback rule is used.
|
||||
///
|
||||
/// See https://developer.android.com/reference/androidx/camera/core/resolutionselector/AspectRatioStrategy#FALLBACK_RULE_NONE().
|
||||
static const int fallbackRuleNone = 0;
|
||||
|
||||
/// CameraX automatically chooses the next best aspect ratio which contains
|
||||
/// the closest field of view (FOV) of the camera sensor, from the remaining
|
||||
/// options.
|
||||
///
|
||||
/// See https://developer.android.com/reference/androidx/camera/core/resolutionselector/AspectRatioStrategy#FALLBACK_RULE_AUTO().
|
||||
static const int fallbackRuleAuto = 1;
|
||||
|
||||
final _AspectRatioStrategyHostApiImpl _api;
|
||||
|
||||
/// The preferred aspect ratio captured by the camera.
|
||||
final int preferredAspectRatio;
|
||||
|
||||
/// The specified fallback rule for choosing the aspect ratio when the
|
||||
/// preferred aspect ratio is not available.
|
||||
final int fallbackRule;
|
||||
}
|
||||
|
||||
/// Host API implementation of [AspectRatioStrategy].
|
||||
class _AspectRatioStrategyHostApiImpl extends AspectRatioStrategyHostApi {
|
||||
/// Constructs an [_AspectRatioStrategyHostApiImpl].
|
||||
///
|
||||
/// If [binaryMessenger] is null, the default [BinaryMessenger] will be used,
|
||||
/// which routes to the host platform.
|
||||
///
|
||||
/// An [instanceManager] is typically passed when a copy of an instance
|
||||
/// contained by an [InstanceManager] is being created. If left null, it
|
||||
/// will default to the global instance defined in [JavaObject].
|
||||
_AspectRatioStrategyHostApiImpl({
|
||||
this.binaryMessenger,
|
||||
InstanceManager? instanceManager,
|
||||
}) : instanceManager = instanceManager ?? JavaObject.globalInstanceManager,
|
||||
super(binaryMessenger: binaryMessenger);
|
||||
|
||||
/// Receives binary data across the Flutter platform barrier.
|
||||
final BinaryMessenger? binaryMessenger;
|
||||
|
||||
/// Maintains instances stored to communicate with native language objects.
|
||||
final InstanceManager instanceManager;
|
||||
|
||||
/// Creates a [AspectRatioStrategy] on the native side with the preferred
|
||||
/// aspect ratio and fallback rule specified.
|
||||
Future<void> createFromInstances(
|
||||
AspectRatioStrategy instance,
|
||||
int preferredAspectRatio,
|
||||
int fallbackRule,
|
||||
) {
|
||||
return create(
|
||||
instanceManager.addDartCreatedInstance(
|
||||
instance,
|
||||
onCopy: (AspectRatioStrategy original) => AspectRatioStrategy.detached(
|
||||
preferredAspectRatio: original.preferredAspectRatio,
|
||||
fallbackRule: original.fallbackRule,
|
||||
binaryMessenger: binaryMessenger,
|
||||
instanceManager: instanceManager,
|
||||
),
|
||||
),
|
||||
preferredAspectRatio,
|
||||
fallbackRule,
|
||||
);
|
||||
}
|
||||
}
|
@ -22,6 +22,22 @@ enum CameraStateType {
|
||||
pendingOpen,
|
||||
}
|
||||
|
||||
/// The types (T) properly wrapped to be used as a LiveData<T>.
|
||||
///
|
||||
/// If you need to add another type to support a type S to use a LiveData<S> in
|
||||
/// this plugin, ensure the following is done on the Dart side:
|
||||
///
|
||||
/// * In `../lib/src/live_data.dart`, add new cases for S in
|
||||
/// `_LiveDataHostApiImpl#getValueFromInstances` to get the current value of
|
||||
/// type S from a LiveData<S> instance and in `LiveDataFlutterApiImpl#create`
|
||||
/// to create the expected type of LiveData<S> when requested.
|
||||
///
|
||||
/// On the native side, ensure the following is done:
|
||||
///
|
||||
/// * Update `LiveDataHostApiImpl#getValue` is updated to properly return
|
||||
/// identifiers for instances of type S.
|
||||
/// * Update `ObserverFlutterApiWrapper#onChanged` to properly handle receiving
|
||||
/// calls with instances of type S if a LiveData<S> instance is observed.
|
||||
enum LiveDataSupportedType {
|
||||
cameraState,
|
||||
zoomState,
|
||||
@ -937,9 +953,6 @@ class _PreviewHostApiCodec extends StandardMessageCodec {
|
||||
if (value is ResolutionInfo) {
|
||||
buffer.putUint8(128);
|
||||
writeValue(buffer, value.encode());
|
||||
} else if (value is ResolutionInfo) {
|
||||
buffer.putUint8(129);
|
||||
writeValue(buffer, value.encode());
|
||||
} else {
|
||||
super.writeValue(buffer, value);
|
||||
}
|
||||
@ -950,8 +963,6 @@ class _PreviewHostApiCodec extends StandardMessageCodec {
|
||||
switch (type) {
|
||||
case 128:
|
||||
return ResolutionInfo.decode(readValue(buffer)!);
|
||||
case 129:
|
||||
return ResolutionInfo.decode(readValue(buffer)!);
|
||||
default:
|
||||
return super.readValueOfType(type, buffer);
|
||||
}
|
||||
@ -969,12 +980,12 @@ class PreviewHostApi {
|
||||
static const MessageCodec<Object?> codec = _PreviewHostApiCodec();
|
||||
|
||||
Future<void> create(int arg_identifier, int? arg_rotation,
|
||||
ResolutionInfo? arg_targetResolution) async {
|
||||
int? arg_resolutionSelectorId) async {
|
||||
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
|
||||
'dev.flutter.pigeon.PreviewHostApi.create', codec,
|
||||
binaryMessenger: _binaryMessenger);
|
||||
final List<Object?>? replyList = await channel
|
||||
.send(<Object?>[arg_identifier, arg_rotation, arg_targetResolution])
|
||||
final List<Object?>? replyList = await channel.send(
|
||||
<Object?>[arg_identifier, arg_rotation, arg_resolutionSelectorId])
|
||||
as List<Object?>?;
|
||||
if (replyList == null) {
|
||||
throw PlatformException(
|
||||
@ -1505,29 +1516,6 @@ abstract class RecordingFlutterApi {
|
||||
}
|
||||
}
|
||||
|
||||
class _ImageCaptureHostApiCodec extends StandardMessageCodec {
|
||||
const _ImageCaptureHostApiCodec();
|
||||
@override
|
||||
void writeValue(WriteBuffer buffer, Object? value) {
|
||||
if (value is ResolutionInfo) {
|
||||
buffer.putUint8(128);
|
||||
writeValue(buffer, value.encode());
|
||||
} else {
|
||||
super.writeValue(buffer, value);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Object? readValueOfType(int type, ReadBuffer buffer) {
|
||||
switch (type) {
|
||||
case 128:
|
||||
return ResolutionInfo.decode(readValue(buffer)!);
|
||||
default:
|
||||
return super.readValueOfType(type, buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ImageCaptureHostApi {
|
||||
/// Constructor for [ImageCaptureHostApi]. The [binaryMessenger] named argument is
|
||||
/// available for dependency injection. If it is left null, the default
|
||||
@ -1536,15 +1524,15 @@ class ImageCaptureHostApi {
|
||||
: _binaryMessenger = binaryMessenger;
|
||||
final BinaryMessenger? _binaryMessenger;
|
||||
|
||||
static const MessageCodec<Object?> codec = _ImageCaptureHostApiCodec();
|
||||
static const MessageCodec<Object?> codec = StandardMessageCodec();
|
||||
|
||||
Future<void> create(int arg_identifier, int? arg_flashMode,
|
||||
ResolutionInfo? arg_targetResolution) async {
|
||||
int? arg_resolutionSelectorId) async {
|
||||
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
|
||||
'dev.flutter.pigeon.ImageCaptureHostApi.create', codec,
|
||||
binaryMessenger: _binaryMessenger);
|
||||
final List<Object?>? replyList = await channel.send(
|
||||
<Object?>[arg_identifier, arg_flashMode, arg_targetResolution])
|
||||
<Object?>[arg_identifier, arg_flashMode, arg_resolutionSelectorId])
|
||||
as List<Object?>?;
|
||||
if (replyList == null) {
|
||||
throw PlatformException(
|
||||
@ -1612,6 +1600,138 @@ class ImageCaptureHostApi {
|
||||
}
|
||||
}
|
||||
|
||||
class _ResolutionStrategyHostApiCodec extends StandardMessageCodec {
|
||||
const _ResolutionStrategyHostApiCodec();
|
||||
@override
|
||||
void writeValue(WriteBuffer buffer, Object? value) {
|
||||
if (value is ResolutionInfo) {
|
||||
buffer.putUint8(128);
|
||||
writeValue(buffer, value.encode());
|
||||
} else {
|
||||
super.writeValue(buffer, value);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Object? readValueOfType(int type, ReadBuffer buffer) {
|
||||
switch (type) {
|
||||
case 128:
|
||||
return ResolutionInfo.decode(readValue(buffer)!);
|
||||
default:
|
||||
return super.readValueOfType(type, buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ResolutionStrategyHostApi {
|
||||
/// Constructor for [ResolutionStrategyHostApi]. The [binaryMessenger] named argument is
|
||||
/// available for dependency injection. If it is left null, the default
|
||||
/// BinaryMessenger will be used which routes to the host platform.
|
||||
ResolutionStrategyHostApi({BinaryMessenger? binaryMessenger})
|
||||
: _binaryMessenger = binaryMessenger;
|
||||
final BinaryMessenger? _binaryMessenger;
|
||||
|
||||
static const MessageCodec<Object?> codec = _ResolutionStrategyHostApiCodec();
|
||||
|
||||
Future<void> create(int arg_identifier, ResolutionInfo? arg_boundSize,
|
||||
int? arg_fallbackRule) async {
|
||||
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
|
||||
'dev.flutter.pigeon.ResolutionStrategyHostApi.create', codec,
|
||||
binaryMessenger: _binaryMessenger);
|
||||
final List<Object?>? replyList = await channel
|
||||
.send(<Object?>[arg_identifier, arg_boundSize, arg_fallbackRule])
|
||||
as List<Object?>?;
|
||||
if (replyList == null) {
|
||||
throw PlatformException(
|
||||
code: 'channel-error',
|
||||
message: 'Unable to establish connection on channel.',
|
||||
);
|
||||
} else if (replyList.length > 1) {
|
||||
throw PlatformException(
|
||||
code: replyList[0]! as String,
|
||||
message: replyList[1] as String?,
|
||||
details: replyList[2],
|
||||
);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ResolutionSelectorHostApi {
|
||||
/// Constructor for [ResolutionSelectorHostApi]. The [binaryMessenger] named argument is
|
||||
/// available for dependency injection. If it is left null, the default
|
||||
/// BinaryMessenger will be used which routes to the host platform.
|
||||
ResolutionSelectorHostApi({BinaryMessenger? binaryMessenger})
|
||||
: _binaryMessenger = binaryMessenger;
|
||||
final BinaryMessenger? _binaryMessenger;
|
||||
|
||||
static const MessageCodec<Object?> codec = StandardMessageCodec();
|
||||
|
||||
Future<void> create(int arg_identifier, int? arg_resolutionStrategyIdentifier,
|
||||
int? arg_aspectRatioStrategyIdentifier) async {
|
||||
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
|
||||
'dev.flutter.pigeon.ResolutionSelectorHostApi.create', codec,
|
||||
binaryMessenger: _binaryMessenger);
|
||||
final List<Object?>? replyList = await channel.send(<Object?>[
|
||||
arg_identifier,
|
||||
arg_resolutionStrategyIdentifier,
|
||||
arg_aspectRatioStrategyIdentifier
|
||||
]) as List<Object?>?;
|
||||
if (replyList == null) {
|
||||
throw PlatformException(
|
||||
code: 'channel-error',
|
||||
message: 'Unable to establish connection on channel.',
|
||||
);
|
||||
} else if (replyList.length > 1) {
|
||||
throw PlatformException(
|
||||
code: replyList[0]! as String,
|
||||
message: replyList[1] as String?,
|
||||
details: replyList[2],
|
||||
);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class AspectRatioStrategyHostApi {
|
||||
/// Constructor for [AspectRatioStrategyHostApi]. The [binaryMessenger] named argument is
|
||||
/// available for dependency injection. If it is left null, the default
|
||||
/// BinaryMessenger will be used which routes to the host platform.
|
||||
AspectRatioStrategyHostApi({BinaryMessenger? binaryMessenger})
|
||||
: _binaryMessenger = binaryMessenger;
|
||||
final BinaryMessenger? _binaryMessenger;
|
||||
|
||||
static const MessageCodec<Object?> codec = StandardMessageCodec();
|
||||
|
||||
Future<void> create(int arg_identifier, int arg_preferredAspectRatio,
|
||||
int arg_fallbackRule) async {
|
||||
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
|
||||
'dev.flutter.pigeon.AspectRatioStrategyHostApi.create', codec,
|
||||
binaryMessenger: _binaryMessenger);
|
||||
final List<Object?>? replyList = await channel.send(<Object?>[
|
||||
arg_identifier,
|
||||
arg_preferredAspectRatio,
|
||||
arg_fallbackRule
|
||||
]) as List<Object?>?;
|
||||
if (replyList == null) {
|
||||
throw PlatformException(
|
||||
code: 'channel-error',
|
||||
message: 'Unable to establish connection on channel.',
|
||||
);
|
||||
} else if (replyList.length > 1) {
|
||||
throw PlatformException(
|
||||
code: replyList[0]! as String,
|
||||
message: replyList[1] as String?,
|
||||
details: replyList[2],
|
||||
);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class _CameraStateFlutterApiCodec extends StandardMessageCodec {
|
||||
const _CameraStateFlutterApiCodec();
|
||||
@override
|
||||
@ -1767,29 +1887,6 @@ abstract class ZoomStateFlutterApi {
|
||||
}
|
||||
}
|
||||
|
||||
class _ImageAnalysisHostApiCodec extends StandardMessageCodec {
|
||||
const _ImageAnalysisHostApiCodec();
|
||||
@override
|
||||
void writeValue(WriteBuffer buffer, Object? value) {
|
||||
if (value is ResolutionInfo) {
|
||||
buffer.putUint8(128);
|
||||
writeValue(buffer, value.encode());
|
||||
} else {
|
||||
super.writeValue(buffer, value);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Object? readValueOfType(int type, ReadBuffer buffer) {
|
||||
switch (type) {
|
||||
case 128:
|
||||
return ResolutionInfo.decode(readValue(buffer)!);
|
||||
default:
|
||||
return super.readValueOfType(type, buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ImageAnalysisHostApi {
|
||||
/// Constructor for [ImageAnalysisHostApi]. The [binaryMessenger] named argument is
|
||||
/// available for dependency injection. If it is left null, the default
|
||||
@ -1798,15 +1895,14 @@ class ImageAnalysisHostApi {
|
||||
: _binaryMessenger = binaryMessenger;
|
||||
final BinaryMessenger? _binaryMessenger;
|
||||
|
||||
static const MessageCodec<Object?> codec = _ImageAnalysisHostApiCodec();
|
||||
static const MessageCodec<Object?> codec = StandardMessageCodec();
|
||||
|
||||
Future<void> create(int arg_identifier,
|
||||
ResolutionInfo? arg_targetResolutionIdentifier) async {
|
||||
Future<void> create(int arg_identifier, int? arg_resolutionSelectorId) async {
|
||||
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
|
||||
'dev.flutter.pigeon.ImageAnalysisHostApi.create', codec,
|
||||
binaryMessenger: _binaryMessenger);
|
||||
final List<Object?>? replyList = await channel
|
||||
.send(<Object?>[arg_identifier, arg_targetResolutionIdentifier])
|
||||
final List<Object?>? replyList =
|
||||
await channel.send(<Object?>[arg_identifier, arg_resolutionSelectorId])
|
||||
as List<Object?>?;
|
||||
if (replyList == null) {
|
||||
throw PlatformException(
|
||||
|
@ -12,6 +12,7 @@ import 'android_camera_camerax_flutter_api_impls.dart';
|
||||
import 'camerax_library.g.dart';
|
||||
import 'instance_manager.dart';
|
||||
import 'java_object.dart';
|
||||
import 'resolution_selector.dart';
|
||||
import 'use_case.dart';
|
||||
|
||||
/// Use case for providing CPU accessible images for performing image analysis.
|
||||
@ -23,13 +24,13 @@ class ImageAnalysis extends UseCase {
|
||||
ImageAnalysis(
|
||||
{BinaryMessenger? binaryMessenger,
|
||||
InstanceManager? instanceManager,
|
||||
this.targetResolution})
|
||||
this.resolutionSelector})
|
||||
: super.detached(
|
||||
binaryMessenger: binaryMessenger,
|
||||
instanceManager: instanceManager) {
|
||||
_api = _ImageAnalysisHostApiImpl(
|
||||
binaryMessenger: binaryMessenger, instanceManager: instanceManager);
|
||||
_api.createfromInstances(this, targetResolution);
|
||||
_api.createfromInstances(this, resolutionSelector);
|
||||
AndroidCameraXCameraFlutterApis.instance.ensureSetUp();
|
||||
}
|
||||
|
||||
@ -37,7 +38,7 @@ class ImageAnalysis extends UseCase {
|
||||
ImageAnalysis.detached(
|
||||
{BinaryMessenger? binaryMessenger,
|
||||
InstanceManager? instanceManager,
|
||||
this.targetResolution})
|
||||
this.resolutionSelector})
|
||||
: super.detached(
|
||||
binaryMessenger: binaryMessenger,
|
||||
instanceManager: instanceManager) {
|
||||
@ -49,7 +50,10 @@ class ImageAnalysis extends UseCase {
|
||||
late final _ImageAnalysisHostApiImpl _api;
|
||||
|
||||
/// Target resolution of the camera preview stream.
|
||||
final ResolutionInfo? targetResolution;
|
||||
///
|
||||
/// If not set, this [UseCase] will default to the behavior described in:
|
||||
/// https://developer.android.com/reference/androidx/camera/core/ImageAnalysis.Builder#setResolutionSelector(androidx.camera.core.resolutionselector.ResolutionSelector).
|
||||
final ResolutionSelector? resolutionSelector;
|
||||
|
||||
/// Sets an [Analyzer] to receive and analyze images.
|
||||
Future<void> setAnalyzer(Analyzer analyzer) =>
|
||||
@ -83,18 +87,20 @@ class _ImageAnalysisHostApiImpl extends ImageAnalysisHostApi {
|
||||
/// on the native side.
|
||||
Future<void> createfromInstances(
|
||||
ImageAnalysis instance,
|
||||
ResolutionInfo? targetResolution,
|
||||
ResolutionSelector? resolutionSelector,
|
||||
) {
|
||||
return create(
|
||||
instanceManager.addDartCreatedInstance(
|
||||
instance,
|
||||
onCopy: (ImageAnalysis original) => ImageAnalysis.detached(
|
||||
targetResolution: original.targetResolution,
|
||||
resolutionSelector: original.resolutionSelector,
|
||||
binaryMessenger: binaryMessenger,
|
||||
instanceManager: instanceManager,
|
||||
),
|
||||
),
|
||||
targetResolution,
|
||||
resolutionSelector == null
|
||||
? null
|
||||
: instanceManager.getIdentifier(resolutionSelector),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -8,6 +8,7 @@ import 'package:meta/meta.dart' show immutable;
|
||||
import 'camerax_library.g.dart';
|
||||
import 'instance_manager.dart';
|
||||
import 'java_object.dart';
|
||||
import 'resolution_selector.dart';
|
||||
import 'use_case.dart';
|
||||
|
||||
/// Use case for picture taking.
|
||||
@ -20,14 +21,14 @@ class ImageCapture extends UseCase {
|
||||
BinaryMessenger? binaryMessenger,
|
||||
InstanceManager? instanceManager,
|
||||
this.targetFlashMode,
|
||||
this.targetResolution,
|
||||
this.resolutionSelector,
|
||||
}) : super.detached(
|
||||
binaryMessenger: binaryMessenger,
|
||||
instanceManager: instanceManager,
|
||||
) {
|
||||
_api = ImageCaptureHostApiImpl(
|
||||
binaryMessenger: binaryMessenger, instanceManager: instanceManager);
|
||||
_api.createFromInstance(this, targetFlashMode, targetResolution);
|
||||
_api.createFromInstance(this, targetFlashMode, resolutionSelector);
|
||||
}
|
||||
|
||||
/// Constructs a [ImageCapture] that is not automatically attached to a native object.
|
||||
@ -35,7 +36,7 @@ class ImageCapture extends UseCase {
|
||||
BinaryMessenger? binaryMessenger,
|
||||
InstanceManager? instanceManager,
|
||||
this.targetFlashMode,
|
||||
this.targetResolution,
|
||||
this.resolutionSelector,
|
||||
}) : super.detached(
|
||||
binaryMessenger: binaryMessenger,
|
||||
instanceManager: instanceManager,
|
||||
@ -50,7 +51,10 @@ class ImageCapture extends UseCase {
|
||||
final int? targetFlashMode;
|
||||
|
||||
/// Target resolution of the image output from taking a picture.
|
||||
final ResolutionInfo? targetResolution;
|
||||
///
|
||||
/// If not set, this [UseCase] will default to the behavior described in:
|
||||
/// https://developer.android.com/reference/androidx/camera/core/ImageCapture.Builder#setResolutionSelector(androidx.camera.core.resolutionselector.ResolutionSelector).
|
||||
final ResolutionSelector? resolutionSelector;
|
||||
|
||||
/// Constant for automatic flash mode.
|
||||
///
|
||||
@ -121,16 +125,21 @@ class ImageCaptureHostApiImpl extends ImageCaptureHostApi {
|
||||
/// Creates an [ImageCapture] instance with the flash mode and target resolution
|
||||
/// if specified.
|
||||
void createFromInstance(ImageCapture instance, int? targetFlashMode,
|
||||
ResolutionInfo? targetResolution) {
|
||||
ResolutionSelector? resolutionSelector) {
|
||||
final int identifier = instanceManager.addDartCreatedInstance(instance,
|
||||
onCopy: (ImageCapture original) {
|
||||
return ImageCapture.detached(
|
||||
binaryMessenger: binaryMessenger,
|
||||
instanceManager: instanceManager,
|
||||
targetFlashMode: original.targetFlashMode,
|
||||
targetResolution: original.targetResolution);
|
||||
resolutionSelector: original.resolutionSelector);
|
||||
});
|
||||
create(identifier, targetFlashMode, targetResolution);
|
||||
create(
|
||||
identifier,
|
||||
targetFlashMode,
|
||||
resolutionSelector == null
|
||||
? null
|
||||
: instanceManager.getIdentifier(resolutionSelector));
|
||||
}
|
||||
|
||||
/// Sets the flash mode for the specified [ImageCapture] instance to take
|
||||
|
@ -8,6 +8,7 @@ import 'package:meta/meta.dart' show immutable;
|
||||
import 'camerax_library.g.dart';
|
||||
import 'instance_manager.dart';
|
||||
import 'java_object.dart';
|
||||
import 'resolution_selector.dart';
|
||||
import 'use_case.dart';
|
||||
|
||||
/// Use case that provides a camera preview stream for display.
|
||||
@ -20,13 +21,13 @@ class Preview extends UseCase {
|
||||
{BinaryMessenger? binaryMessenger,
|
||||
InstanceManager? instanceManager,
|
||||
this.targetRotation,
|
||||
this.targetResolution})
|
||||
this.resolutionSelector})
|
||||
: super.detached(
|
||||
binaryMessenger: binaryMessenger,
|
||||
instanceManager: instanceManager) {
|
||||
_api = PreviewHostApiImpl(
|
||||
binaryMessenger: binaryMessenger, instanceManager: instanceManager);
|
||||
_api.createFromInstance(this, targetRotation, targetResolution);
|
||||
_api.createFromInstance(this, targetRotation, resolutionSelector);
|
||||
}
|
||||
|
||||
/// Constructs a [Preview] that is not automatically attached to a native object.
|
||||
@ -34,7 +35,7 @@ class Preview extends UseCase {
|
||||
{BinaryMessenger? binaryMessenger,
|
||||
InstanceManager? instanceManager,
|
||||
this.targetRotation,
|
||||
this.targetResolution})
|
||||
this.resolutionSelector})
|
||||
: super.detached(
|
||||
binaryMessenger: binaryMessenger,
|
||||
instanceManager: instanceManager) {
|
||||
@ -48,7 +49,10 @@ class Preview extends UseCase {
|
||||
final int? targetRotation;
|
||||
|
||||
/// Target resolution of the camera preview stream.
|
||||
final ResolutionInfo? targetResolution;
|
||||
///
|
||||
/// If not set, this [UseCase] will default to the behavior described in:
|
||||
/// https://developer.android.com/reference/androidx/camera/core/Preview.Builder#setResolutionSelector(androidx.camera.core.resolutionselector.ResolutionSelector).
|
||||
final ResolutionSelector? resolutionSelector;
|
||||
|
||||
/// Sets the surface provider for the preview stream.
|
||||
///
|
||||
@ -92,17 +96,22 @@ class PreviewHostApiImpl extends PreviewHostApi {
|
||||
|
||||
/// Creates a [Preview] with the target rotation and target resolution if
|
||||
/// specified.
|
||||
void createFromInstance(
|
||||
Preview instance, int? targetRotation, ResolutionInfo? targetResolution) {
|
||||
void createFromInstance(Preview instance, int? targetRotation,
|
||||
ResolutionSelector? resolutionSelector) {
|
||||
final int identifier = instanceManager.addDartCreatedInstance(instance,
|
||||
onCopy: (Preview original) {
|
||||
return Preview.detached(
|
||||
binaryMessenger: binaryMessenger,
|
||||
instanceManager: instanceManager,
|
||||
targetRotation: original.targetRotation,
|
||||
targetResolution: original.targetResolution);
|
||||
resolutionSelector: original.resolutionSelector);
|
||||
});
|
||||
create(identifier, targetRotation, targetResolution);
|
||||
create(
|
||||
identifier,
|
||||
targetRotation,
|
||||
resolutionSelector == null
|
||||
? null
|
||||
: instanceManager.getIdentifier(resolutionSelector));
|
||||
}
|
||||
|
||||
/// Sets the surface provider of the specified [Preview] instance and returns
|
||||
|
@ -0,0 +1,108 @@
|
||||
// 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.
|
||||
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:meta/meta.dart' show immutable;
|
||||
|
||||
import 'aspect_ratio_strategy.dart';
|
||||
import 'camerax_library.g.dart';
|
||||
import 'instance_manager.dart';
|
||||
import 'java_object.dart';
|
||||
import 'resolution_strategy.dart';
|
||||
|
||||
/// A set of requirements and priorities used to select a resolution for a
|
||||
/// UseCase.
|
||||
///
|
||||
/// See https://developer.android.com/reference/androidx/camera/core/resolutionselector/ResolutionSelector.
|
||||
@immutable
|
||||
class ResolutionSelector extends JavaObject {
|
||||
/// Construct a [ResolutionSelector].
|
||||
ResolutionSelector({
|
||||
this.resolutionStrategy,
|
||||
this.aspectRatioStrategy,
|
||||
super.binaryMessenger,
|
||||
super.instanceManager,
|
||||
}) : _api = _ResolutionSelectorHostApiImpl(
|
||||
instanceManager: instanceManager,
|
||||
binaryMessenger: binaryMessenger,
|
||||
),
|
||||
super.detached() {
|
||||
_api.createFromInstances(this, resolutionStrategy, aspectRatioStrategy);
|
||||
}
|
||||
|
||||
/// Instantiates a [ResolutionSelector] without creating and attaching to an
|
||||
/// instance of the associated native class.
|
||||
///
|
||||
/// This should only be used outside of tests by subclasses created by this
|
||||
/// library or to create a copy for an [InstanceManager].
|
||||
ResolutionSelector.detached({
|
||||
this.resolutionStrategy,
|
||||
this.aspectRatioStrategy,
|
||||
super.binaryMessenger,
|
||||
super.instanceManager,
|
||||
}) : _api = _ResolutionSelectorHostApiImpl(
|
||||
instanceManager: instanceManager,
|
||||
binaryMessenger: binaryMessenger,
|
||||
),
|
||||
super.detached();
|
||||
|
||||
final _ResolutionSelectorHostApiImpl _api;
|
||||
|
||||
/// Determines how the UseCase will choose the resolution of the captured
|
||||
/// image.
|
||||
final ResolutionStrategy? resolutionStrategy;
|
||||
|
||||
/// Determines how the UseCase will choose the aspect ratio of the captured
|
||||
/// image.
|
||||
final AspectRatioStrategy? aspectRatioStrategy;
|
||||
}
|
||||
|
||||
/// Host API implementation of [ResolutionSelector].
|
||||
class _ResolutionSelectorHostApiImpl extends ResolutionSelectorHostApi {
|
||||
/// Constructs an [_ResolutionSelectorHostApiImpl].
|
||||
///
|
||||
/// If [binaryMessenger] is null, the default [BinaryMessenger] will be used,
|
||||
/// which routes to the host platform.
|
||||
///
|
||||
/// An [instanceManager] is typically passed when a copy of an instance
|
||||
/// contained by an [InstanceManager] is being created. If left null, it
|
||||
/// will default to the global instance defined in [JavaObject].
|
||||
_ResolutionSelectorHostApiImpl({
|
||||
this.binaryMessenger,
|
||||
InstanceManager? instanceManager,
|
||||
}) : instanceManager = instanceManager ?? JavaObject.globalInstanceManager,
|
||||
super(binaryMessenger: binaryMessenger);
|
||||
|
||||
/// Receives binary data across the Flutter platform barrier.
|
||||
final BinaryMessenger? binaryMessenger;
|
||||
|
||||
/// Maintains instances stored to communicate with native language objects.
|
||||
final InstanceManager instanceManager;
|
||||
|
||||
/// Creates a [ResolutionSelector] on the native side with the
|
||||
/// [ResolutionStrategy] and [AspectRatioStrategy] if specified.
|
||||
Future<void> createFromInstances(
|
||||
ResolutionSelector instance,
|
||||
ResolutionStrategy? resolutionStrategy,
|
||||
AspectRatioStrategy? aspectRatioStrategy,
|
||||
) {
|
||||
return create(
|
||||
instanceManager.addDartCreatedInstance(
|
||||
instance,
|
||||
onCopy: (ResolutionSelector original) => ResolutionSelector.detached(
|
||||
resolutionStrategy: original.resolutionStrategy,
|
||||
aspectRatioStrategy: original.aspectRatioStrategy,
|
||||
binaryMessenger: binaryMessenger,
|
||||
instanceManager: instanceManager,
|
||||
),
|
||||
),
|
||||
resolutionStrategy == null
|
||||
? null
|
||||
: instanceManager.getIdentifier(resolutionStrategy)!,
|
||||
aspectRatioStrategy == null
|
||||
? null
|
||||
: instanceManager.getIdentifier(aspectRatioStrategy)!,
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,189 @@
|
||||
// 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.
|
||||
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:meta/meta.dart' show immutable;
|
||||
|
||||
import 'camerax_library.g.dart';
|
||||
import 'instance_manager.dart';
|
||||
import 'java_object.dart';
|
||||
|
||||
/// The resolution strategy defines the resolution selection sequence to select
|
||||
/// the best size.
|
||||
///
|
||||
/// See https://developer.android.com/reference/androidx/camera/core/resolutionselector/ResolutionStrategy.
|
||||
@immutable
|
||||
class ResolutionStrategy extends JavaObject {
|
||||
/// Constructs a [ResolutionStrategy].
|
||||
ResolutionStrategy({
|
||||
required Size this.boundSize,
|
||||
this.fallbackRule,
|
||||
super.binaryMessenger,
|
||||
super.instanceManager,
|
||||
}) : _api = _ResolutionStrategyHostApiImpl(
|
||||
instanceManager: instanceManager,
|
||||
binaryMessenger: binaryMessenger,
|
||||
),
|
||||
super.detached() {
|
||||
_api.createFromInstances(this, boundSize, fallbackRule);
|
||||
}
|
||||
|
||||
/// Constructs a [ResolutionStrategy] that represents the strategy that
|
||||
/// chooses the highest available resolution.
|
||||
///
|
||||
/// See https://developer.android.com/reference/androidx/camera/core/resolutionselector/ResolutionStrategy#HIGHEST_AVAILABLE_STRATEGY().
|
||||
ResolutionStrategy.highestAvailableStrategy({
|
||||
super.binaryMessenger,
|
||||
super.instanceManager,
|
||||
}) : _api = _ResolutionStrategyHostApiImpl(
|
||||
instanceManager: instanceManager,
|
||||
binaryMessenger: binaryMessenger,
|
||||
),
|
||||
boundSize = null,
|
||||
fallbackRule = null,
|
||||
super.detached() {
|
||||
_api.createFromInstances(this, boundSize, fallbackRule);
|
||||
}
|
||||
|
||||
/// Instantiates a [ResolutionStrategy] without creating and attaching to an
|
||||
/// instance of the associated native class.
|
||||
///
|
||||
/// This should only be used outside of tests by subclasses created by this
|
||||
/// library or to create a copy for an [InstanceManager].
|
||||
ResolutionStrategy.detached({
|
||||
required this.boundSize,
|
||||
this.fallbackRule,
|
||||
super.binaryMessenger,
|
||||
super.instanceManager,
|
||||
}) : _api = _ResolutionStrategyHostApiImpl(
|
||||
instanceManager: instanceManager,
|
||||
binaryMessenger: binaryMessenger,
|
||||
),
|
||||
super.detached();
|
||||
|
||||
/// Instantiates a [ResolutionStrategy] that represents the strategy that
|
||||
/// chooses the highest available resolution without creating and attaching to
|
||||
/// an instance of the associated native class.
|
||||
///
|
||||
/// This should only be used outside of tests by subclasses created by this
|
||||
/// library or to create a copy for an [InstanceManager].
|
||||
ResolutionStrategy.detachedHighestAvailableStrategy({
|
||||
super.binaryMessenger,
|
||||
super.instanceManager,
|
||||
}) : _api = _ResolutionStrategyHostApiImpl(
|
||||
instanceManager: instanceManager,
|
||||
binaryMessenger: binaryMessenger,
|
||||
),
|
||||
boundSize = null,
|
||||
fallbackRule = null,
|
||||
super.detached();
|
||||
|
||||
/// CameraX doesn't select an alternate size when the specified bound size is
|
||||
/// unavailable.
|
||||
///
|
||||
/// Applications will receive [PlatformException] when binding the [UseCase]s
|
||||
/// with this fallback rule if the device doesn't support the specified bound
|
||||
/// size.
|
||||
///
|
||||
/// See https://developer.android.com/reference/androidx/camera/core/resolutionselector/ResolutionStrategy#FALLBACK_RULE_NONE().
|
||||
static const int fallbackRuleNone = 0;
|
||||
|
||||
/// When the specified bound size is unavailable, CameraX falls back to select
|
||||
/// the closest higher resolution size.
|
||||
///
|
||||
/// See https://developer.android.com/reference/androidx/camera/core/resolutionselector/ResolutionStrategy#FALLBACK_RULE_CLOSEST_HIGHER_THEN_LOWER().
|
||||
static const int fallbackRuleClosestHigherThenLower = 1;
|
||||
|
||||
/// When the specified bound size is unavailable, CameraX falls back to the
|
||||
/// closest higher resolution size.
|
||||
///
|
||||
/// If CameraX still cannot find any available resolution, it will fallback to
|
||||
/// select other lower resolutions.
|
||||
///
|
||||
/// See https://developer.android.com/reference/androidx/camera/core/resolutionselector/ResolutionStrategy#FALLBACK_RULE_CLOSEST_HIGHER().
|
||||
static const int fallbackRuleClosestHigher = 2;
|
||||
|
||||
/// When the specified bound size is unavailable, CameraX falls back to select
|
||||
/// the closest lower resolution size.
|
||||
///
|
||||
/// If CameraX still cannot find any available resolution, it will fallback to
|
||||
/// select other higher resolutions.
|
||||
///
|
||||
/// See https://developer.android.com/reference/androidx/camera/core/resolutionselector/ResolutionStrategy#FALLBACK_RULE_CLOSEST_LOWER_THEN_HIGHER().
|
||||
static const int fallbackRuleClosestLowerThenHigher = 3;
|
||||
|
||||
/// When the specified bound size is unavailable, CameraX falls back to the
|
||||
/// closest lower resolution size.
|
||||
///
|
||||
/// See https://developer.android.com/reference/androidx/camera/core/resolutionselector/ResolutionStrategy#FALLBACK_RULE_CLOSEST_LOWER().
|
||||
static const int fallbackRuleClosestLower = 4;
|
||||
|
||||
final _ResolutionStrategyHostApiImpl _api;
|
||||
|
||||
/// The specified bound size for the desired resolution of the camera.
|
||||
///
|
||||
/// If left null, [fallbackRule] must also be left null in order to create a
|
||||
/// valid [ResolutionStrategy]. This will create the [ResolutionStrategy]
|
||||
/// that chooses the highest available resolution, which can also be retrieved
|
||||
/// by calling [getHighestAvailableStrategy].
|
||||
final Size? boundSize;
|
||||
|
||||
/// The fallback rule for choosing an alternate size when the specified bound
|
||||
/// size is unavailable.
|
||||
///
|
||||
/// Must be left null if [boundSize] is specified as null. This will create
|
||||
/// the [ResolutionStrategy] that chooses the highest available resolution,
|
||||
/// which can also be retrieved by calling [getHighestAvailableStrategy].
|
||||
final int? fallbackRule;
|
||||
}
|
||||
|
||||
/// Host API implementation of [ResolutionStrategy].
|
||||
class _ResolutionStrategyHostApiImpl extends ResolutionStrategyHostApi {
|
||||
/// Constructs an [_ResolutionStrategyHostApiImpl].
|
||||
///
|
||||
/// If [binaryMessenger] is null, the default [BinaryMessenger] will be used,
|
||||
/// which routes to the host platform.
|
||||
///
|
||||
/// An [instanceManager] is typically passed when a copy of an instance
|
||||
/// contained by an [InstanceManager] is being created. If left null, it
|
||||
/// will default to the global instance defined in [JavaObject].
|
||||
_ResolutionStrategyHostApiImpl({
|
||||
this.binaryMessenger,
|
||||
InstanceManager? instanceManager,
|
||||
}) : instanceManager = instanceManager ?? JavaObject.globalInstanceManager,
|
||||
super(binaryMessenger: binaryMessenger);
|
||||
|
||||
/// Receives binary data across the Flutter platform barrier.
|
||||
final BinaryMessenger? binaryMessenger;
|
||||
|
||||
/// Maintains instances stored to communicate with native language objects.
|
||||
final InstanceManager instanceManager;
|
||||
|
||||
/// Creates a [ResolutionStrategy] on the native side with the bound [Size]
|
||||
/// and fallback rule, if specified.
|
||||
Future<void> createFromInstances(
|
||||
ResolutionStrategy instance,
|
||||
Size? boundSize,
|
||||
int? fallbackRule,
|
||||
) {
|
||||
return create(
|
||||
instanceManager.addDartCreatedInstance(
|
||||
instance,
|
||||
onCopy: (ResolutionStrategy original) => ResolutionStrategy.detached(
|
||||
boundSize: original.boundSize,
|
||||
fallbackRule: original.fallbackRule,
|
||||
binaryMessenger: binaryMessenger,
|
||||
instanceManager: instanceManager,
|
||||
),
|
||||
),
|
||||
boundSize == null
|
||||
? null
|
||||
: ResolutionInfo(
|
||||
width: boundSize.width.toInt(),
|
||||
height: boundSize.height.toInt(),
|
||||
),
|
||||
fallbackRule,
|
||||
);
|
||||
}
|
||||
}
|
@ -196,7 +196,7 @@ abstract class SystemServicesFlutterApi {
|
||||
|
||||
@HostApi(dartHostTestHandler: 'TestPreviewHostApi')
|
||||
abstract class PreviewHostApi {
|
||||
void create(int identifier, int? rotation, ResolutionInfo? targetResolution);
|
||||
void create(int identifier, int? rotation, int? resolutionSelectorId);
|
||||
|
||||
int setSurfaceProvider(int identifier);
|
||||
|
||||
@ -261,7 +261,7 @@ abstract class RecordingFlutterApi {
|
||||
|
||||
@HostApi(dartHostTestHandler: 'TestImageCaptureHostApi')
|
||||
abstract class ImageCaptureHostApi {
|
||||
void create(int identifier, int? flashMode, ResolutionInfo? targetResolution);
|
||||
void create(int identifier, int? flashMode, int? resolutionSelectorId);
|
||||
|
||||
void setFlashMode(int identifier, int flashMode);
|
||||
|
||||
@ -269,6 +269,25 @@ abstract class ImageCaptureHostApi {
|
||||
String takePicture(int identifier);
|
||||
}
|
||||
|
||||
@HostApi(dartHostTestHandler: 'TestResolutionStrategyHostApi')
|
||||
abstract class ResolutionStrategyHostApi {
|
||||
void create(int identifier, ResolutionInfo? boundSize, int? fallbackRule);
|
||||
}
|
||||
|
||||
@HostApi(dartHostTestHandler: 'TestResolutionSelectorHostApi')
|
||||
abstract class ResolutionSelectorHostApi {
|
||||
void create(
|
||||
int identifier,
|
||||
int? resolutionStrategyIdentifier,
|
||||
int? aspectRatioStrategyIdentifier,
|
||||
);
|
||||
}
|
||||
|
||||
@HostApi(dartHostTestHandler: 'TestAspectRatioStrategyHostApi')
|
||||
abstract class AspectRatioStrategyHostApi {
|
||||
void create(int identifier, int preferredAspectRatio, int fallbackRule);
|
||||
}
|
||||
|
||||
@FlutterApi()
|
||||
abstract class CameraStateFlutterApi {
|
||||
void create(int identifier, CameraStateTypeData type, int? errorIdentifier);
|
||||
@ -289,7 +308,7 @@ abstract class ZoomStateFlutterApi {
|
||||
|
||||
@HostApi(dartHostTestHandler: 'TestImageAnalysisHostApi')
|
||||
abstract class ImageAnalysisHostApi {
|
||||
void create(int identifier, ResolutionInfo? targetResolutionIdentifier);
|
||||
void create(int identifier, int? resolutionSelectorId);
|
||||
|
||||
void setAnalyzer(int identifier, int analyzerIdentifier);
|
||||
|
||||
|
@ -2,7 +2,7 @@ name: camera_android_camerax
|
||||
description: Android implementation of the camera plugin using the CameraX library.
|
||||
repository: https://github.com/flutter/packages/tree/main/packages/camera/camera_android_camerax
|
||||
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+camera%22
|
||||
version: 0.5.0+11
|
||||
version: 0.5.0+12
|
||||
|
||||
environment:
|
||||
sdk: ">=2.19.0 <4.0.0"
|
||||
|
@ -1127,13 +1127,12 @@ class FakeAndroidCameraCameraX extends AndroidCameraCameraX {
|
||||
}
|
||||
|
||||
@override
|
||||
Preview createPreview(int targetRotation, ResolutionInfo? targetResolution) {
|
||||
Preview createPreview(int targetRotation) {
|
||||
return testPreview;
|
||||
}
|
||||
|
||||
@override
|
||||
ImageCapture createImageCapture(
|
||||
int? flashMode, ResolutionInfo? targetResolution) {
|
||||
ImageCapture createImageCapture(int? flashMode) {
|
||||
return testImageCapture;
|
||||
}
|
||||
|
||||
@ -1148,7 +1147,7 @@ class FakeAndroidCameraCameraX extends AndroidCameraCameraX {
|
||||
}
|
||||
|
||||
@override
|
||||
ImageAnalysis createImageAnalysis(ResolutionInfo? targetResolution) {
|
||||
ImageAnalysis createImageAnalysis() {
|
||||
return mockImageAnalysis;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,84 @@
|
||||
// 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.
|
||||
|
||||
import 'package:camera_android_camerax/src/aspect_ratio_strategy.dart';
|
||||
import 'package:camera_android_camerax/src/instance_manager.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:mockito/annotations.dart';
|
||||
import 'package:mockito/mockito.dart';
|
||||
|
||||
import 'aspect_ratio_strategy_test.mocks.dart';
|
||||
import 'test_camerax_library.g.dart';
|
||||
|
||||
@GenerateMocks(<Type>[
|
||||
TestAspectRatioStrategyHostApi,
|
||||
TestInstanceManagerHostApi,
|
||||
])
|
||||
void main() {
|
||||
TestWidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
group('AspectRatioStrategy', () {
|
||||
tearDown(() {
|
||||
TestAspectRatioStrategyHostApi.setup(null);
|
||||
TestInstanceManagerHostApi.setup(null);
|
||||
});
|
||||
|
||||
test(
|
||||
'detached create does not make call to create expected AspectRatioStrategy instance',
|
||||
() async {
|
||||
final MockTestAspectRatioStrategyHostApi mockApi =
|
||||
MockTestAspectRatioStrategyHostApi();
|
||||
TestAspectRatioStrategyHostApi.setup(mockApi);
|
||||
|
||||
final InstanceManager instanceManager = InstanceManager(
|
||||
onWeakReferenceRemoved: (_) {},
|
||||
);
|
||||
|
||||
const int preferredAspectRatio = 1;
|
||||
|
||||
const int fallbackRule = 1;
|
||||
|
||||
AspectRatioStrategy.detached(
|
||||
preferredAspectRatio: preferredAspectRatio,
|
||||
fallbackRule: fallbackRule,
|
||||
instanceManager: instanceManager,
|
||||
);
|
||||
|
||||
verifyNever(mockApi.create(
|
||||
argThat(isA<int>()),
|
||||
preferredAspectRatio,
|
||||
fallbackRule,
|
||||
));
|
||||
});
|
||||
|
||||
test(
|
||||
'HostApi create makes call to create expected AspectRatioStrategy instance',
|
||||
() {
|
||||
final MockTestAspectRatioStrategyHostApi mockApi =
|
||||
MockTestAspectRatioStrategyHostApi();
|
||||
TestAspectRatioStrategyHostApi.setup(mockApi);
|
||||
TestInstanceManagerHostApi.setup(MockTestInstanceManagerHostApi());
|
||||
|
||||
final InstanceManager instanceManager = InstanceManager(
|
||||
onWeakReferenceRemoved: (_) {},
|
||||
);
|
||||
|
||||
const int preferredAspectRatio = 0;
|
||||
|
||||
const int fallbackRule = 0;
|
||||
|
||||
final AspectRatioStrategy instance = AspectRatioStrategy(
|
||||
preferredAspectRatio: preferredAspectRatio,
|
||||
fallbackRule: fallbackRule,
|
||||
instanceManager: instanceManager,
|
||||
);
|
||||
|
||||
verify(mockApi.create(
|
||||
instanceManager.getIdentifier(instance),
|
||||
preferredAspectRatio,
|
||||
fallbackRule,
|
||||
));
|
||||
});
|
||||
});
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
// Mocks generated by Mockito 5.4.1 from annotations
|
||||
// in camera_android_camerax/test/aspect_ratio_strategy_test.dart.
|
||||
// Do not manually edit this file.
|
||||
|
||||
// @dart=2.19
|
||||
|
||||
// ignore_for_file: no_leading_underscores_for_library_prefixes
|
||||
import 'package:mockito/mockito.dart' as _i1;
|
||||
|
||||
import 'test_camerax_library.g.dart' as _i2;
|
||||
|
||||
// ignore_for_file: type=lint
|
||||
// ignore_for_file: avoid_redundant_argument_values
|
||||
// ignore_for_file: avoid_setters_without_getters
|
||||
// ignore_for_file: comment_references
|
||||
// ignore_for_file: implementation_imports
|
||||
// ignore_for_file: invalid_use_of_visible_for_testing_member
|
||||
// ignore_for_file: prefer_const_constructors
|
||||
// ignore_for_file: unnecessary_parenthesis
|
||||
// ignore_for_file: camel_case_types
|
||||
// ignore_for_file: subtype_of_sealed_class
|
||||
|
||||
/// A class which mocks [TestAspectRatioStrategyHostApi].
|
||||
///
|
||||
/// See the documentation for Mockito's code generation for more information.
|
||||
class MockTestAspectRatioStrategyHostApi extends _i1.Mock
|
||||
implements _i2.TestAspectRatioStrategyHostApi {
|
||||
MockTestAspectRatioStrategyHostApi() {
|
||||
_i1.throwOnMissingStub(this);
|
||||
}
|
||||
|
||||
@override
|
||||
void create(
|
||||
int? identifier,
|
||||
int? preferredAspectRatio,
|
||||
int? fallbackRule,
|
||||
) =>
|
||||
super.noSuchMethod(
|
||||
Invocation.method(
|
||||
#create,
|
||||
[
|
||||
identifier,
|
||||
preferredAspectRatio,
|
||||
fallbackRule,
|
||||
],
|
||||
),
|
||||
returnValueForMissingStub: null,
|
||||
);
|
||||
}
|
||||
|
||||
/// A class which mocks [TestInstanceManagerHostApi].
|
||||
///
|
||||
/// See the documentation for Mockito's code generation for more information.
|
||||
class MockTestInstanceManagerHostApi extends _i1.Mock
|
||||
implements _i2.TestInstanceManagerHostApi {
|
||||
MockTestInstanceManagerHostApi() {
|
||||
_i1.throwOnMissingStub(this);
|
||||
}
|
||||
|
||||
@override
|
||||
void clear() => super.noSuchMethod(
|
||||
Invocation.method(
|
||||
#clear,
|
||||
[],
|
||||
),
|
||||
returnValueForMissingStub: null,
|
||||
);
|
||||
}
|
@ -3,10 +3,10 @@
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'package:camera_android_camerax/src/analyzer.dart';
|
||||
import 'package:camera_android_camerax/src/camerax_library.g.dart';
|
||||
import 'package:camera_android_camerax/src/image_analysis.dart';
|
||||
import 'package:camera_android_camerax/src/image_proxy.dart';
|
||||
import 'package:camera_android_camerax/src/instance_manager.dart';
|
||||
import 'package:camera_android_camerax/src/resolution_selector.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:mockito/annotations.dart';
|
||||
import 'package:mockito/mockito.dart';
|
||||
@ -14,7 +14,11 @@ import 'package:mockito/mockito.dart';
|
||||
import 'image_analysis_test.mocks.dart';
|
||||
import 'test_camerax_library.g.dart';
|
||||
|
||||
@GenerateMocks(<Type>[TestImageAnalysisHostApi, TestInstanceManagerHostApi])
|
||||
@GenerateMocks(<Type>[
|
||||
TestImageAnalysisHostApi,
|
||||
TestInstanceManagerHostApi,
|
||||
ResolutionSelector,
|
||||
])
|
||||
void main() {
|
||||
TestWidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
@ -22,13 +26,11 @@ void main() {
|
||||
TestInstanceManagerHostApi.setup(MockTestInstanceManagerHostApi());
|
||||
|
||||
group('ImageAnalysis', () {
|
||||
setUp(() {});
|
||||
|
||||
tearDown(() {
|
||||
TestImageAnalysisHostApi.setup(null);
|
||||
});
|
||||
|
||||
test('HostApi create', () {
|
||||
test('create calls create on the Java side', () {
|
||||
final MockTestImageAnalysisHostApi mockApi =
|
||||
MockTestImageAnalysisHostApi();
|
||||
TestImageAnalysisHostApi.setup(mockApi);
|
||||
@ -37,25 +39,28 @@ void main() {
|
||||
onWeakReferenceRemoved: (_) {},
|
||||
);
|
||||
|
||||
const int targetResolutionWidth = 65;
|
||||
const int targetResolutionHeight = 99;
|
||||
final ResolutionInfo targetResolution =
|
||||
ResolutionInfo(width: 65, height: 99);
|
||||
final MockResolutionSelector mockResolutionSelector =
|
||||
MockResolutionSelector();
|
||||
const int mockResolutionSelectorId = 24;
|
||||
|
||||
instanceManager.addHostCreatedInstance(
|
||||
mockResolutionSelector, mockResolutionSelectorId,
|
||||
onCopy: (ResolutionSelector original) {
|
||||
return MockResolutionSelector();
|
||||
});
|
||||
|
||||
final ImageAnalysis instance = ImageAnalysis(
|
||||
targetResolution: targetResolution,
|
||||
resolutionSelector: mockResolutionSelector,
|
||||
instanceManager: instanceManager,
|
||||
);
|
||||
|
||||
final VerificationResult createVerification = verify(mockApi.create(
|
||||
verify(mockApi.create(
|
||||
argThat(equals(instanceManager.getIdentifier(instance))),
|
||||
captureAny));
|
||||
final ResolutionInfo capturedResolutionInfo =
|
||||
createVerification.captured.single as ResolutionInfo;
|
||||
expect(capturedResolutionInfo.width, equals(targetResolutionWidth));
|
||||
expect(capturedResolutionInfo.height, equals(targetResolutionHeight));
|
||||
argThat(equals(mockResolutionSelectorId))));
|
||||
});
|
||||
|
||||
test('setAnalyzer', () async {
|
||||
test('setAnalyzer makes call to set analyzer on ImageAnalysis instance',
|
||||
() async {
|
||||
final MockTestImageAnalysisHostApi mockApi =
|
||||
MockTestImageAnalysisHostApi();
|
||||
TestImageAnalysisHostApi.setup(mockApi);
|
||||
@ -65,7 +70,7 @@ void main() {
|
||||
);
|
||||
|
||||
final ImageAnalysis instance = ImageAnalysis.detached(
|
||||
targetResolution: ResolutionInfo(width: 75, height: 98),
|
||||
resolutionSelector: MockResolutionSelector(),
|
||||
instanceManager: instanceManager,
|
||||
);
|
||||
const int instanceIdentifier = 0;
|
||||
@ -73,7 +78,7 @@ void main() {
|
||||
instance,
|
||||
instanceIdentifier,
|
||||
onCopy: (ImageAnalysis original) => ImageAnalysis.detached(
|
||||
targetResolution: original.targetResolution,
|
||||
resolutionSelector: original.resolutionSelector,
|
||||
instanceManager: instanceManager,
|
||||
),
|
||||
);
|
||||
@ -102,7 +107,8 @@ void main() {
|
||||
));
|
||||
});
|
||||
|
||||
test('clearAnalyzer', () async {
|
||||
test('clearAnalyzer makes call to clear analyzer on ImageAnalysis instance',
|
||||
() async {
|
||||
final MockTestImageAnalysisHostApi mockApi =
|
||||
MockTestImageAnalysisHostApi();
|
||||
TestImageAnalysisHostApi.setup(mockApi);
|
||||
@ -112,7 +118,7 @@ void main() {
|
||||
);
|
||||
|
||||
final ImageAnalysis instance = ImageAnalysis.detached(
|
||||
targetResolution: ResolutionInfo(width: 75, height: 98),
|
||||
resolutionSelector: MockResolutionSelector(),
|
||||
instanceManager: instanceManager,
|
||||
);
|
||||
const int instanceIdentifier = 0;
|
||||
@ -120,7 +126,7 @@ void main() {
|
||||
instance,
|
||||
instanceIdentifier,
|
||||
onCopy: (ImageAnalysis original) => ImageAnalysis.detached(
|
||||
targetResolution: original.targetResolution,
|
||||
resolutionSelector: original.resolutionSelector,
|
||||
instanceManager: instanceManager,
|
||||
),
|
||||
);
|
||||
|
@ -5,7 +5,7 @@
|
||||
// @dart=2.19
|
||||
|
||||
// ignore_for_file: no_leading_underscores_for_library_prefixes
|
||||
import 'package:camera_android_camerax/src/camerax_library.g.dart' as _i3;
|
||||
import 'package:camera_android_camerax/src/resolution_selector.dart' as _i3;
|
||||
import 'package:mockito/mockito.dart' as _i1;
|
||||
|
||||
import 'test_camerax_library.g.dart' as _i2;
|
||||
@ -33,14 +33,14 @@ class MockTestImageAnalysisHostApi extends _i1.Mock
|
||||
@override
|
||||
void create(
|
||||
int? identifier,
|
||||
_i3.ResolutionInfo? targetResolutionIdentifier,
|
||||
int? resolutionSelectorId,
|
||||
) =>
|
||||
super.noSuchMethod(
|
||||
Invocation.method(
|
||||
#create,
|
||||
[
|
||||
identifier,
|
||||
targetResolutionIdentifier,
|
||||
resolutionSelectorId,
|
||||
],
|
||||
),
|
||||
returnValueForMissingStub: null,
|
||||
@ -88,3 +88,14 @@ class MockTestInstanceManagerHostApi extends _i1.Mock
|
||||
returnValueForMissingStub: null,
|
||||
);
|
||||
}
|
||||
|
||||
/// A class which mocks [ResolutionSelector].
|
||||
///
|
||||
/// See the documentation for Mockito's code generation for more information.
|
||||
// ignore: must_be_immutable
|
||||
class MockResolutionSelector extends _i1.Mock
|
||||
implements _i3.ResolutionSelector {
|
||||
MockResolutionSelector() {
|
||||
_i1.throwOnMissingStub(this);
|
||||
}
|
||||
}
|
||||
|
@ -2,9 +2,9 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'package:camera_android_camerax/src/camerax_library.g.dart';
|
||||
import 'package:camera_android_camerax/src/image_capture.dart';
|
||||
import 'package:camera_android_camerax/src/instance_manager.dart';
|
||||
import 'package:camera_android_camerax/src/resolution_selector.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:mockito/annotations.dart';
|
||||
import 'package:mockito/mockito.dart';
|
||||
@ -12,7 +12,11 @@ import 'package:mockito/mockito.dart';
|
||||
import 'image_capture_test.mocks.dart';
|
||||
import 'test_camerax_library.g.dart';
|
||||
|
||||
@GenerateMocks(<Type>[TestImageCaptureHostApi, TestInstanceManagerHostApi])
|
||||
@GenerateMocks(<Type>[
|
||||
TestImageCaptureHostApi,
|
||||
TestInstanceManagerHostApi,
|
||||
ResolutionSelector
|
||||
])
|
||||
void main() {
|
||||
TestWidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
@ -32,11 +36,11 @@ void main() {
|
||||
ImageCapture.detached(
|
||||
instanceManager: instanceManager,
|
||||
targetFlashMode: ImageCapture.flashModeOn,
|
||||
targetResolution: ResolutionInfo(width: 50, height: 10),
|
||||
resolutionSelector: MockResolutionSelector(),
|
||||
);
|
||||
|
||||
verifyNever(mockApi.create(argThat(isA<int>()), argThat(isA<int>()),
|
||||
argThat(isA<ResolutionInfo>())));
|
||||
argThat(isA<ResolutionSelector>())));
|
||||
});
|
||||
|
||||
test('create calls create on the Java side', () async {
|
||||
@ -47,21 +51,26 @@ void main() {
|
||||
onWeakReferenceRemoved: (_) {},
|
||||
);
|
||||
const int targetFlashMode = ImageCapture.flashModeAuto;
|
||||
const int targetResolutionWidth = 10;
|
||||
const int targetResolutionHeight = 50;
|
||||
final MockResolutionSelector mockResolutionSelector =
|
||||
MockResolutionSelector();
|
||||
const int mockResolutionSelectorId = 24;
|
||||
|
||||
instanceManager.addHostCreatedInstance(
|
||||
mockResolutionSelector, mockResolutionSelectorId,
|
||||
onCopy: (ResolutionSelector original) {
|
||||
return MockResolutionSelector();
|
||||
});
|
||||
|
||||
ImageCapture(
|
||||
instanceManager: instanceManager,
|
||||
targetFlashMode: targetFlashMode,
|
||||
targetResolution: ResolutionInfo(
|
||||
width: targetResolutionWidth, height: targetResolutionHeight),
|
||||
resolutionSelector: mockResolutionSelector,
|
||||
);
|
||||
|
||||
final VerificationResult createVerification = verify(mockApi.create(
|
||||
argThat(isA<int>()), argThat(equals(targetFlashMode)), captureAny));
|
||||
final ResolutionInfo capturedResolutionInfo =
|
||||
createVerification.captured.single as ResolutionInfo;
|
||||
expect(capturedResolutionInfo.width, equals(targetResolutionWidth));
|
||||
expect(capturedResolutionInfo.height, equals(targetResolutionHeight));
|
||||
verify(mockApi.create(
|
||||
argThat(isA<int>()),
|
||||
argThat(equals(targetFlashMode)),
|
||||
argThat(equals(mockResolutionSelectorId))));
|
||||
});
|
||||
|
||||
test('setFlashMode makes call to set flash mode for ImageCapture instance',
|
||||
|
@ -5,9 +5,9 @@
|
||||
// @dart=2.19
|
||||
|
||||
// ignore_for_file: no_leading_underscores_for_library_prefixes
|
||||
import 'dart:async' as _i4;
|
||||
import 'dart:async' as _i3;
|
||||
|
||||
import 'package:camera_android_camerax/src/camerax_library.g.dart' as _i3;
|
||||
import 'package:camera_android_camerax/src/resolution_selector.dart' as _i4;
|
||||
import 'package:mockito/mockito.dart' as _i1;
|
||||
|
||||
import 'test_camerax_library.g.dart' as _i2;
|
||||
@ -36,7 +36,7 @@ class MockTestImageCaptureHostApi extends _i1.Mock
|
||||
void create(
|
||||
int? identifier,
|
||||
int? flashMode,
|
||||
_i3.ResolutionInfo? targetResolution,
|
||||
int? resolutionSelectorId,
|
||||
) =>
|
||||
super.noSuchMethod(
|
||||
Invocation.method(
|
||||
@ -44,7 +44,7 @@ class MockTestImageCaptureHostApi extends _i1.Mock
|
||||
[
|
||||
identifier,
|
||||
flashMode,
|
||||
targetResolution,
|
||||
resolutionSelectorId,
|
||||
],
|
||||
),
|
||||
returnValueForMissingStub: null,
|
||||
@ -65,13 +65,13 @@ class MockTestImageCaptureHostApi extends _i1.Mock
|
||||
returnValueForMissingStub: null,
|
||||
);
|
||||
@override
|
||||
_i4.Future<String> takePicture(int? identifier) => (super.noSuchMethod(
|
||||
_i3.Future<String> takePicture(int? identifier) => (super.noSuchMethod(
|
||||
Invocation.method(
|
||||
#takePicture,
|
||||
[identifier],
|
||||
),
|
||||
returnValue: _i4.Future<String>.value(''),
|
||||
) as _i4.Future<String>);
|
||||
returnValue: _i3.Future<String>.value(''),
|
||||
) as _i3.Future<String>);
|
||||
}
|
||||
|
||||
/// A class which mocks [TestInstanceManagerHostApi].
|
||||
@ -92,3 +92,14 @@ class MockTestInstanceManagerHostApi extends _i1.Mock
|
||||
returnValueForMissingStub: null,
|
||||
);
|
||||
}
|
||||
|
||||
/// A class which mocks [ResolutionSelector].
|
||||
///
|
||||
/// See the documentation for Mockito's code generation for more information.
|
||||
// ignore: must_be_immutable
|
||||
class MockResolutionSelector extends _i1.Mock
|
||||
implements _i4.ResolutionSelector {
|
||||
MockResolutionSelector() {
|
||||
_i1.throwOnMissingStub(this);
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@
|
||||
import 'package:camera_android_camerax/src/camerax_library.g.dart';
|
||||
import 'package:camera_android_camerax/src/instance_manager.dart';
|
||||
import 'package:camera_android_camerax/src/preview.dart';
|
||||
import 'package:camera_android_camerax/src/resolution_selector.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:mockito/annotations.dart';
|
||||
import 'package:mockito/mockito.dart';
|
||||
@ -12,7 +13,8 @@ import 'package:mockito/mockito.dart';
|
||||
import 'preview_test.mocks.dart';
|
||||
import 'test_camerax_library.g.dart';
|
||||
|
||||
@GenerateMocks(<Type>[TestInstanceManagerHostApi, TestPreviewHostApi])
|
||||
@GenerateMocks(
|
||||
<Type>[TestInstanceManagerHostApi, TestPreviewHostApi, ResolutionSelector])
|
||||
void main() {
|
||||
TestWidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
@ -32,11 +34,11 @@ void main() {
|
||||
Preview.detached(
|
||||
instanceManager: instanceManager,
|
||||
targetRotation: 90,
|
||||
targetResolution: ResolutionInfo(width: 50, height: 10),
|
||||
resolutionSelector: MockResolutionSelector(),
|
||||
);
|
||||
|
||||
verifyNever(mockApi.create(argThat(isA<int>()), argThat(isA<int>()),
|
||||
argThat(isA<ResolutionInfo>())));
|
||||
argThat(isA<ResolutionSelector>())));
|
||||
});
|
||||
|
||||
test('create calls create on the Java side', () async {
|
||||
@ -47,21 +49,26 @@ void main() {
|
||||
onWeakReferenceRemoved: (_) {},
|
||||
);
|
||||
const int targetRotation = 90;
|
||||
const int targetResolutionWidth = 10;
|
||||
const int targetResolutionHeight = 50;
|
||||
final MockResolutionSelector mockResolutionSelector =
|
||||
MockResolutionSelector();
|
||||
const int mockResolutionSelectorId = 24;
|
||||
|
||||
instanceManager.addHostCreatedInstance(
|
||||
mockResolutionSelector, mockResolutionSelectorId,
|
||||
onCopy: (ResolutionSelector original) {
|
||||
return MockResolutionSelector();
|
||||
});
|
||||
|
||||
Preview(
|
||||
instanceManager: instanceManager,
|
||||
targetRotation: targetRotation,
|
||||
targetResolution: ResolutionInfo(
|
||||
width: targetResolutionWidth, height: targetResolutionHeight),
|
||||
resolutionSelector: mockResolutionSelector,
|
||||
);
|
||||
|
||||
final VerificationResult createVerification = verify(mockApi.create(
|
||||
argThat(isA<int>()), argThat(equals(targetRotation)), captureAny));
|
||||
final ResolutionInfo capturedResolutionInfo =
|
||||
createVerification.captured.single as ResolutionInfo;
|
||||
expect(capturedResolutionInfo.width, equals(targetResolutionWidth));
|
||||
expect(capturedResolutionInfo.height, equals(targetResolutionHeight));
|
||||
verify(mockApi.create(
|
||||
argThat(isA<int>()),
|
||||
argThat(equals(targetRotation)),
|
||||
argThat(equals(mockResolutionSelectorId))));
|
||||
});
|
||||
|
||||
test(
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
// ignore_for_file: no_leading_underscores_for_library_prefixes
|
||||
import 'package:camera_android_camerax/src/camerax_library.g.dart' as _i2;
|
||||
import 'package:camera_android_camerax/src/resolution_selector.dart' as _i4;
|
||||
import 'package:mockito/mockito.dart' as _i1;
|
||||
|
||||
import 'test_camerax_library.g.dart' as _i3;
|
||||
@ -64,7 +65,7 @@ class MockTestPreviewHostApi extends _i1.Mock
|
||||
void create(
|
||||
int? identifier,
|
||||
int? rotation,
|
||||
_i2.ResolutionInfo? targetResolution,
|
||||
int? resolutionSelectorId,
|
||||
) =>
|
||||
super.noSuchMethod(
|
||||
Invocation.method(
|
||||
@ -72,7 +73,7 @@ class MockTestPreviewHostApi extends _i1.Mock
|
||||
[
|
||||
identifier,
|
||||
rotation,
|
||||
targetResolution,
|
||||
resolutionSelectorId,
|
||||
],
|
||||
),
|
||||
returnValueForMissingStub: null,
|
||||
@ -108,3 +109,14 @@ class MockTestPreviewHostApi extends _i1.Mock
|
||||
),
|
||||
) as _i2.ResolutionInfo);
|
||||
}
|
||||
|
||||
/// A class which mocks [ResolutionSelector].
|
||||
///
|
||||
/// See the documentation for Mockito's code generation for more information.
|
||||
// ignore: must_be_immutable
|
||||
class MockResolutionSelector extends _i1.Mock
|
||||
implements _i4.ResolutionSelector {
|
||||
MockResolutionSelector() {
|
||||
_i1.throwOnMissingStub(this);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,124 @@
|
||||
// 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.
|
||||
|
||||
import 'dart:ui';
|
||||
|
||||
import 'package:camera_android_camerax/src/aspect_ratio_strategy.dart';
|
||||
import 'package:camera_android_camerax/src/instance_manager.dart';
|
||||
import 'package:camera_android_camerax/src/resolution_selector.dart';
|
||||
import 'package:camera_android_camerax/src/resolution_strategy.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:mockito/annotations.dart';
|
||||
import 'package:mockito/mockito.dart';
|
||||
|
||||
import 'resolution_selector_test.mocks.dart';
|
||||
import 'test_camerax_library.g.dart';
|
||||
|
||||
@GenerateMocks(<Type>[
|
||||
AspectRatioStrategy,
|
||||
ResolutionStrategy,
|
||||
TestResolutionSelectorHostApi,
|
||||
TestInstanceManagerHostApi,
|
||||
])
|
||||
void main() {
|
||||
TestWidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
group('ResolutionSelector', () {
|
||||
tearDown(() {
|
||||
TestResolutionSelectorHostApi.setup(null);
|
||||
TestInstanceManagerHostApi.setup(null);
|
||||
});
|
||||
|
||||
test(
|
||||
'detached constructor does not make call to create expected AspectRatioStrategy instance',
|
||||
() async {
|
||||
final MockTestResolutionSelectorHostApi mockApi =
|
||||
MockTestResolutionSelectorHostApi();
|
||||
TestResolutionSelectorHostApi.setup(mockApi);
|
||||
TestInstanceManagerHostApi.setup(MockTestInstanceManagerHostApi());
|
||||
|
||||
final InstanceManager instanceManager = InstanceManager(
|
||||
onWeakReferenceRemoved: (_) {},
|
||||
);
|
||||
|
||||
const int preferredAspectRatio = 1;
|
||||
|
||||
const int fallbackRule = 1;
|
||||
|
||||
AspectRatioStrategy.detached(
|
||||
preferredAspectRatio: preferredAspectRatio,
|
||||
fallbackRule: fallbackRule,
|
||||
instanceManager: instanceManager,
|
||||
);
|
||||
|
||||
ResolutionSelector.detached(
|
||||
resolutionStrategy: MockResolutionStrategy(),
|
||||
aspectRatioStrategy: MockAspectRatioStrategy(),
|
||||
instanceManager: instanceManager,
|
||||
);
|
||||
|
||||
verifyNever(mockApi.create(
|
||||
argThat(isA<int>()),
|
||||
argThat(isA<int>()),
|
||||
argThat(isA<int>()),
|
||||
));
|
||||
});
|
||||
|
||||
test('HostApi create creates expected ResolutionSelector instance', () {
|
||||
final MockTestResolutionSelectorHostApi mockApi =
|
||||
MockTestResolutionSelectorHostApi();
|
||||
TestResolutionSelectorHostApi.setup(mockApi);
|
||||
TestInstanceManagerHostApi.setup(MockTestInstanceManagerHostApi());
|
||||
|
||||
final InstanceManager instanceManager = InstanceManager(
|
||||
onWeakReferenceRemoved: (_) {},
|
||||
);
|
||||
|
||||
final ResolutionStrategy resolutionStrategy = ResolutionStrategy.detached(
|
||||
boundSize: const Size(50, 30),
|
||||
fallbackRule: ResolutionStrategy.fallbackRuleClosestLower,
|
||||
instanceManager: instanceManager,
|
||||
);
|
||||
const int resolutionStrategyIdentifier = 14;
|
||||
instanceManager.addHostCreatedInstance(
|
||||
resolutionStrategy,
|
||||
resolutionStrategyIdentifier,
|
||||
onCopy: (ResolutionStrategy original) => ResolutionStrategy.detached(
|
||||
boundSize: original.boundSize,
|
||||
fallbackRule: original.fallbackRule,
|
||||
instanceManager: instanceManager,
|
||||
),
|
||||
);
|
||||
|
||||
final AspectRatioStrategy aspectRatioStrategy =
|
||||
AspectRatioStrategy.detached(
|
||||
preferredAspectRatio: AspectRatio.ratio4To3,
|
||||
fallbackRule: AspectRatioStrategy.fallbackRuleAuto,
|
||||
instanceManager: instanceManager,
|
||||
);
|
||||
const int aspectRatioStrategyIdentifier = 15;
|
||||
instanceManager.addHostCreatedInstance(
|
||||
aspectRatioStrategy,
|
||||
aspectRatioStrategyIdentifier,
|
||||
onCopy: (AspectRatioStrategy original) => AspectRatioStrategy.detached(
|
||||
preferredAspectRatio: original.preferredAspectRatio,
|
||||
fallbackRule: original.fallbackRule,
|
||||
instanceManager: instanceManager,
|
||||
),
|
||||
);
|
||||
|
||||
final ResolutionSelector instance = ResolutionSelector(
|
||||
resolutionStrategy: resolutionStrategy,
|
||||
aspectRatioStrategy: aspectRatioStrategy,
|
||||
instanceManager: instanceManager,
|
||||
);
|
||||
|
||||
verify(mockApi.create(
|
||||
instanceManager.getIdentifier(instance),
|
||||
resolutionStrategyIdentifier,
|
||||
aspectRatioStrategyIdentifier,
|
||||
));
|
||||
});
|
||||
});
|
||||
}
|
@ -0,0 +1,103 @@
|
||||
// Mocks generated by Mockito 5.4.1 from annotations
|
||||
// in camera_android_camerax/test/resolution_selector_test.dart.
|
||||
// Do not manually edit this file.
|
||||
|
||||
// @dart=2.19
|
||||
|
||||
// ignore_for_file: no_leading_underscores_for_library_prefixes
|
||||
import 'package:camera_android_camerax/src/aspect_ratio_strategy.dart' as _i2;
|
||||
import 'package:camera_android_camerax/src/resolution_strategy.dart' as _i3;
|
||||
import 'package:mockito/mockito.dart' as _i1;
|
||||
|
||||
import 'test_camerax_library.g.dart' as _i4;
|
||||
|
||||
// ignore_for_file: type=lint
|
||||
// ignore_for_file: avoid_redundant_argument_values
|
||||
// ignore_for_file: avoid_setters_without_getters
|
||||
// ignore_for_file: comment_references
|
||||
// ignore_for_file: implementation_imports
|
||||
// ignore_for_file: invalid_use_of_visible_for_testing_member
|
||||
// ignore_for_file: prefer_const_constructors
|
||||
// ignore_for_file: unnecessary_parenthesis
|
||||
// ignore_for_file: camel_case_types
|
||||
// ignore_for_file: subtype_of_sealed_class
|
||||
|
||||
/// A class which mocks [AspectRatioStrategy].
|
||||
///
|
||||
/// See the documentation for Mockito's code generation for more information.
|
||||
// ignore: must_be_immutable
|
||||
class MockAspectRatioStrategy extends _i1.Mock
|
||||
implements _i2.AspectRatioStrategy {
|
||||
MockAspectRatioStrategy() {
|
||||
_i1.throwOnMissingStub(this);
|
||||
}
|
||||
|
||||
@override
|
||||
int get preferredAspectRatio => (super.noSuchMethod(
|
||||
Invocation.getter(#preferredAspectRatio),
|
||||
returnValue: 0,
|
||||
) as int);
|
||||
@override
|
||||
int get fallbackRule => (super.noSuchMethod(
|
||||
Invocation.getter(#fallbackRule),
|
||||
returnValue: 0,
|
||||
) as int);
|
||||
}
|
||||
|
||||
/// A class which mocks [ResolutionStrategy].
|
||||
///
|
||||
/// See the documentation for Mockito's code generation for more information.
|
||||
// ignore: must_be_immutable
|
||||
class MockResolutionStrategy extends _i1.Mock
|
||||
implements _i3.ResolutionStrategy {
|
||||
MockResolutionStrategy() {
|
||||
_i1.throwOnMissingStub(this);
|
||||
}
|
||||
}
|
||||
|
||||
/// A class which mocks [TestResolutionSelectorHostApi].
|
||||
///
|
||||
/// See the documentation for Mockito's code generation for more information.
|
||||
class MockTestResolutionSelectorHostApi extends _i1.Mock
|
||||
implements _i4.TestResolutionSelectorHostApi {
|
||||
MockTestResolutionSelectorHostApi() {
|
||||
_i1.throwOnMissingStub(this);
|
||||
}
|
||||
|
||||
@override
|
||||
void create(
|
||||
int? identifier,
|
||||
int? resolutionStrategyIdentifier,
|
||||
int? aspectRatioStrategyIdentifier,
|
||||
) =>
|
||||
super.noSuchMethod(
|
||||
Invocation.method(
|
||||
#create,
|
||||
[
|
||||
identifier,
|
||||
resolutionStrategyIdentifier,
|
||||
aspectRatioStrategyIdentifier,
|
||||
],
|
||||
),
|
||||
returnValueForMissingStub: null,
|
||||
);
|
||||
}
|
||||
|
||||
/// A class which mocks [TestInstanceManagerHostApi].
|
||||
///
|
||||
/// See the documentation for Mockito's code generation for more information.
|
||||
class MockTestInstanceManagerHostApi extends _i1.Mock
|
||||
implements _i4.TestInstanceManagerHostApi {
|
||||
MockTestInstanceManagerHostApi() {
|
||||
_i1.throwOnMissingStub(this);
|
||||
}
|
||||
|
||||
@override
|
||||
void clear() => super.noSuchMethod(
|
||||
Invocation.method(
|
||||
#clear,
|
||||
[],
|
||||
),
|
||||
returnValueForMissingStub: null,
|
||||
);
|
||||
}
|
@ -0,0 +1,109 @@
|
||||
// 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.
|
||||
|
||||
import 'dart:ui';
|
||||
|
||||
import 'package:camera_android_camerax/src/camerax_library.g.dart';
|
||||
import 'package:camera_android_camerax/src/instance_manager.dart';
|
||||
import 'package:camera_android_camerax/src/resolution_strategy.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:mockito/annotations.dart';
|
||||
import 'package:mockito/mockito.dart';
|
||||
|
||||
import 'resolution_strategy_test.mocks.dart';
|
||||
import 'test_camerax_library.g.dart';
|
||||
|
||||
@GenerateMocks(<Type>[
|
||||
TestResolutionStrategyHostApi,
|
||||
TestInstanceManagerHostApi,
|
||||
])
|
||||
void main() {
|
||||
TestWidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
group('ResolutionStrategy', () {
|
||||
tearDown(() {
|
||||
TestResolutionStrategyHostApi.setup(null);
|
||||
TestInstanceManagerHostApi.setup(null);
|
||||
});
|
||||
|
||||
test(
|
||||
'detached resolutionStrategy constructors do not make call to Host API create',
|
||||
() {
|
||||
final MockTestResolutionStrategyHostApi mockApi =
|
||||
MockTestResolutionStrategyHostApi();
|
||||
TestResolutionStrategyHostApi.setup(mockApi);
|
||||
TestInstanceManagerHostApi.setup(MockTestInstanceManagerHostApi());
|
||||
|
||||
final InstanceManager instanceManager = InstanceManager(
|
||||
onWeakReferenceRemoved: (_) {},
|
||||
);
|
||||
|
||||
const Size boundSize = Size(70, 20);
|
||||
const int fallbackRule = 1;
|
||||
|
||||
ResolutionStrategy.detached(
|
||||
boundSize: boundSize,
|
||||
fallbackRule: fallbackRule,
|
||||
instanceManager: instanceManager,
|
||||
);
|
||||
|
||||
verifyNever(mockApi.create(
|
||||
argThat(isA<int>()),
|
||||
argThat(isA<ResolutionInfo>()
|
||||
.having((ResolutionInfo size) => size.width, 'width', 50)
|
||||
.having((ResolutionInfo size) => size.height, 'height', 30)),
|
||||
fallbackRule,
|
||||
));
|
||||
|
||||
ResolutionStrategy.detachedHighestAvailableStrategy(
|
||||
instanceManager: instanceManager,
|
||||
);
|
||||
|
||||
verifyNever(mockApi.create(
|
||||
argThat(isA<int>()),
|
||||
null,
|
||||
null,
|
||||
));
|
||||
});
|
||||
|
||||
test('HostApi create creates expected ResolutionStrategies', () {
|
||||
final MockTestResolutionStrategyHostApi mockApi =
|
||||
MockTestResolutionStrategyHostApi();
|
||||
TestResolutionStrategyHostApi.setup(mockApi);
|
||||
TestInstanceManagerHostApi.setup(MockTestInstanceManagerHostApi());
|
||||
|
||||
final InstanceManager instanceManager = InstanceManager(
|
||||
onWeakReferenceRemoved: (_) {},
|
||||
);
|
||||
|
||||
const Size boundSize = Size(50, 30);
|
||||
const int fallbackRule = 0;
|
||||
|
||||
final ResolutionStrategy instance = ResolutionStrategy(
|
||||
boundSize: boundSize,
|
||||
fallbackRule: fallbackRule,
|
||||
instanceManager: instanceManager,
|
||||
);
|
||||
|
||||
verify(mockApi.create(
|
||||
instanceManager.getIdentifier(instance),
|
||||
argThat(isA<ResolutionInfo>()
|
||||
.having((ResolutionInfo size) => size.width, 'width', 50)
|
||||
.having((ResolutionInfo size) => size.height, 'height', 30)),
|
||||
fallbackRule,
|
||||
));
|
||||
|
||||
final ResolutionStrategy highestAvailableInstance =
|
||||
ResolutionStrategy.highestAvailableStrategy(
|
||||
instanceManager: instanceManager,
|
||||
);
|
||||
|
||||
verify(mockApi.create(
|
||||
instanceManager.getIdentifier(highestAvailableInstance),
|
||||
null,
|
||||
null,
|
||||
));
|
||||
});
|
||||
});
|
||||
}
|
@ -0,0 +1,69 @@
|
||||
// Mocks generated by Mockito 5.4.1 from annotations
|
||||
// in camera_android_camerax/test/resolution_strategy_test.dart.
|
||||
// Do not manually edit this file.
|
||||
|
||||
// @dart=2.19
|
||||
|
||||
// ignore_for_file: no_leading_underscores_for_library_prefixes
|
||||
import 'package:camera_android_camerax/src/camerax_library.g.dart' as _i3;
|
||||
import 'package:mockito/mockito.dart' as _i1;
|
||||
|
||||
import 'test_camerax_library.g.dart' as _i2;
|
||||
|
||||
// ignore_for_file: type=lint
|
||||
// ignore_for_file: avoid_redundant_argument_values
|
||||
// ignore_for_file: avoid_setters_without_getters
|
||||
// ignore_for_file: comment_references
|
||||
// ignore_for_file: implementation_imports
|
||||
// ignore_for_file: invalid_use_of_visible_for_testing_member
|
||||
// ignore_for_file: prefer_const_constructors
|
||||
// ignore_for_file: unnecessary_parenthesis
|
||||
// ignore_for_file: camel_case_types
|
||||
// ignore_for_file: subtype_of_sealed_class
|
||||
|
||||
/// A class which mocks [TestResolutionStrategyHostApi].
|
||||
///
|
||||
/// See the documentation for Mockito's code generation for more information.
|
||||
class MockTestResolutionStrategyHostApi extends _i1.Mock
|
||||
implements _i2.TestResolutionStrategyHostApi {
|
||||
MockTestResolutionStrategyHostApi() {
|
||||
_i1.throwOnMissingStub(this);
|
||||
}
|
||||
|
||||
@override
|
||||
void create(
|
||||
int? identifier,
|
||||
_i3.ResolutionInfo? boundSize,
|
||||
int? fallbackRule,
|
||||
) =>
|
||||
super.noSuchMethod(
|
||||
Invocation.method(
|
||||
#create,
|
||||
[
|
||||
identifier,
|
||||
boundSize,
|
||||
fallbackRule,
|
||||
],
|
||||
),
|
||||
returnValueForMissingStub: null,
|
||||
);
|
||||
}
|
||||
|
||||
/// A class which mocks [TestInstanceManagerHostApi].
|
||||
///
|
||||
/// See the documentation for Mockito's code generation for more information.
|
||||
class MockTestInstanceManagerHostApi extends _i1.Mock
|
||||
implements _i2.TestInstanceManagerHostApi {
|
||||
MockTestInstanceManagerHostApi() {
|
||||
_i1.throwOnMissingStub(this);
|
||||
}
|
||||
|
||||
@override
|
||||
void clear() => super.noSuchMethod(
|
||||
Invocation.method(
|
||||
#clear,
|
||||
[],
|
||||
),
|
||||
returnValueForMissingStub: null,
|
||||
);
|
||||
}
|
@ -597,9 +597,6 @@ class _TestPreviewHostApiCodec extends StandardMessageCodec {
|
||||
if (value is ResolutionInfo) {
|
||||
buffer.putUint8(128);
|
||||
writeValue(buffer, value.encode());
|
||||
} else if (value is ResolutionInfo) {
|
||||
buffer.putUint8(129);
|
||||
writeValue(buffer, value.encode());
|
||||
} else {
|
||||
super.writeValue(buffer, value);
|
||||
}
|
||||
@ -610,8 +607,6 @@ class _TestPreviewHostApiCodec extends StandardMessageCodec {
|
||||
switch (type) {
|
||||
case 128:
|
||||
return ResolutionInfo.decode(readValue(buffer)!);
|
||||
case 129:
|
||||
return ResolutionInfo.decode(readValue(buffer)!);
|
||||
default:
|
||||
return super.readValueOfType(type, buffer);
|
||||
}
|
||||
@ -623,7 +618,7 @@ abstract class TestPreviewHostApi {
|
||||
TestDefaultBinaryMessengerBinding.instance;
|
||||
static const MessageCodec<Object?> codec = _TestPreviewHostApiCodec();
|
||||
|
||||
void create(int identifier, int? rotation, ResolutionInfo? targetResolution);
|
||||
void create(int identifier, int? rotation, int? resolutionSelectorId);
|
||||
|
||||
int setSurfaceProvider(int identifier);
|
||||
|
||||
@ -651,9 +646,8 @@ abstract class TestPreviewHostApi {
|
||||
assert(arg_identifier != null,
|
||||
'Argument for dev.flutter.pigeon.PreviewHostApi.create was null, expected non-null int.');
|
||||
final int? arg_rotation = (args[1] as int?);
|
||||
final ResolutionInfo? arg_targetResolution =
|
||||
(args[2] as ResolutionInfo?);
|
||||
api.create(arg_identifier!, arg_rotation, arg_targetResolution);
|
||||
final int? arg_resolutionSelectorId = (args[2] as int?);
|
||||
api.create(arg_identifier!, arg_rotation, arg_resolutionSelectorId);
|
||||
return <Object?>[];
|
||||
});
|
||||
}
|
||||
@ -1033,35 +1027,12 @@ abstract class TestRecordingHostApi {
|
||||
}
|
||||
}
|
||||
|
||||
class _TestImageCaptureHostApiCodec extends StandardMessageCodec {
|
||||
const _TestImageCaptureHostApiCodec();
|
||||
@override
|
||||
void writeValue(WriteBuffer buffer, Object? value) {
|
||||
if (value is ResolutionInfo) {
|
||||
buffer.putUint8(128);
|
||||
writeValue(buffer, value.encode());
|
||||
} else {
|
||||
super.writeValue(buffer, value);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Object? readValueOfType(int type, ReadBuffer buffer) {
|
||||
switch (type) {
|
||||
case 128:
|
||||
return ResolutionInfo.decode(readValue(buffer)!);
|
||||
default:
|
||||
return super.readValueOfType(type, buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
abstract class TestImageCaptureHostApi {
|
||||
static TestDefaultBinaryMessengerBinding? get _testBinaryMessengerBinding =>
|
||||
TestDefaultBinaryMessengerBinding.instance;
|
||||
static const MessageCodec<Object?> codec = _TestImageCaptureHostApiCodec();
|
||||
static const MessageCodec<Object?> codec = StandardMessageCodec();
|
||||
|
||||
void create(int identifier, int? flashMode, ResolutionInfo? targetResolution);
|
||||
void create(int identifier, int? flashMode, int? resolutionSelectorId);
|
||||
|
||||
void setFlashMode(int identifier, int flashMode);
|
||||
|
||||
@ -1087,9 +1058,8 @@ abstract class TestImageCaptureHostApi {
|
||||
assert(arg_identifier != null,
|
||||
'Argument for dev.flutter.pigeon.ImageCaptureHostApi.create was null, expected non-null int.');
|
||||
final int? arg_flashMode = (args[1] as int?);
|
||||
final ResolutionInfo? arg_targetResolution =
|
||||
(args[2] as ResolutionInfo?);
|
||||
api.create(arg_identifier!, arg_flashMode, arg_targetResolution);
|
||||
final int? arg_resolutionSelectorId = (args[2] as int?);
|
||||
api.create(arg_identifier!, arg_flashMode, arg_resolutionSelectorId);
|
||||
return <Object?>[];
|
||||
});
|
||||
}
|
||||
@ -1144,8 +1114,8 @@ abstract class TestImageCaptureHostApi {
|
||||
}
|
||||
}
|
||||
|
||||
class _TestImageAnalysisHostApiCodec extends StandardMessageCodec {
|
||||
const _TestImageAnalysisHostApiCodec();
|
||||
class _TestResolutionStrategyHostApiCodec extends StandardMessageCodec {
|
||||
const _TestResolutionStrategyHostApiCodec();
|
||||
@override
|
||||
void writeValue(WriteBuffer buffer, Object? value) {
|
||||
if (value is ResolutionInfo) {
|
||||
@ -1167,12 +1137,128 @@ class _TestImageAnalysisHostApiCodec extends StandardMessageCodec {
|
||||
}
|
||||
}
|
||||
|
||||
abstract class TestResolutionStrategyHostApi {
|
||||
static TestDefaultBinaryMessengerBinding? get _testBinaryMessengerBinding =>
|
||||
TestDefaultBinaryMessengerBinding.instance;
|
||||
static const MessageCodec<Object?> codec =
|
||||
_TestResolutionStrategyHostApiCodec();
|
||||
|
||||
void create(int identifier, ResolutionInfo? boundSize, int? fallbackRule);
|
||||
|
||||
static void setup(TestResolutionStrategyHostApi? api,
|
||||
{BinaryMessenger? binaryMessenger}) {
|
||||
{
|
||||
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
|
||||
'dev.flutter.pigeon.ResolutionStrategyHostApi.create', codec,
|
||||
binaryMessenger: binaryMessenger);
|
||||
if (api == null) {
|
||||
_testBinaryMessengerBinding!.defaultBinaryMessenger
|
||||
.setMockDecodedMessageHandler<Object?>(channel, null);
|
||||
} else {
|
||||
_testBinaryMessengerBinding!.defaultBinaryMessenger
|
||||
.setMockDecodedMessageHandler<Object?>(channel,
|
||||
(Object? message) async {
|
||||
assert(message != null,
|
||||
'Argument for dev.flutter.pigeon.ResolutionStrategyHostApi.create was null.');
|
||||
final List<Object?> args = (message as List<Object?>?)!;
|
||||
final int? arg_identifier = (args[0] as int?);
|
||||
assert(arg_identifier != null,
|
||||
'Argument for dev.flutter.pigeon.ResolutionStrategyHostApi.create was null, expected non-null int.');
|
||||
final ResolutionInfo? arg_boundSize = (args[1] as ResolutionInfo?);
|
||||
final int? arg_fallbackRule = (args[2] as int?);
|
||||
api.create(arg_identifier!, arg_boundSize, arg_fallbackRule);
|
||||
return <Object?>[];
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
abstract class TestResolutionSelectorHostApi {
|
||||
static TestDefaultBinaryMessengerBinding? get _testBinaryMessengerBinding =>
|
||||
TestDefaultBinaryMessengerBinding.instance;
|
||||
static const MessageCodec<Object?> codec = StandardMessageCodec();
|
||||
|
||||
void create(int identifier, int? resolutionStrategyIdentifier,
|
||||
int? aspectRatioStrategyIdentifier);
|
||||
|
||||
static void setup(TestResolutionSelectorHostApi? api,
|
||||
{BinaryMessenger? binaryMessenger}) {
|
||||
{
|
||||
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
|
||||
'dev.flutter.pigeon.ResolutionSelectorHostApi.create', codec,
|
||||
binaryMessenger: binaryMessenger);
|
||||
if (api == null) {
|
||||
_testBinaryMessengerBinding!.defaultBinaryMessenger
|
||||
.setMockDecodedMessageHandler<Object?>(channel, null);
|
||||
} else {
|
||||
_testBinaryMessengerBinding!.defaultBinaryMessenger
|
||||
.setMockDecodedMessageHandler<Object?>(channel,
|
||||
(Object? message) async {
|
||||
assert(message != null,
|
||||
'Argument for dev.flutter.pigeon.ResolutionSelectorHostApi.create was null.');
|
||||
final List<Object?> args = (message as List<Object?>?)!;
|
||||
final int? arg_identifier = (args[0] as int?);
|
||||
assert(arg_identifier != null,
|
||||
'Argument for dev.flutter.pigeon.ResolutionSelectorHostApi.create was null, expected non-null int.');
|
||||
final int? arg_resolutionStrategyIdentifier = (args[1] as int?);
|
||||
final int? arg_aspectRatioStrategyIdentifier = (args[2] as int?);
|
||||
api.create(arg_identifier!, arg_resolutionStrategyIdentifier,
|
||||
arg_aspectRatioStrategyIdentifier);
|
||||
return <Object?>[];
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
abstract class TestAspectRatioStrategyHostApi {
|
||||
static TestDefaultBinaryMessengerBinding? get _testBinaryMessengerBinding =>
|
||||
TestDefaultBinaryMessengerBinding.instance;
|
||||
static const MessageCodec<Object?> codec = StandardMessageCodec();
|
||||
|
||||
void create(int identifier, int preferredAspectRatio, int fallbackRule);
|
||||
|
||||
static void setup(TestAspectRatioStrategyHostApi? api,
|
||||
{BinaryMessenger? binaryMessenger}) {
|
||||
{
|
||||
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
|
||||
'dev.flutter.pigeon.AspectRatioStrategyHostApi.create', codec,
|
||||
binaryMessenger: binaryMessenger);
|
||||
if (api == null) {
|
||||
_testBinaryMessengerBinding!.defaultBinaryMessenger
|
||||
.setMockDecodedMessageHandler<Object?>(channel, null);
|
||||
} else {
|
||||
_testBinaryMessengerBinding!.defaultBinaryMessenger
|
||||
.setMockDecodedMessageHandler<Object?>(channel,
|
||||
(Object? message) async {
|
||||
assert(message != null,
|
||||
'Argument for dev.flutter.pigeon.AspectRatioStrategyHostApi.create was null.');
|
||||
final List<Object?> args = (message as List<Object?>?)!;
|
||||
final int? arg_identifier = (args[0] as int?);
|
||||
assert(arg_identifier != null,
|
||||
'Argument for dev.flutter.pigeon.AspectRatioStrategyHostApi.create was null, expected non-null int.');
|
||||
final int? arg_preferredAspectRatio = (args[1] as int?);
|
||||
assert(arg_preferredAspectRatio != null,
|
||||
'Argument for dev.flutter.pigeon.AspectRatioStrategyHostApi.create was null, expected non-null int.');
|
||||
final int? arg_fallbackRule = (args[2] as int?);
|
||||
assert(arg_fallbackRule != null,
|
||||
'Argument for dev.flutter.pigeon.AspectRatioStrategyHostApi.create was null, expected non-null int.');
|
||||
api.create(
|
||||
arg_identifier!, arg_preferredAspectRatio!, arg_fallbackRule!);
|
||||
return <Object?>[];
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
abstract class TestImageAnalysisHostApi {
|
||||
static TestDefaultBinaryMessengerBinding? get _testBinaryMessengerBinding =>
|
||||
TestDefaultBinaryMessengerBinding.instance;
|
||||
static const MessageCodec<Object?> codec = _TestImageAnalysisHostApiCodec();
|
||||
static const MessageCodec<Object?> codec = StandardMessageCodec();
|
||||
|
||||
void create(int identifier, ResolutionInfo? targetResolutionIdentifier);
|
||||
void create(int identifier, int? resolutionSelectorId);
|
||||
|
||||
void setAnalyzer(int identifier, int analyzerIdentifier);
|
||||
|
||||
@ -1197,9 +1283,8 @@ abstract class TestImageAnalysisHostApi {
|
||||
final int? arg_identifier = (args[0] as int?);
|
||||
assert(arg_identifier != null,
|
||||
'Argument for dev.flutter.pigeon.ImageAnalysisHostApi.create was null, expected non-null int.');
|
||||
final ResolutionInfo? arg_targetResolutionIdentifier =
|
||||
(args[1] as ResolutionInfo?);
|
||||
api.create(arg_identifier!, arg_targetResolutionIdentifier);
|
||||
final int? arg_resolutionSelectorId = (args[1] as int?);
|
||||
api.create(arg_identifier!, arg_resolutionSelectorId);
|
||||
return <Object?>[];
|
||||
});
|
||||
}
|
||||
|
Reference in New Issue
Block a user