Compare commits
63 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0ad6dbe102 | |||
| c7c0173da1 | |||
| d32dfc72de | |||
| 54f5c2bb65 | |||
| 91d8819cd9 | |||
| 180c238ae2 | |||
| d0969068ed | |||
| 7fe3db197e | |||
| ad42f3a675 | |||
| da7ebf7c35 | |||
| 0375a0c78d | |||
| 96685954b1 | |||
| ee73135b8d | |||
| 290994b83e | |||
| 4663358edd | |||
| 1df33da0c6 | |||
| 80c290cb1f | |||
| 3b8e8a8395 | |||
| 15e4f0aa9a | |||
| 33ea208754 | |||
| b6ade7868a | |||
| 295777c622 | |||
| 42339f800c | |||
| 6df93c4527 | |||
| 8d5b16c4bd | |||
| 7e9c31aabc | |||
| add2692f37 | |||
| 43029afab3 | |||
| 358bd1b7f3 | |||
| eb0746a780 | |||
| 58e5e93382 | |||
| 6d22e7c6ae | |||
| 0bf4a3df8f | |||
| 57729b9dd8 | |||
| f3d67273a2 | |||
| 0b0ded639b | |||
| 898769b1a4 | |||
| 0ce7f5e687 | |||
| c2b8755f5f | |||
| 628781b706 | |||
| 3dfa659723 | |||
| 37ec1addde | |||
| 6614785f7b | |||
| e89a06e4e0 | |||
| 4f46df5bfd | |||
| e5c60fb31f | |||
| 88c8281f27 | |||
| 4249bc5b30 | |||
| 541bd2d740 | |||
| b25faddf57 | |||
| 82501be283 | |||
| fcf1432c43 | |||
| 79e8b58167 | |||
| 6ad0e214da | |||
| 17f897e8a1 | |||
| 582174aeb1 | |||
| 023743135e | |||
| ba031c1437 | |||
| a951882fe9 | |||
| 2d0cc63637 | |||
| 5b953c1df2 | |||
| f25ea5d39f | |||
| aab760bab8 |
@@ -2,6 +2,9 @@
|
||||
|
||||

|
||||
|
||||
|
||||

|
||||
|
||||
Camera API in Android is hard. Having 2 different API for new and old Camera does not make things any easier. But fret not, that is your lucky day! After several years of working with Camera we came up with Fotoapparat.
|
||||
|
||||
What it provides:
|
||||
@@ -46,6 +49,7 @@ Configure `Fotoapparat` instance
|
||||
Fotoapparat
|
||||
.with(context)
|
||||
.into(cameraView) // view which will draw the camera preview
|
||||
.previewScaleType(ScaleType.CENTER_CROP) // we want the preview to fill the view
|
||||
.photoSize(biggestSize()) // we want to have the biggest photo possible
|
||||
.lensPosition(back()) // we want back camera
|
||||
.focusMode(firstAvailable( // (optional) use the first focus mode which is supported by device
|
||||
@@ -119,6 +123,22 @@ photoResult
|
||||
});
|
||||
```
|
||||
|
||||
## Update parameters
|
||||
|
||||
It is also possible to update some parameters after `Fotoapparat` was already started.
|
||||
|
||||
```java
|
||||
fotoapparat.updateParameters(
|
||||
UpdateRequest.builder()
|
||||
.flash(
|
||||
isTurnedOn
|
||||
? torch()
|
||||
: off()
|
||||
)
|
||||
.build()
|
||||
)
|
||||
```
|
||||
|
||||
## Set up
|
||||
|
||||
Add dependency to your `build.gradle`
|
||||
@@ -128,16 +148,20 @@ repositories {
|
||||
maven { url 'https://jitpack.io' }
|
||||
}
|
||||
|
||||
compile 'io.fotoapparat.fotoapparat:library:1.0.2'
|
||||
compile 'io.fotoapparat.fotoapparat:library:1.3.0'
|
||||
```
|
||||
|
||||
Camera permission will be automatically added to your `AndroidManifest.xml`. Do not forget to request this permission on Marshmallow and higher.
|
||||
|
||||
## Face detection
|
||||
|
||||
Optionally, you can check out our other library which adds face detection capabilities - [FaceDetector](https://github.com/Fotoapparat/FaceDetector).
|
||||
|
||||
## Credits
|
||||
|
||||
We want to say thanks to [Mark Murphy](https://github.com/commonsguy) for the awesome job he did with [CWAC-Camera](https://github.com/commonsguy/cwac-camera). We were using his library for a couple of years and now we feel that Fotoapparat is a next step in the right direction.
|
||||
|
||||
We also want to say many thanks to [Leander Lenzing](http://leanderlenzing.com/) for the amazing icon. Don't forget to follow his work in [dribbble](https://dribbble.com/leanderlenzing).
|
||||
|
||||
## License
|
||||
|
||||
|
||||
@@ -19,13 +19,16 @@ android {
|
||||
minifyEnabled false
|
||||
}
|
||||
}
|
||||
|
||||
testOptions {
|
||||
unitTests.returnDefaultValues = true
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile "com.android.support:appcompat-v7:${project.appCompatVersion}"
|
||||
compile "com.android.support:support-annotations:${project.appCompatVersion}"
|
||||
|
||||
testCompile "junit:junit:${project.junitVersion}"
|
||||
testCompile "org.mockito:mockito-core:${project.mockitoVersion}"
|
||||
testCompile 'commons-io:commons-io:2.5'
|
||||
|
||||
}
|
||||
@@ -1,10 +1,14 @@
|
||||
package io.fotoapparat;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.FloatRange;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import io.fotoapparat.error.Callbacks;
|
||||
import io.fotoapparat.error.CameraErrorCallback;
|
||||
import io.fotoapparat.hardware.CameraDevice;
|
||||
import io.fotoapparat.hardware.orientation.OrientationSensor;
|
||||
import io.fotoapparat.hardware.orientation.RotationListener;
|
||||
@@ -12,15 +16,20 @@ import io.fotoapparat.hardware.orientation.ScreenOrientationProvider;
|
||||
import io.fotoapparat.parameter.provider.CapabilitiesProvider;
|
||||
import io.fotoapparat.parameter.provider.InitialParametersProvider;
|
||||
import io.fotoapparat.parameter.provider.InitialParametersValidator;
|
||||
import io.fotoapparat.parameter.update.UpdateRequest;
|
||||
import io.fotoapparat.result.CapabilitiesResult;
|
||||
import io.fotoapparat.result.FocusResult;
|
||||
import io.fotoapparat.result.PendingResult;
|
||||
import io.fotoapparat.result.PhotoResult;
|
||||
import io.fotoapparat.routine.AutoFocusRoutine;
|
||||
import io.fotoapparat.routine.CheckAvailabilityRoutine;
|
||||
import io.fotoapparat.routine.ConfigurePreviewStreamRoutine;
|
||||
import io.fotoapparat.routine.StartCameraRoutine;
|
||||
import io.fotoapparat.routine.StopCameraRoutine;
|
||||
import io.fotoapparat.routine.TakePictureRoutine;
|
||||
import io.fotoapparat.routine.UpdateOrientationRoutine;
|
||||
import io.fotoapparat.routine.focus.AutoFocusRoutine;
|
||||
import io.fotoapparat.routine.parameter.UpdateParametersRoutine;
|
||||
import io.fotoapparat.routine.picture.TakePictureRoutine;
|
||||
import io.fotoapparat.routine.zoom.UpdateZoomLevelRoutine;
|
||||
|
||||
/**
|
||||
* Camera. Takes pictures.
|
||||
@@ -37,6 +46,8 @@ public class Fotoapparat {
|
||||
private final TakePictureRoutine takePictureRoutine;
|
||||
private final AutoFocusRoutine autoFocusRoutine;
|
||||
private final CheckAvailabilityRoutine checkAvailabilityRoutine;
|
||||
private final UpdateParametersRoutine updateParametersRoutine;
|
||||
private final UpdateZoomLevelRoutine updateZoomLevelRoutine;
|
||||
private final Executor executor;
|
||||
|
||||
private boolean started = false;
|
||||
@@ -49,6 +60,8 @@ public class Fotoapparat {
|
||||
TakePictureRoutine takePictureRoutine,
|
||||
AutoFocusRoutine autoFocusRoutine,
|
||||
CheckAvailabilityRoutine checkAvailabilityRoutine,
|
||||
UpdateParametersRoutine updateParametersRoutine,
|
||||
UpdateZoomLevelRoutine updateZoomLevelRoutine,
|
||||
Executor executor) {
|
||||
this.startCameraRoutine = startCameraRoutine;
|
||||
this.stopCameraRoutine = stopCameraRoutine;
|
||||
@@ -58,6 +71,8 @@ public class Fotoapparat {
|
||||
this.takePictureRoutine = takePictureRoutine;
|
||||
this.autoFocusRoutine = autoFocusRoutine;
|
||||
this.checkAvailabilityRoutine = checkAvailabilityRoutine;
|
||||
this.updateParametersRoutine = updateParametersRoutine;
|
||||
this.updateZoomLevelRoutine = updateZoomLevelRoutine;
|
||||
this.executor = executor;
|
||||
}
|
||||
|
||||
@@ -70,8 +85,12 @@ public class Fotoapparat {
|
||||
}
|
||||
|
||||
static Fotoapparat create(FotoapparatBuilder builder) {
|
||||
CameraErrorCallback cameraErrorCallback = Callbacks.onMainThread(
|
||||
builder.cameraErrorCallback
|
||||
);
|
||||
|
||||
CameraDevice cameraDevice = builder.cameraProvider.get(builder.logger);
|
||||
|
||||
ScreenOrientationProvider screenOrientationProvider = new ScreenOrientationProvider(builder.context);
|
||||
RotationListener rotationListener = new RotationListener(builder.context);
|
||||
|
||||
@@ -88,9 +107,11 @@ public class Fotoapparat {
|
||||
StartCameraRoutine startCameraRoutine = new StartCameraRoutine(
|
||||
cameraDevice,
|
||||
builder.renderer,
|
||||
builder.scaleType,
|
||||
builder.lensPositionSelector,
|
||||
screenOrientationProvider,
|
||||
initialParametersProvider
|
||||
initialParametersProvider,
|
||||
cameraErrorCallback
|
||||
);
|
||||
|
||||
StopCameraRoutine stopCameraRoutine = new StopCameraRoutine(cameraDevice);
|
||||
@@ -121,13 +142,24 @@ public class Fotoapparat {
|
||||
SERIAL_EXECUTOR
|
||||
);
|
||||
|
||||
AutoFocusRoutine autoFocusRoutine = new AutoFocusRoutine(cameraDevice);
|
||||
AutoFocusRoutine autoFocusRoutine = new AutoFocusRoutine(
|
||||
cameraDevice,
|
||||
SERIAL_EXECUTOR
|
||||
);
|
||||
|
||||
CheckAvailabilityRoutine checkAvailabilityRoutine = new CheckAvailabilityRoutine(
|
||||
cameraDevice,
|
||||
builder.lensPositionSelector
|
||||
);
|
||||
|
||||
UpdateParametersRoutine updateParametersRoutine = new UpdateParametersRoutine(
|
||||
cameraDevice
|
||||
);
|
||||
|
||||
UpdateZoomLevelRoutine updateZoomLevelRoutine = new UpdateZoomLevelRoutine(
|
||||
cameraDevice
|
||||
);
|
||||
|
||||
return new Fotoapparat(
|
||||
startCameraRoutine,
|
||||
stopCameraRoutine,
|
||||
@@ -137,6 +169,8 @@ public class Fotoapparat {
|
||||
takePictureRoutine,
|
||||
autoFocusRoutine,
|
||||
checkAvailabilityRoutine,
|
||||
updateParametersRoutine,
|
||||
updateZoomLevelRoutine,
|
||||
SERIAL_EXECUTOR
|
||||
);
|
||||
}
|
||||
@@ -175,15 +209,54 @@ public class Fotoapparat {
|
||||
* Performs auto focus. If it is not available or not enabled, does nothing.
|
||||
*/
|
||||
public Fotoapparat autoFocus() {
|
||||
ensureStarted();
|
||||
|
||||
executor.execute(
|
||||
autoFocusRoutine
|
||||
);
|
||||
focus();
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to focus the camera asynchronously.
|
||||
*
|
||||
* @return the pending result of focus operation which will deliver result asynchronously.
|
||||
*/
|
||||
public PendingResult<FocusResult> focus() {
|
||||
ensureStarted();
|
||||
|
||||
return autoFocusRoutine.autoFocus();
|
||||
}
|
||||
|
||||
/**
|
||||
* Asynchronously updates parameters of the camera. Must be called only after {@link #start()}.
|
||||
*/
|
||||
public void updateParameters(@NonNull final UpdateRequest updateRequest) {
|
||||
ensureStarted();
|
||||
|
||||
executor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
updateParametersRoutine.updateParameters(updateRequest);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Asynchronously updates zoom level of the camera. Must be called only after {@link #start()}.
|
||||
* <p>
|
||||
* If zoom is not supported by the device - does nothing.
|
||||
*
|
||||
* @param zoomLevel zoom level of the camera. A value between 0 and 1.
|
||||
*/
|
||||
public void setZoom(@FloatRange(from = 0f, to = 1f) final float zoomLevel) {
|
||||
ensureStarted();
|
||||
|
||||
executor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
updateZoomLevelRoutine.updateZoomLevel(zoomLevel);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts camera.
|
||||
*
|
||||
|
||||
@@ -3,6 +3,7 @@ package io.fotoapparat;
|
||||
import android.content.Context;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import io.fotoapparat.error.CameraErrorCallback;
|
||||
import io.fotoapparat.hardware.CameraDevice;
|
||||
import io.fotoapparat.hardware.provider.CameraProvider;
|
||||
import io.fotoapparat.log.Logger;
|
||||
@@ -10,6 +11,7 @@ import io.fotoapparat.log.Loggers;
|
||||
import io.fotoapparat.parameter.Flash;
|
||||
import io.fotoapparat.parameter.FocusMode;
|
||||
import io.fotoapparat.parameter.LensPosition;
|
||||
import io.fotoapparat.parameter.ScaleType;
|
||||
import io.fotoapparat.parameter.Size;
|
||||
import io.fotoapparat.parameter.selector.FlashSelectors;
|
||||
import io.fotoapparat.parameter.selector.SelectorFunction;
|
||||
@@ -50,10 +52,14 @@ public class FotoapparatBuilder {
|
||||
);
|
||||
SelectorFunction<Flash> flashSelector = FlashSelectors.off();
|
||||
|
||||
ScaleType scaleType = ScaleType.CENTER_CROP;
|
||||
|
||||
FrameProcessor frameProcessor = null;
|
||||
|
||||
Logger logger = Loggers.none();
|
||||
|
||||
CameraErrorCallback cameraErrorCallback = CameraErrorCallback.NULL;
|
||||
|
||||
FotoapparatBuilder(@NonNull Context context) {
|
||||
this.context = context;
|
||||
}
|
||||
@@ -61,7 +67,7 @@ public class FotoapparatBuilder {
|
||||
/**
|
||||
* @param cameraProvider decides which {@link CameraDevice} to use.
|
||||
*/
|
||||
public FotoapparatBuilder cameraProvider(CameraProvider cameraProvider) {
|
||||
public FotoapparatBuilder cameraProvider(@NonNull CameraProvider cameraProvider) {
|
||||
this.cameraProvider = cameraProvider;
|
||||
return this;
|
||||
}
|
||||
@@ -69,7 +75,7 @@ public class FotoapparatBuilder {
|
||||
/**
|
||||
* @param selector selects size of the photo (in pixels) from list of available sizes.
|
||||
*/
|
||||
public FotoapparatBuilder photoSize(SelectorFunction<Size> selector) {
|
||||
public FotoapparatBuilder photoSize(@NonNull SelectorFunction<Size> selector) {
|
||||
photoSizeSelector = selector;
|
||||
return this;
|
||||
}
|
||||
@@ -77,15 +83,23 @@ public class FotoapparatBuilder {
|
||||
/**
|
||||
* @param selector selects size of preview stream (in pixels) from list of available sizes.
|
||||
*/
|
||||
public FotoapparatBuilder previewSize(SelectorFunction<Size> selector) {
|
||||
public FotoapparatBuilder previewSize(@NonNull SelectorFunction<Size> selector) {
|
||||
previewSizeSelector = selector;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param scaleType of preview inside the view.
|
||||
*/
|
||||
public FotoapparatBuilder previewScaleType(ScaleType scaleType) {
|
||||
this.scaleType = scaleType;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param selector selects focus mode from list of available modes.
|
||||
*/
|
||||
public FotoapparatBuilder focusMode(SelectorFunction<FocusMode> selector) {
|
||||
public FotoapparatBuilder focusMode(@NonNull SelectorFunction<FocusMode> selector) {
|
||||
focusModeSelector = selector;
|
||||
return this;
|
||||
}
|
||||
@@ -93,7 +107,7 @@ public class FotoapparatBuilder {
|
||||
/**
|
||||
* @param selector selects flash mode from list of available modes.
|
||||
*/
|
||||
public FotoapparatBuilder flash(SelectorFunction<Flash> selector) {
|
||||
public FotoapparatBuilder flash(@NonNull SelectorFunction<Flash> selector) {
|
||||
flashSelector = selector;
|
||||
return this;
|
||||
}
|
||||
@@ -101,7 +115,7 @@ public class FotoapparatBuilder {
|
||||
/**
|
||||
* @param selector camera sensor position from list of available positions.
|
||||
*/
|
||||
public FotoapparatBuilder lensPosition(SelectorFunction<LensPosition> selector) {
|
||||
public FotoapparatBuilder lensPosition(@NonNull SelectorFunction<LensPosition> selector) {
|
||||
lensPositionSelector = selector;
|
||||
return this;
|
||||
}
|
||||
@@ -110,7 +124,7 @@ public class FotoapparatBuilder {
|
||||
* @param frameProcessor receives preview frames for processing.
|
||||
* @see FrameProcessor
|
||||
*/
|
||||
public FotoapparatBuilder frameProcessor(FrameProcessor frameProcessor) {
|
||||
public FotoapparatBuilder frameProcessor(@NonNull FrameProcessor frameProcessor) {
|
||||
this.frameProcessor = frameProcessor;
|
||||
return this;
|
||||
}
|
||||
@@ -119,16 +133,25 @@ public class FotoapparatBuilder {
|
||||
* @param logger logger which will print logs. No logger is set by default.
|
||||
* @see Loggers
|
||||
*/
|
||||
public FotoapparatBuilder logger(Logger logger) {
|
||||
public FotoapparatBuilder logger(@NonNull Logger logger) {
|
||||
this.logger = logger;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param callback which will be notified when camera error happens in Fotoapparat.
|
||||
* @see CameraErrorCallback
|
||||
*/
|
||||
public FotoapparatBuilder cameraErrorCallback(@NonNull CameraErrorCallback callback) {
|
||||
this.cameraErrorCallback = callback;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param renderer view which will draw the stream from the camera.
|
||||
* @see CameraView
|
||||
*/
|
||||
public FotoapparatBuilder into(CameraRenderer renderer) {
|
||||
public FotoapparatBuilder into(@NonNull CameraRenderer renderer) {
|
||||
this.renderer = renderer;
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
package io.fotoapparat.error;
|
||||
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
|
||||
import io.fotoapparat.hardware.CameraException;
|
||||
|
||||
/**
|
||||
* Factory methods for callbacks.
|
||||
*/
|
||||
public class Callbacks {
|
||||
|
||||
private static final Handler MAIN_THREAD_HANDLER = new Handler(Looper.getMainLooper());
|
||||
|
||||
/**
|
||||
* @return CameraErrorCallback which will always move execution to the main thread.
|
||||
*/
|
||||
public static CameraErrorCallback onMainThread(final CameraErrorCallback original) {
|
||||
return new CameraErrorCallback() {
|
||||
@Override
|
||||
public void onError(final CameraException e) {
|
||||
if (Looper.myLooper() == Looper.getMainLooper()) {
|
||||
original.onError(e);
|
||||
} else {
|
||||
MAIN_THREAD_HANDLER.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
original.onError(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package io.fotoapparat.error;
|
||||
|
||||
import io.fotoapparat.hardware.CameraException;
|
||||
|
||||
/**
|
||||
* Notified when an camera error happens within Fotoapparat.
|
||||
* <p>
|
||||
* This method is always called from the main thread.
|
||||
*/
|
||||
public interface CameraErrorCallback {
|
||||
|
||||
/**
|
||||
* No-op implementation of {@link CameraErrorCallback}.
|
||||
*/
|
||||
CameraErrorCallback NULL = new CameraErrorCallback() {
|
||||
@Override
|
||||
public void onError(CameraException e) {
|
||||
// Do nothing
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Notified when a camera error happens within Fotoapparat.
|
||||
*/
|
||||
void onError(CameraException e);
|
||||
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
package io.fotoapparat.hardware;
|
||||
|
||||
import android.support.annotation.FloatRange;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import io.fotoapparat.hardware.operators.AutoFocusOperator;
|
||||
@@ -13,13 +15,14 @@ import io.fotoapparat.hardware.operators.PreviewOperator;
|
||||
import io.fotoapparat.hardware.operators.PreviewStreamOperator;
|
||||
import io.fotoapparat.hardware.operators.RendererParametersOperator;
|
||||
import io.fotoapparat.hardware.operators.SurfaceOperator;
|
||||
import io.fotoapparat.hardware.operators.ZoomOperator;
|
||||
import io.fotoapparat.hardware.provider.AvailableLensPositionsProvider;
|
||||
import io.fotoapparat.lens.FocusResult;
|
||||
import io.fotoapparat.parameter.LensPosition;
|
||||
import io.fotoapparat.parameter.Parameters;
|
||||
import io.fotoapparat.parameter.RendererParameters;
|
||||
import io.fotoapparat.photo.Photo;
|
||||
import io.fotoapparat.preview.PreviewStream;
|
||||
import io.fotoapparat.lens.FocusResult;
|
||||
|
||||
/**
|
||||
* Abstraction for camera hardware.
|
||||
@@ -27,7 +30,8 @@ import io.fotoapparat.lens.FocusResult;
|
||||
public interface CameraDevice extends CaptureOperator,
|
||||
PreviewOperator, CapabilitiesOperator, OrientationOperator, ParametersOperator,
|
||||
ConnectionOperator, SurfaceOperator, PreviewStreamOperator, RendererParametersOperator,
|
||||
ExposureMeasurementOperator, AutoFocusOperator, AvailableLensPositionsProvider {
|
||||
ExposureMeasurementOperator, AutoFocusOperator, AvailableLensPositionsProvider,
|
||||
ZoomOperator {
|
||||
|
||||
@Override
|
||||
void open(LensPosition lensPosition);
|
||||
@@ -71,4 +75,7 @@ public interface CameraDevice extends CaptureOperator,
|
||||
@Override
|
||||
List<LensPosition> getAvailableLensPositions();
|
||||
|
||||
@Override
|
||||
void setZoom(@FloatRange(from = 0f, to = 1f) float level);
|
||||
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ package io.fotoapparat.hardware;
|
||||
* A generic camera exception.
|
||||
*/
|
||||
public class CameraException extends RuntimeException {
|
||||
|
||||
public CameraException(Exception e) {
|
||||
super(e);
|
||||
}
|
||||
@@ -11,4 +12,9 @@ public class CameraException extends RuntimeException {
|
||||
public CameraException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
|
||||
public CameraException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -22,15 +22,18 @@ public class Capabilities {
|
||||
private final Set<FocusMode> focusModes;
|
||||
@NonNull
|
||||
private final Set<Flash> flashModes;
|
||||
private final boolean zoomSupported;
|
||||
|
||||
public Capabilities(@NonNull Set<Size> photoSizes,
|
||||
@NonNull Set<Size> previewSizes,
|
||||
@NonNull Set<FocusMode> focusModes,
|
||||
@NonNull Set<Flash> flashModes) {
|
||||
@NonNull Set<Flash> flashModes,
|
||||
boolean zoomSupported) {
|
||||
this.photoSizes = photoSizes;
|
||||
this.previewSizes = previewSizes;
|
||||
this.focusModes = focusModes;
|
||||
this.flashModes = flashModes;
|
||||
this.zoomSupported = zoomSupported;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -41,7 +44,8 @@ public class Capabilities {
|
||||
Collections.<Size>emptySet(),
|
||||
Collections.<Size>emptySet(),
|
||||
Collections.<FocusMode>emptySet(),
|
||||
Collections.<Flash>emptySet()
|
||||
Collections.<Flash>emptySet(),
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
@@ -73,6 +77,13 @@ public class Capabilities {
|
||||
return flashModes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@code true} if zoom feature is supported. {@code false} if it is not supported.
|
||||
*/
|
||||
public boolean isZoomSupported() {
|
||||
return zoomSupported;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
@@ -80,7 +91,8 @@ public class Capabilities {
|
||||
|
||||
Capabilities that = (Capabilities) o;
|
||||
|
||||
return photoSizes.equals(that.photoSizes)
|
||||
return zoomSupported == that.zoomSupported
|
||||
&& photoSizes.equals(that.photoSizes)
|
||||
&& previewSizes.equals(that.previewSizes)
|
||||
&& focusModes.equals(that.focusModes)
|
||||
&& flashModes.equals(that.flashModes);
|
||||
@@ -93,6 +105,7 @@ public class Capabilities {
|
||||
result = 31 * result + previewSizes.hashCode();
|
||||
result = 31 * result + focusModes.hashCode();
|
||||
result = 31 * result + flashModes.hashCode();
|
||||
result = 31 * result + (zoomSupported ? 1 : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -103,6 +116,7 @@ public class Capabilities {
|
||||
", previewSizes=" + previewSizes +
|
||||
", focusModes=" + focusModes +
|
||||
", flashModes=" + flashModes +
|
||||
", zoomSupported=" + zoomSupported +
|
||||
'}';
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
package io.fotoapparat.hardware.operators;
|
||||
|
||||
import android.support.annotation.FloatRange;
|
||||
|
||||
/**
|
||||
* Modifies zoom level of the camera.
|
||||
*/
|
||||
public interface ZoomOperator {
|
||||
|
||||
/**
|
||||
* Changes zoom level of the camera. Must be called only if zoom is supported.
|
||||
*
|
||||
* @param level normalized zoom level. Value in range [0..1].
|
||||
*/
|
||||
void setZoom(@FloatRange(from = 0f, to = 1f) float level);
|
||||
|
||||
}
|
||||
@@ -1,22 +1,30 @@
|
||||
package io.fotoapparat.hardware.v1;
|
||||
|
||||
import android.hardware.Camera;
|
||||
import android.support.annotation.FloatRange;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.view.SurfaceView;
|
||||
import android.view.TextureView;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import io.fotoapparat.hardware.CameraDevice;
|
||||
import io.fotoapparat.hardware.CameraException;
|
||||
import io.fotoapparat.hardware.Capabilities;
|
||||
import io.fotoapparat.hardware.operators.ParametersOperator;
|
||||
import io.fotoapparat.hardware.orientation.OrientationUtils;
|
||||
import io.fotoapparat.hardware.provider.AvailableLensPositionsProvider;
|
||||
import io.fotoapparat.hardware.provider.V1AvailableLensPositionProvider;
|
||||
import io.fotoapparat.hardware.v1.capabilities.CapabilitiesFactory;
|
||||
import io.fotoapparat.hardware.v1.parameters.SplitParametersOperator;
|
||||
import io.fotoapparat.hardware.v1.parameters.SupressExceptionsParametersOperator;
|
||||
import io.fotoapparat.hardware.v1.parameters.SwitchOnFailureParametersOperator;
|
||||
import io.fotoapparat.hardware.v1.parameters.UnsafeParametersOperator;
|
||||
import io.fotoapparat.lens.FocusResult;
|
||||
import io.fotoapparat.log.Logger;
|
||||
import io.fotoapparat.parameter.LensPosition;
|
||||
@@ -32,18 +40,25 @@ import io.fotoapparat.preview.PreviewStream;
|
||||
@SuppressWarnings("deprecation")
|
||||
public class Camera1 implements CameraDevice {
|
||||
|
||||
private static final long AUTOFOCUS_TIMEOUT_SECONDS = 3L;
|
||||
|
||||
private final CapabilitiesFactory capabilitiesFactory;
|
||||
private final ParametersConverter parametersConverter;
|
||||
private final AvailableLensPositionsProvider availableLensPositionsProvider;
|
||||
private final Logger logger;
|
||||
|
||||
private Camera camera;
|
||||
private int cameraId;
|
||||
private int cameraId = -1;
|
||||
private PreviewStream1 previewStream;
|
||||
|
||||
private Throwable lastStacktrace;
|
||||
private int imageRotation;
|
||||
|
||||
@Nullable
|
||||
private Capabilities cachedCapabilities = null;
|
||||
@Nullable
|
||||
private Camera.Parameters cachedZoomParameters = null;
|
||||
|
||||
public Camera1(Logger logger) {
|
||||
this.capabilitiesFactory = new CapabilitiesFactory();
|
||||
this.parametersConverter = new ParametersConverter();
|
||||
@@ -51,6 +66,10 @@ public class Camera1 implements CameraDevice {
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
private static void throwOnFailSetDisplaySurface(Object displaySurface, IOException e) {
|
||||
throw new CameraException("Unable to set display surface: " + displaySurface, e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void open(LensPosition lensPosition) {
|
||||
recordMethod();
|
||||
@@ -60,7 +79,7 @@ public class Camera1 implements CameraDevice {
|
||||
camera = Camera.open(cameraId);
|
||||
previewStream = new PreviewStream1(camera);
|
||||
} catch (RuntimeException e) {
|
||||
throw new CameraException(e);
|
||||
throwOnFailedToOpenCamera(lensPosition, e);
|
||||
}
|
||||
|
||||
camera.setErrorCallback(new Camera.ErrorCallback() {
|
||||
@@ -70,11 +89,18 @@ public class Camera1 implements CameraDevice {
|
||||
lastStacktrace.printStackTrace();
|
||||
}
|
||||
|
||||
throw new IllegalStateException("Camera error code: " + error);
|
||||
logger.log("Camera error code: " + error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void throwOnFailedToOpenCamera(LensPosition lensPosition, RuntimeException e) {
|
||||
throw new CameraException(
|
||||
"Failed to open camera with lens position: " + lensPosition + " and id: " + cameraId,
|
||||
e
|
||||
);
|
||||
}
|
||||
|
||||
private int cameraIdForLensPosition(LensPosition lensPosition) {
|
||||
int numberOfCameras = Camera.getNumberOfCameras();
|
||||
|
||||
@@ -104,7 +130,9 @@ public class Camera1 implements CameraDevice {
|
||||
public void close() {
|
||||
recordMethod();
|
||||
|
||||
if (camera != null) {
|
||||
cachedCapabilities = null;
|
||||
|
||||
if (isCameraOpened()) {
|
||||
camera.release();
|
||||
}
|
||||
}
|
||||
@@ -113,14 +141,27 @@ public class Camera1 implements CameraDevice {
|
||||
public void startPreview() {
|
||||
recordMethod();
|
||||
|
||||
camera.startPreview();
|
||||
try {
|
||||
camera.startPreview();
|
||||
} catch (RuntimeException e) {
|
||||
throwOnFailStartPreview(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void throwOnFailStartPreview(RuntimeException e) {
|
||||
throw new CameraException(
|
||||
"Failed to start preview for camera devices: " + cameraId,
|
||||
e
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopPreview() {
|
||||
recordMethod();
|
||||
|
||||
camera.stopPreview();
|
||||
if (isCameraOpened()) {
|
||||
camera.stopPreview();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -130,7 +171,7 @@ public class Camera1 implements CameraDevice {
|
||||
try {
|
||||
trySetDisplaySurface(displaySurface);
|
||||
} catch (IOException e) {
|
||||
throw new CameraException(e);
|
||||
throwOnFailSetDisplaySurface(displaySurface, e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -138,6 +179,10 @@ public class Camera1 implements CameraDevice {
|
||||
public void setDisplayOrientation(int degrees) {
|
||||
recordMethod();
|
||||
|
||||
if (!isCameraOpened()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Camera.CameraInfo info = getCameraInfo(cameraId);
|
||||
|
||||
imageRotation = computeImageOrientation(degrees, info);
|
||||
@@ -170,21 +215,46 @@ public class Camera1 implements CameraDevice {
|
||||
public void updateParameters(Parameters parameters) {
|
||||
recordMethod();
|
||||
|
||||
Camera.Parameters cameraParameters = parametersConverter.convert(
|
||||
parameters,
|
||||
camera.getParameters()
|
||||
parametersOperator().updateParameters(parameters);
|
||||
|
||||
cachedZoomParameters = null;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private SwitchOnFailureParametersOperator parametersOperator() {
|
||||
ParametersOperator unsafeParametersOperator = new UnsafeParametersOperator(
|
||||
camera,
|
||||
parametersConverter
|
||||
);
|
||||
|
||||
camera.setParameters(cameraParameters);
|
||||
ParametersOperator fallbackOperator = new SplitParametersOperator(
|
||||
new SupressExceptionsParametersOperator(
|
||||
unsafeParametersOperator,
|
||||
logger
|
||||
)
|
||||
);
|
||||
|
||||
return new SwitchOnFailureParametersOperator(
|
||||
unsafeParametersOperator,
|
||||
fallbackOperator
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Capabilities getCapabilities() {
|
||||
if (cachedCapabilities != null) {
|
||||
return cachedCapabilities;
|
||||
}
|
||||
|
||||
recordMethod();
|
||||
|
||||
return capabilitiesFactory.fromParameters(
|
||||
Capabilities capabilities = capabilitiesFactory.fromParameters(
|
||||
camera.getParameters()
|
||||
);
|
||||
|
||||
cachedCapabilities = capabilities;
|
||||
|
||||
return capabilities;
|
||||
}
|
||||
|
||||
private void trySetDisplaySurface(Object displaySurface) throws IOException {
|
||||
@@ -232,25 +302,32 @@ public class Camera1 implements CameraDevice {
|
||||
@Override
|
||||
public PreviewStream getPreviewStream() {
|
||||
recordMethod();
|
||||
ensurePreviewStreamAvailable();
|
||||
|
||||
return previewStream;
|
||||
return isPreviewStreamInitialized()
|
||||
? previewStream
|
||||
: PreviewStream.NULL;
|
||||
}
|
||||
|
||||
private void ensurePreviewStreamAvailable() {
|
||||
if (previewStream == null) {
|
||||
throw new IllegalStateException("Preview stream is null. Make sure camera is opened.");
|
||||
}
|
||||
private boolean isPreviewStreamInitialized() {
|
||||
return previewStream != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RendererParameters getRendererParameters() {
|
||||
recordMethod();
|
||||
|
||||
return new RendererParameters(
|
||||
RendererParameters rendererParameters = new RendererParameters(
|
||||
previewSize(),
|
||||
imageRotation
|
||||
);
|
||||
|
||||
logRendererParameters(rendererParameters);
|
||||
|
||||
return rendererParameters;
|
||||
}
|
||||
|
||||
private void logRendererParameters(RendererParameters rendererParameters) {
|
||||
logger.log("Renderer parameters are: " + rendererParameters);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -258,15 +335,22 @@ public class Camera1 implements CameraDevice {
|
||||
recordMethod();
|
||||
|
||||
final CountDownLatch latch = new CountDownLatch(1);
|
||||
camera.autoFocus(new Camera.AutoFocusCallback() {
|
||||
@Override
|
||||
public void onAutoFocus(boolean success, Camera camera) {
|
||||
latch.countDown();
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
latch.await();
|
||||
camera.autoFocus(new Camera.AutoFocusCallback() {
|
||||
@Override
|
||||
public void onAutoFocus(boolean success, Camera camera) {
|
||||
latch.countDown();
|
||||
}
|
||||
});
|
||||
} catch (Exception e) {
|
||||
logFailedAutoFocus(e);
|
||||
|
||||
return FocusResult.none();
|
||||
}
|
||||
|
||||
try {
|
||||
latch.await(AUTOFOCUS_TIMEOUT_SECONDS, TimeUnit.SECONDS);
|
||||
} catch (InterruptedException e) {
|
||||
// Do nothing
|
||||
}
|
||||
@@ -274,9 +358,13 @@ public class Camera1 implements CameraDevice {
|
||||
return FocusResult.successNoMeasurement();
|
||||
}
|
||||
|
||||
private void logFailedAutoFocus(Exception e) {
|
||||
logger.log("Failed to perform autofocus using device " + cameraId + " e: " + e.getMessage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void measureExposure() {
|
||||
// TODO: 30.04.17
|
||||
// Do nothing. Not supported by Camera1.
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -284,6 +372,31 @@ public class Camera1 implements CameraDevice {
|
||||
return availableLensPositionsProvider.getAvailableLensPositions();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setZoom(@FloatRange(from = 0f, to = 1f) float level) {
|
||||
try {
|
||||
setZoomUnsafe(level);
|
||||
} catch (Exception e) {
|
||||
logFailedZoomUpdate(level, e);
|
||||
}
|
||||
}
|
||||
|
||||
private void setZoomUnsafe(@FloatRange(from = 0f, to = 1f) float level) {
|
||||
if (cachedZoomParameters == null) {
|
||||
cachedZoomParameters = camera.getParameters();
|
||||
}
|
||||
|
||||
cachedZoomParameters.setZoom(
|
||||
(int) (cachedZoomParameters.getMaxZoom() * level)
|
||||
);
|
||||
|
||||
camera.setParameters(cachedZoomParameters);
|
||||
}
|
||||
|
||||
private void logFailedZoomUpdate(float level, Exception e) {
|
||||
logger.log("Unable to change zoom level to " + level + " e: " + e.getMessage());
|
||||
}
|
||||
|
||||
private Size previewSize() {
|
||||
Camera.Size previewSize = camera.getParameters().getPreviewSize();
|
||||
|
||||
@@ -300,6 +413,10 @@ public class Camera1 implements CameraDevice {
|
||||
return info;
|
||||
}
|
||||
|
||||
private boolean isCameraOpened() {
|
||||
return camera != null;
|
||||
}
|
||||
|
||||
private void recordMethod() {
|
||||
lastStacktrace = new Exception();
|
||||
|
||||
|
||||
@@ -6,6 +6,8 @@ import android.support.annotation.NonNull;
|
||||
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import io.fotoapparat.parameter.Size;
|
||||
import io.fotoapparat.preview.Frame;
|
||||
@@ -18,6 +20,8 @@ import io.fotoapparat.preview.PreviewStream;
|
||||
@SuppressWarnings("deprecation")
|
||||
public class PreviewStream1 implements PreviewStream {
|
||||
|
||||
private static Executor FRAME_PROCESSORS_EXECUTOR = Executors.newSingleThreadExecutor();
|
||||
|
||||
private final Camera camera;
|
||||
|
||||
private final Set<FrameProcessor> frameProcessors = new LinkedHashSet<>();
|
||||
@@ -86,6 +90,15 @@ public class PreviewStream1 implements PreviewStream {
|
||||
camera.setPreviewCallbackWithBuffer(new Camera.PreviewCallback() {
|
||||
@Override
|
||||
public void onPreviewFrame(byte[] data, Camera camera) {
|
||||
dispatchFrameOnBackgroundThread(data);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void dispatchFrameOnBackgroundThread(final byte[] data) {
|
||||
FRAME_PROCESSORS_EXECUTOR.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
synchronized (frameProcessors) {
|
||||
dispatchFrame(data);
|
||||
}
|
||||
|
||||
@@ -29,7 +29,8 @@ public class CapabilitiesFactory {
|
||||
extractPictureSizes(parameters),
|
||||
extractPreviewSizes(parameters),
|
||||
extractFocusModes(parameters),
|
||||
extractFlashModes(parameters)
|
||||
extractFlashModes(parameters),
|
||||
parameters.isZoomSupported()
|
||||
);
|
||||
}
|
||||
|
||||
@@ -84,7 +85,6 @@ public class CapabilitiesFactory {
|
||||
}
|
||||
|
||||
result.add(FocusMode.FIXED);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
package io.fotoapparat.hardware.v1.parameters;
|
||||
|
||||
import io.fotoapparat.hardware.operators.ParametersOperator;
|
||||
import io.fotoapparat.parameter.Parameters;
|
||||
|
||||
/**
|
||||
* Instead of updating all parameters at once, updates each parameter one by one.
|
||||
*/
|
||||
public class SplitParametersOperator implements ParametersOperator {
|
||||
|
||||
private final ParametersOperator wrapped;
|
||||
|
||||
public SplitParametersOperator(ParametersOperator wrapped) {
|
||||
this.wrapped = wrapped;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateParameters(Parameters parameters) {
|
||||
for (Parameters.Type type : parameters.storedTypes()) {
|
||||
wrapped.updateParameters(
|
||||
newParameters(type, parameters.getValue(type))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private Parameters newParameters(Parameters.Type type, Object value) {
|
||||
Parameters parameters = new Parameters();
|
||||
parameters.putValue(type, value);
|
||||
|
||||
return parameters;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package io.fotoapparat.hardware.v1.parameters;
|
||||
|
||||
import io.fotoapparat.hardware.operators.ParametersOperator;
|
||||
import io.fotoapparat.log.Logger;
|
||||
import io.fotoapparat.parameter.Parameters;
|
||||
|
||||
/**
|
||||
* Tries to update parameters. If that fails, suppresses the exception and writes relevant
|
||||
* information to log.
|
||||
*/
|
||||
public class SupressExceptionsParametersOperator implements ParametersOperator {
|
||||
|
||||
private final ParametersOperator wrapped;
|
||||
private final Logger logger;
|
||||
|
||||
public SupressExceptionsParametersOperator(ParametersOperator wrapped,
|
||||
Logger logger) {
|
||||
this.wrapped = wrapped;
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateParameters(Parameters parameters) {
|
||||
try {
|
||||
wrapped.updateParameters(parameters);
|
||||
} catch (Exception e) {
|
||||
logger.log("Unable to set parameters: " + parameters);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package io.fotoapparat.hardware.v1.parameters;
|
||||
|
||||
import io.fotoapparat.hardware.operators.ParametersOperator;
|
||||
import io.fotoapparat.parameter.Parameters;
|
||||
|
||||
/**
|
||||
* Tries to execute first operator. If that fails, tries to execute the second one.
|
||||
*/
|
||||
public class SwitchOnFailureParametersOperator implements ParametersOperator {
|
||||
|
||||
private final ParametersOperator first;
|
||||
private final ParametersOperator second;
|
||||
|
||||
public SwitchOnFailureParametersOperator(ParametersOperator first,
|
||||
ParametersOperator second) {
|
||||
this.first = first;
|
||||
this.second = second;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateParameters(Parameters parameters) {
|
||||
try {
|
||||
first.updateParameters(parameters);
|
||||
} catch (Exception e) {
|
||||
second.updateParameters(parameters);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package io.fotoapparat.hardware.v1.parameters;
|
||||
|
||||
import android.hardware.Camera;
|
||||
|
||||
import io.fotoapparat.hardware.operators.ParametersOperator;
|
||||
import io.fotoapparat.hardware.v1.ParametersConverter;
|
||||
import io.fotoapparat.parameter.Parameters;
|
||||
|
||||
/**
|
||||
* Updates parameters of camera, possibly throwing a {@link RuntimeException} if something goes
|
||||
* wrong. We can't really know why camera might reject parameters, so it should be expected.
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public class UnsafeParametersOperator implements ParametersOperator {
|
||||
|
||||
private final Camera camera;
|
||||
private final ParametersConverter parametersConverter;
|
||||
|
||||
public UnsafeParametersOperator(Camera camera,
|
||||
ParametersConverter parametersConverter) {
|
||||
this.camera = camera;
|
||||
this.parametersConverter = parametersConverter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateParameters(Parameters parameters) {
|
||||
Camera.Parameters cameraParameters = parametersConverter.convert(
|
||||
parameters,
|
||||
camera.getParameters()
|
||||
);
|
||||
|
||||
camera.setParameters(cameraParameters);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package io.fotoapparat.hardware.v2;
|
||||
|
||||
import android.os.Build;
|
||||
import android.support.annotation.FloatRange;
|
||||
import android.support.annotation.RequiresApi;
|
||||
|
||||
import java.util.List;
|
||||
@@ -172,6 +173,11 @@ public class Camera2 implements CameraDevice {
|
||||
return availableLensPositionsProvider.getAvailableLensPositions();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setZoom(@FloatRange(from = 0f, to = 1f) float level) {
|
||||
throw new UnsupportedOperationException("Not implemented. We do not actively support Camera2 at the moment.");
|
||||
}
|
||||
|
||||
private void recordMethod() {
|
||||
Exception lastStacktrace = new Exception();
|
||||
|
||||
|
||||
@@ -23,78 +23,79 @@ import static io.fotoapparat.hardware.v2.parameters.converters.FlashConverter.ex
|
||||
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
|
||||
public class CapabilitiesFactory implements CapabilitiesOperator {
|
||||
|
||||
private final CameraConnection cameraConnection;
|
||||
private final CameraConnection cameraConnection;
|
||||
|
||||
public CapabilitiesFactory(CameraConnection cameraConnection) {
|
||||
this.cameraConnection = cameraConnection;
|
||||
}
|
||||
public CapabilitiesFactory(CameraConnection cameraConnection) {
|
||||
this.cameraConnection = cameraConnection;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Capabilities getCapabilities() {
|
||||
return new Capabilities(
|
||||
availableJpegSizes(),
|
||||
availablePreviewSizes(),
|
||||
availableFocusModes(),
|
||||
availableFlashModes()
|
||||
);
|
||||
}
|
||||
@Override
|
||||
public Capabilities getCapabilities() {
|
||||
return new Capabilities(
|
||||
availableJpegSizes(),
|
||||
availablePreviewSizes(),
|
||||
availableFocusModes(),
|
||||
availableFlashModes(),
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
private Set<Size> availableJpegSizes() {
|
||||
return characteristics().getJpegOutputSizes();
|
||||
}
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
private Set<Size> availableJpegSizes() {
|
||||
return characteristics().getJpegOutputSizes();
|
||||
}
|
||||
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
private Set<Size> availablePreviewSizes() {
|
||||
HashSet<Size> filteredOutputSizes = new HashSet<>();
|
||||
for (Size outputSize : characteristics().getSurfaceOutputSizes()) {
|
||||
if (outputSize.width <= PreviewSizeInfo.MAX_PREVIEW_WIDTH && outputSize.height <= PreviewSizeInfo.MAX_PREVIEW_HEIGHT) {
|
||||
filteredOutputSizes.add(outputSize);
|
||||
}
|
||||
}
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
private Set<Size> availablePreviewSizes() {
|
||||
HashSet<Size> filteredOutputSizes = new HashSet<>();
|
||||
for (Size outputSize : characteristics().getSurfaceOutputSizes()) {
|
||||
if (outputSize.width <= PreviewSizeInfo.MAX_PREVIEW_WIDTH && outputSize.height <= PreviewSizeInfo.MAX_PREVIEW_HEIGHT) {
|
||||
filteredOutputSizes.add(outputSize);
|
||||
}
|
||||
}
|
||||
|
||||
return filteredOutputSizes;
|
||||
}
|
||||
return filteredOutputSizes;
|
||||
}
|
||||
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
private Set<FocusMode> availableFocusModes() {
|
||||
Set<FocusMode> focusModes = new HashSet<>();
|
||||
for (int afMode : characteristics().autoFocusModes()) {
|
||||
focusModes.add(FocusConverter.afModeToFocus(afMode));
|
||||
}
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
private Set<FocusMode> availableFocusModes() {
|
||||
Set<FocusMode> focusModes = new HashSet<>();
|
||||
for (int afMode : characteristics().autoFocusModes()) {
|
||||
focusModes.add(FocusConverter.afModeToFocus(afMode));
|
||||
}
|
||||
|
||||
return focusModes;
|
||||
}
|
||||
return focusModes;
|
||||
}
|
||||
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
private Set<Flash> availableFlashModes() {
|
||||
if (characteristics().isFlashAvailable()) {
|
||||
return availableFlashUnitModes();
|
||||
}
|
||||
return Collections.singleton(Flash.OFF);
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
private Set<Flash> availableFlashModes() {
|
||||
if (characteristics().isFlashAvailable()) {
|
||||
return availableFlashUnitModes();
|
||||
}
|
||||
return Collections.singleton(Flash.OFF);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
private Set<Flash> availableFlashUnitModes() {
|
||||
Set<Flash> flashes = new HashSet<>();
|
||||
flashes.add(Flash.OFF);
|
||||
flashes.add(Flash.TORCH);
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
private Set<Flash> availableFlashUnitModes() {
|
||||
Set<Flash> flashes = new HashSet<>();
|
||||
flashes.add(Flash.OFF);
|
||||
flashes.add(Flash.TORCH);
|
||||
|
||||
int[] autoExposureModes = characteristics().autoExposureModes();
|
||||
int[] autoExposureModes = characteristics().autoExposureModes();
|
||||
|
||||
for (int autoExposureMode : autoExposureModes) {
|
||||
Flash flash = exposureModeToFlash(autoExposureMode);
|
||||
if (flash != null) {
|
||||
flashes.add(flash);
|
||||
}
|
||||
}
|
||||
for (int autoExposureMode : autoExposureModes) {
|
||||
Flash flash = exposureModeToFlash(autoExposureMode);
|
||||
if (flash != null) {
|
||||
flashes.add(flash);
|
||||
}
|
||||
}
|
||||
|
||||
return flashes;
|
||||
}
|
||||
return flashes;
|
||||
}
|
||||
|
||||
private Characteristics characteristics() {
|
||||
return cameraConnection.getCharacteristics();
|
||||
}
|
||||
private Characteristics characteristics() {
|
||||
return cameraConnection.getCharacteristics();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
package io.fotoapparat.hardware.v2.surface;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.graphics.SurfaceTexture;
|
||||
import android.os.Build;
|
||||
|
||||
import io.fotoapparat.parameter.Size;
|
||||
|
||||
/**
|
||||
* Sets the preview {@link Size} on a {@link SurfaceTexture}.
|
||||
*/
|
||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
||||
class SetTextureBufferSizeTask implements Runnable {
|
||||
|
||||
private final SurfaceTexture surfaceTexture;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package io.fotoapparat.parameter;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
@@ -14,6 +15,20 @@ public class Parameters {
|
||||
|
||||
private final Map<Type, Object> values = new HashMap<>();
|
||||
|
||||
/**
|
||||
* @return single {@link Parameters} which is a result of adding up all parameters in the list
|
||||
* using {@link Parameters#putAll(Parameters)}.
|
||||
*/
|
||||
public static Parameters combineParameters(Collection<Parameters> parametersList) {
|
||||
Parameters result = new Parameters();
|
||||
|
||||
for (Parameters parameters : parametersList) {
|
||||
result.putAll(parameters);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts value of given type, rewriting existing one (if any). Note that given value must be of
|
||||
* the type specified by {@link Type}.
|
||||
@@ -21,10 +36,12 @@ public class Parameters {
|
||||
* @param type type of the parameter to store.
|
||||
* @param value value of the parameter.
|
||||
*/
|
||||
public void putValue(Type type, Object value) {
|
||||
public Parameters putValue(Type type, Object value) {
|
||||
ensureType(type, value);
|
||||
|
||||
values.put(type, value);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
private void ensureType(Type type, Object value) {
|
||||
@@ -64,6 +81,36 @@ public class Parameters {
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts all parameters which are in input to current set of parameters. If there are duplicates,
|
||||
* they are overwritten.
|
||||
*/
|
||||
public void putAll(Parameters input) {
|
||||
values.putAll(input.values);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
Parameters that = (Parameters) o;
|
||||
|
||||
return values.equals(that.values);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return values.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Parameters{" +
|
||||
"values=" + values +
|
||||
'}';
|
||||
}
|
||||
|
||||
/**
|
||||
* Type of values which can be stored in {@link Parameters}.
|
||||
*/
|
||||
|
||||
@@ -33,7 +33,6 @@ public class RendererParameters {
|
||||
RendererParameters that = (RendererParameters) o;
|
||||
|
||||
return frameRotation == that.frameRotation && (previewSize != null ? previewSize.equals(that.previewSize) : that.previewSize == null);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -42,4 +41,12 @@ public class RendererParameters {
|
||||
result = 31 * result + frameRotation;
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RendererParameters{" +
|
||||
"previewSize=" + previewSize +
|
||||
", frameRotation=" + frameRotation +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
package io.fotoapparat.parameter;
|
||||
|
||||
/**
|
||||
* The scale type of the preview relatively to the view.
|
||||
*/
|
||||
public enum ScaleType {
|
||||
|
||||
/**
|
||||
* The preview will be scaled so as its one dimensions will be equal and the other one equal or
|
||||
* larger than the corresponding dimension of the view
|
||||
*/
|
||||
CENTER_CROP,
|
||||
|
||||
/**
|
||||
* The preview will be scaled so as its one dimensions will be equal and the other one equal or
|
||||
* smaller than the corresponding dimension of the view
|
||||
*/
|
||||
CENTER_INSIDE
|
||||
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package io.fotoapparat.parameter.factory;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import io.fotoapparat.hardware.Capabilities;
|
||||
import io.fotoapparat.parameter.Flash;
|
||||
import io.fotoapparat.parameter.FocusMode;
|
||||
import io.fotoapparat.parameter.Parameters;
|
||||
import io.fotoapparat.parameter.Size;
|
||||
import io.fotoapparat.parameter.selector.SelectorFunction;
|
||||
|
||||
/**
|
||||
* Functions which build {@link Parameters} from given {@link Capabilities} and selector functions.
|
||||
*/
|
||||
public class ParametersFactory {
|
||||
|
||||
/**
|
||||
* @return new parameters by selecting picture size from given capabilities.
|
||||
*/
|
||||
public static Parameters selectPictureSize(@NonNull Capabilities capabilities,
|
||||
@NonNull SelectorFunction<Size> selector) {
|
||||
return new Parameters().putValue(
|
||||
Parameters.Type.PICTURE_SIZE,
|
||||
selector.select(
|
||||
capabilities.supportedPictureSizes()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return new parameters by selecting preview size from given capabilities.
|
||||
*/
|
||||
public static Parameters selectPreviewSize(@NonNull Capabilities capabilities,
|
||||
@NonNull SelectorFunction<Size> selector) {
|
||||
return new Parameters().putValue(
|
||||
Parameters.Type.PREVIEW_SIZE,
|
||||
selector.select(
|
||||
capabilities.supportedPreviewSizes()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return new parameters by selecting focus mode from given capabilities.
|
||||
*/
|
||||
public static Parameters selectFocusMode(@NonNull Capabilities capabilities,
|
||||
@NonNull SelectorFunction<FocusMode> selector) {
|
||||
return new Parameters().putValue(
|
||||
Parameters.Type.FOCUS_MODE,
|
||||
selector.select(
|
||||
capabilities.supportedFocusModes()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return new parameters by selecting flash mode from given capabilities.
|
||||
*/
|
||||
public static Parameters selectFlashMode(@NonNull Capabilities capabilities,
|
||||
@NonNull SelectorFunction<Flash> selector) {
|
||||
return new Parameters().putValue(
|
||||
Parameters.Type.FLASH,
|
||||
selector.select(
|
||||
capabilities.supportedFlashModes()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -7,10 +7,13 @@ import io.fotoapparat.parameter.Flash;
|
||||
import io.fotoapparat.parameter.FocusMode;
|
||||
import io.fotoapparat.parameter.Parameters;
|
||||
import io.fotoapparat.parameter.Size;
|
||||
import io.fotoapparat.parameter.factory.ParametersFactory;
|
||||
import io.fotoapparat.parameter.selector.SelectorFunction;
|
||||
import io.fotoapparat.parameter.selector.Selectors;
|
||||
|
||||
import static io.fotoapparat.parameter.Parameters.combineParameters;
|
||||
import static io.fotoapparat.parameter.selector.AspectRatioSelectors.aspectRatio;
|
||||
import static java.util.Arrays.asList;
|
||||
|
||||
/**
|
||||
* Provides initial {@link Parameters} for {@link CameraDevice}.
|
||||
@@ -38,49 +41,72 @@ public class InitialParametersProvider {
|
||||
this.parametersValidator = parametersValidator;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return function which selects a valid preview size based on current picture size.
|
||||
*/
|
||||
static SelectorFunction<Size> validPreviewSizeSelector(Size photoSize,
|
||||
SelectorFunction<Size> original) {
|
||||
return Selectors
|
||||
.firstAvailable(
|
||||
previewWithSameAspectRatio(photoSize, original),
|
||||
original
|
||||
);
|
||||
}
|
||||
|
||||
private static SelectorFunction<Size> previewWithSameAspectRatio(Size photoSize,
|
||||
SelectorFunction<Size> original) {
|
||||
return aspectRatio(
|
||||
photoSize.getAspectRatio(),
|
||||
original
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@link Parameters} which will be used by {@link CameraDevice} on start-up.
|
||||
*/
|
||||
public Parameters initialParameters() {
|
||||
Capabilities capabilities = capabilitiesOperator.getCapabilities();
|
||||
|
||||
Parameters parameters = new Parameters();
|
||||
|
||||
putPictureSize(capabilities, parameters);
|
||||
putPreviewSize(capabilities, parameters);
|
||||
putFocusMode(capabilities, parameters);
|
||||
putFlash(capabilities, parameters);
|
||||
Parameters parameters = combineParameters(asList(
|
||||
pictureSizeParameters(capabilities),
|
||||
previewSizeParameters(capabilities),
|
||||
focusModeParameters(capabilities),
|
||||
flashModeParameters(capabilities)
|
||||
));
|
||||
|
||||
parametersValidator.validate(parameters);
|
||||
|
||||
return parameters;
|
||||
}
|
||||
|
||||
private void putPreviewSize(Capabilities capabilities, Parameters parameters) {
|
||||
Size photoSize = photoSize(capabilities);
|
||||
|
||||
parameters.putValue(
|
||||
Parameters.Type.PREVIEW_SIZE,
|
||||
Selectors
|
||||
.firstAvailable(
|
||||
previewWithSameAspectRatio(photoSize),
|
||||
previewSizeSelector
|
||||
)
|
||||
.select(capabilities.supportedPreviewSizes())
|
||||
private Parameters flashModeParameters(Capabilities capabilities) {
|
||||
return ParametersFactory.selectFlashMode(
|
||||
capabilities,
|
||||
flashSelector
|
||||
);
|
||||
}
|
||||
|
||||
private SelectorFunction<Size> previewWithSameAspectRatio(Size photoSize) {
|
||||
return aspectRatio(
|
||||
photoSize.getAspectRatio(),
|
||||
previewSizeSelector
|
||||
private Parameters focusModeParameters(Capabilities capabilities) {
|
||||
return ParametersFactory.selectFocusMode(
|
||||
capabilities,
|
||||
focusModeSelector
|
||||
);
|
||||
}
|
||||
|
||||
private void putPictureSize(Capabilities capabilities, Parameters parameters) {
|
||||
parameters.putValue(
|
||||
Parameters.Type.PICTURE_SIZE,
|
||||
photoSize(capabilities)
|
||||
private Parameters previewSizeParameters(Capabilities capabilities) {
|
||||
return ParametersFactory.selectPreviewSize(
|
||||
capabilities,
|
||||
validPreviewSizeSelector(
|
||||
photoSize(capabilities),
|
||||
previewSizeSelector
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
private Parameters pictureSizeParameters(Capabilities capabilities) {
|
||||
return ParametersFactory.selectPictureSize(
|
||||
capabilities,
|
||||
photoSizeSelector
|
||||
);
|
||||
}
|
||||
|
||||
@@ -90,22 +116,4 @@ public class InitialParametersProvider {
|
||||
);
|
||||
}
|
||||
|
||||
private void putFocusMode(Capabilities capabilities, Parameters parameters) {
|
||||
parameters.putValue(
|
||||
Parameters.Type.FOCUS_MODE,
|
||||
focusModeSelector.select(
|
||||
capabilities.supportedFocusModes()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
private void putFlash(Capabilities capabilities, Parameters parameters) {
|
||||
parameters.putValue(
|
||||
Parameters.Type.FLASH,
|
||||
flashSelector.select(
|
||||
capabilities.supportedFlashModes()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
package io.fotoapparat.parameter.update;
|
||||
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import io.fotoapparat.parameter.Flash;
|
||||
import io.fotoapparat.parameter.FocusMode;
|
||||
import io.fotoapparat.parameter.selector.SelectorFunction;
|
||||
|
||||
/**
|
||||
* Request for updating some of the parameters of the {@link io.fotoapparat.Fotoapparat}.
|
||||
* <p>
|
||||
* Use {@link UpdateRequest#builder()} to create a new instance.
|
||||
* <p>
|
||||
* Fields with {@code null} values are ignored and not updated.
|
||||
*/
|
||||
public class UpdateRequest {
|
||||
|
||||
/**
|
||||
* Selects flash mode from list of available modes.
|
||||
* <p>
|
||||
* {@code null} if no update is required.
|
||||
*/
|
||||
@Nullable
|
||||
public final SelectorFunction<Flash> flashSelector;
|
||||
|
||||
/**
|
||||
* Selects focus mode from list of available modes.
|
||||
* <p>
|
||||
* {@code null} if no update is required.
|
||||
*/
|
||||
@Nullable
|
||||
public final SelectorFunction<FocusMode> focusModeSelector;
|
||||
|
||||
private UpdateRequest(Builder builder) {
|
||||
this.flashSelector = builder.flashSelector;
|
||||
this.focusModeSelector = builder.focusModeSelector;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return builder for {@link UpdateRequest}.
|
||||
*/
|
||||
public static Builder builder() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
/**
|
||||
* Builder for {@link UpdateRequest}.
|
||||
*/
|
||||
public static class Builder {
|
||||
|
||||
SelectorFunction<Flash> flashSelector = null;
|
||||
SelectorFunction<FocusMode> focusModeSelector = null;
|
||||
|
||||
/**
|
||||
* @param selector selects focus mode from list of available modes.
|
||||
*/
|
||||
public Builder focusMode(@Nullable SelectorFunction<FocusMode> selector) {
|
||||
this.focusModeSelector = selector;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param selector selects flash mode from list of available modes.
|
||||
*/
|
||||
public Builder flash(@Nullable SelectorFunction<Flash> selector) {
|
||||
this.flashSelector = selector;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a new instance of {@link UpdateRequest} which uses values from current builder.
|
||||
*/
|
||||
public UpdateRequest build() {
|
||||
return new UpdateRequest(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -7,6 +7,31 @@ import android.support.annotation.NonNull;
|
||||
*/
|
||||
public interface PreviewStream {
|
||||
|
||||
/**
|
||||
* Null-object for {@link PreviewStream}.
|
||||
*/
|
||||
PreviewStream NULL = new PreviewStream() {
|
||||
@Override
|
||||
public void addFrameToBuffer() {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addProcessor(@NonNull FrameProcessor processor) {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeProcessor(@NonNull FrameProcessor processor) {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
// Do nothing
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds new frame to buffer.
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
package io.fotoapparat.result;
|
||||
|
||||
/**
|
||||
* Result of trying to focus the camera.
|
||||
*/
|
||||
public enum FocusResult {
|
||||
|
||||
/**
|
||||
* Camera is focused successfully.
|
||||
*/
|
||||
FOCUSED,
|
||||
|
||||
/**
|
||||
* Camera is unable to focus for some reason.
|
||||
*/
|
||||
UNABLE_TO_FOCUS
|
||||
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
package io.fotoapparat.routine;
|
||||
|
||||
import io.fotoapparat.hardware.CameraDevice;
|
||||
|
||||
/**
|
||||
* Performs auto focus.
|
||||
*/
|
||||
public class AutoFocusRoutine implements Runnable {
|
||||
|
||||
private final CameraDevice cameraDevice;
|
||||
|
||||
public AutoFocusRoutine(CameraDevice cameraDevice) {
|
||||
this.cameraDevice = cameraDevice;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
cameraDevice.autoFocus();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,8 +1,11 @@
|
||||
package io.fotoapparat.routine;
|
||||
|
||||
import io.fotoapparat.error.CameraErrorCallback;
|
||||
import io.fotoapparat.hardware.CameraDevice;
|
||||
import io.fotoapparat.hardware.CameraException;
|
||||
import io.fotoapparat.hardware.orientation.ScreenOrientationProvider;
|
||||
import io.fotoapparat.parameter.LensPosition;
|
||||
import io.fotoapparat.parameter.ScaleType;
|
||||
import io.fotoapparat.parameter.provider.InitialParametersProvider;
|
||||
import io.fotoapparat.parameter.selector.SelectorFunction;
|
||||
import io.fotoapparat.view.CameraRenderer;
|
||||
@@ -12,38 +15,53 @@ import io.fotoapparat.view.CameraRenderer;
|
||||
*/
|
||||
public class StartCameraRoutine implements Runnable {
|
||||
|
||||
private final CameraDevice cameraDevice;
|
||||
private final CameraRenderer cameraRenderer;
|
||||
private final SelectorFunction<LensPosition> lensPositionSelector;
|
||||
private final ScreenOrientationProvider screenOrientationProvider;
|
||||
private final InitialParametersProvider initialParametersProvider;
|
||||
private final CameraDevice cameraDevice;
|
||||
private final CameraRenderer cameraRenderer;
|
||||
private final ScaleType scaleType;
|
||||
private final SelectorFunction<LensPosition> lensPositionSelector;
|
||||
private final ScreenOrientationProvider screenOrientationProvider;
|
||||
private final InitialParametersProvider initialParametersProvider;
|
||||
private final CameraErrorCallback cameraErrorCallback;
|
||||
|
||||
public StartCameraRoutine(CameraDevice cameraDevice,
|
||||
CameraRenderer cameraRenderer,
|
||||
SelectorFunction<LensPosition> lensPositionSelector,
|
||||
ScreenOrientationProvider screenOrientationProvider,
|
||||
InitialParametersProvider initialParametersProvider) {
|
||||
this.cameraDevice = cameraDevice;
|
||||
this.cameraRenderer = cameraRenderer;
|
||||
this.lensPositionSelector = lensPositionSelector;
|
||||
this.screenOrientationProvider = screenOrientationProvider;
|
||||
this.initialParametersProvider = initialParametersProvider;
|
||||
}
|
||||
public StartCameraRoutine(CameraDevice cameraDevice,
|
||||
CameraRenderer cameraRenderer,
|
||||
ScaleType scaleType,
|
||||
SelectorFunction<LensPosition> lensPositionSelector,
|
||||
ScreenOrientationProvider screenOrientationProvider,
|
||||
InitialParametersProvider initialParametersProvider,
|
||||
CameraErrorCallback cameraErrorCallback) {
|
||||
this.cameraDevice = cameraDevice;
|
||||
this.cameraRenderer = cameraRenderer;
|
||||
this.scaleType = scaleType;
|
||||
this.lensPositionSelector = lensPositionSelector;
|
||||
this.screenOrientationProvider = screenOrientationProvider;
|
||||
this.initialParametersProvider = initialParametersProvider;
|
||||
this.cameraErrorCallback = cameraErrorCallback;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
LensPosition lensPosition = lensPositionSelector.select(
|
||||
cameraDevice.getAvailableLensPositions()
|
||||
);
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
tryToStartCamera();
|
||||
} catch (CameraException e) {
|
||||
cameraErrorCallback.onError(e);
|
||||
}
|
||||
}
|
||||
|
||||
cameraDevice.open(lensPosition);
|
||||
cameraDevice.updateParameters(
|
||||
initialParametersProvider.initialParameters()
|
||||
);
|
||||
cameraDevice.setDisplayOrientation(
|
||||
screenOrientationProvider.getScreenRotation()
|
||||
);
|
||||
cameraRenderer.attachCamera(cameraDevice);
|
||||
cameraDevice.startPreview();
|
||||
}
|
||||
private void tryToStartCamera() {
|
||||
LensPosition lensPosition = lensPositionSelector.select(
|
||||
cameraDevice.getAvailableLensPositions()
|
||||
);
|
||||
|
||||
cameraDevice.open(lensPosition);
|
||||
cameraDevice.updateParameters(
|
||||
initialParametersProvider.initialParameters()
|
||||
);
|
||||
cameraDevice.setDisplayOrientation(
|
||||
screenOrientationProvider.getScreenRotation()
|
||||
);
|
||||
cameraRenderer.setScaleType(scaleType);
|
||||
cameraRenderer.attachCamera(cameraDevice);
|
||||
cameraDevice.startPreview();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
package io.fotoapparat.routine;
|
||||
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.FutureTask;
|
||||
|
||||
import io.fotoapparat.hardware.CameraDevice;
|
||||
import io.fotoapparat.lens.FocusResult;
|
||||
import io.fotoapparat.photo.Photo;
|
||||
|
||||
/**
|
||||
* Takes photo and returns result as {@link Photo}.
|
||||
*/
|
||||
class TakePictureTask extends FutureTask<Photo> {
|
||||
|
||||
TakePictureTask(final CameraDevice cameraDevice) {
|
||||
super(new Callable<Photo>() {
|
||||
@Override
|
||||
public Photo call() throws Exception {
|
||||
|
||||
int focusAttempts = 0;
|
||||
FocusResult focusResult = FocusResult.none();
|
||||
|
||||
while (focusAttempts < 3 && !focusResult.succeeded) {
|
||||
focusResult = cameraDevice.autoFocus();
|
||||
focusAttempts++;
|
||||
}
|
||||
|
||||
if (focusResult.needsExposureMeasurement) {
|
||||
cameraDevice.measureExposure();
|
||||
}
|
||||
|
||||
Photo photo = cameraDevice.takePicture();
|
||||
|
||||
cameraDevice.startPreview();
|
||||
|
||||
return photo;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package io.fotoapparat.routine.focus;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import io.fotoapparat.hardware.CameraDevice;
|
||||
import io.fotoapparat.result.FocusResult;
|
||||
import io.fotoapparat.result.PendingResult;
|
||||
|
||||
/**
|
||||
* Performs auto focus.
|
||||
*/
|
||||
public class AutoFocusRoutine {
|
||||
|
||||
private final CameraDevice cameraDevice;
|
||||
private final Executor cameraExecutor;
|
||||
|
||||
public AutoFocusRoutine(CameraDevice cameraDevice,
|
||||
Executor cameraExecutor) {
|
||||
this.cameraDevice = cameraDevice;
|
||||
this.cameraExecutor = cameraExecutor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform auto focus asynchronously.
|
||||
*/
|
||||
public PendingResult<FocusResult> autoFocus() {
|
||||
AutoFocusTask autoFocusTask = new AutoFocusTask(cameraDevice);
|
||||
cameraExecutor.execute(autoFocusTask);
|
||||
|
||||
return PendingResult.fromFuture(autoFocusTask);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package io.fotoapparat.routine.focus;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.FutureTask;
|
||||
|
||||
import io.fotoapparat.hardware.CameraDevice;
|
||||
import io.fotoapparat.result.FocusResult;
|
||||
|
||||
/**
|
||||
* Tries to perform auto focus and returns result as {@link FocusResult}.
|
||||
*/
|
||||
public class AutoFocusTask extends FutureTask<FocusResult> {
|
||||
|
||||
public AutoFocusTask(final CameraDevice cameraDevice) {
|
||||
super(new Callable<FocusResult>() {
|
||||
@Override
|
||||
public FocusResult call() throws Exception {
|
||||
return performFocus(cameraDevice);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private static FocusResult performFocus(CameraDevice cameraDevice) {
|
||||
return cameraDevice.autoFocus().succeeded
|
||||
? FocusResult.FOCUSED
|
||||
: FocusResult.UNABLE_TO_FOCUS;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package io.fotoapparat.routine.parameter;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import io.fotoapparat.hardware.CameraDevice;
|
||||
import io.fotoapparat.hardware.Capabilities;
|
||||
import io.fotoapparat.parameter.Parameters;
|
||||
import io.fotoapparat.parameter.factory.ParametersFactory;
|
||||
import io.fotoapparat.parameter.selector.SelectorFunction;
|
||||
import io.fotoapparat.parameter.selector.Selectors;
|
||||
import io.fotoapparat.parameter.update.UpdateRequest;
|
||||
|
||||
import static io.fotoapparat.parameter.Parameters.combineParameters;
|
||||
import static java.util.Arrays.asList;
|
||||
|
||||
/**
|
||||
* Updates {@link CameraDevice} parameters.
|
||||
*/
|
||||
public class UpdateParametersRoutine {
|
||||
|
||||
private final CameraDevice cameraDevice;
|
||||
|
||||
public UpdateParametersRoutine(CameraDevice cameraDevice) {
|
||||
this.cameraDevice = cameraDevice;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates {@link CameraDevice} parameters.
|
||||
*/
|
||||
public void updateParameters(@NonNull UpdateRequest request) {
|
||||
Capabilities capabilities = cameraDevice.getCapabilities();
|
||||
|
||||
cameraDevice.updateParameters(
|
||||
combineParameters(asList(
|
||||
flashModeParameters(request, capabilities),
|
||||
focusModeParameters(request, capabilities)
|
||||
))
|
||||
);
|
||||
}
|
||||
|
||||
private Parameters focusModeParameters(@NonNull UpdateRequest request, Capabilities capabilities) {
|
||||
return ParametersFactory.selectFocusMode(
|
||||
capabilities,
|
||||
optional(request.focusModeSelector)
|
||||
);
|
||||
}
|
||||
|
||||
private Parameters flashModeParameters(@NonNull UpdateRequest request, Capabilities capabilities) {
|
||||
return ParametersFactory.selectFlashMode(
|
||||
capabilities,
|
||||
optional(request.flashSelector)
|
||||
);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private <T> SelectorFunction<T> optional(@Nullable SelectorFunction<T> selector) {
|
||||
return selector != null
|
||||
? selector
|
||||
: Selectors.<T>nothing();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package io.fotoapparat.routine;
|
||||
package io.fotoapparat.routine.picture;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
package io.fotoapparat.routine.picture;
|
||||
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.FutureTask;
|
||||
|
||||
import io.fotoapparat.hardware.CameraDevice;
|
||||
import io.fotoapparat.hardware.CameraException;
|
||||
import io.fotoapparat.lens.FocusResult;
|
||||
import io.fotoapparat.photo.Photo;
|
||||
|
||||
/**
|
||||
* Takes photo and returns result as {@link Photo}.
|
||||
*/
|
||||
class TakePictureTask extends FutureTask<Photo> {
|
||||
|
||||
private static final int MAX_FOCUS_ATTEMPTS = 3;
|
||||
|
||||
TakePictureTask(final CameraDevice cameraDevice) {
|
||||
super(new Callable<Photo>() {
|
||||
@Override
|
||||
public Photo call() throws Exception {
|
||||
adjustCameraForBestShot(cameraDevice);
|
||||
|
||||
Photo photo = cameraDevice.takePicture();
|
||||
|
||||
startPreviewSafe(cameraDevice);
|
||||
|
||||
return photo;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static void adjustCameraForBestShot(CameraDevice cameraDevice) {
|
||||
FocusResult focusResult = autoFocus(cameraDevice);
|
||||
|
||||
if (focusResult.needsExposureMeasurement) {
|
||||
cameraDevice.measureExposure();
|
||||
}
|
||||
}
|
||||
|
||||
private static FocusResult autoFocus(CameraDevice cameraDevice) {
|
||||
int focusAttempts = 0;
|
||||
FocusResult focusResult = FocusResult.none();
|
||||
|
||||
while (focusAttempts < MAX_FOCUS_ATTEMPTS && !focusResult.succeeded) {
|
||||
focusResult = cameraDevice.autoFocus();
|
||||
focusAttempts++;
|
||||
}
|
||||
|
||||
return focusResult;
|
||||
}
|
||||
|
||||
private static void startPreviewSafe(CameraDevice cameraDevice) {
|
||||
try {
|
||||
cameraDevice.startPreview();
|
||||
} catch (CameraException e) {
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package io.fotoapparat.routine.zoom;
|
||||
|
||||
import android.support.annotation.FloatRange;
|
||||
|
||||
import io.fotoapparat.hardware.CameraDevice;
|
||||
|
||||
/**
|
||||
* Updates zoom level of the camera. If zoom is not supported - does nothing.
|
||||
*/
|
||||
public class UpdateZoomLevelRoutine {
|
||||
|
||||
private final CameraDevice cameraDevice;
|
||||
|
||||
public UpdateZoomLevelRoutine(CameraDevice cameraDevice) {
|
||||
this.cameraDevice = cameraDevice;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates zoom level of the camera. If zoom is not supported - does nothing.
|
||||
*
|
||||
* @param zoomLevel zoom level of the camera. Value between 0 and 1.
|
||||
*/
|
||||
public void updateZoomLevel(@FloatRange(from = 0f, to = 1f) float zoomLevel) {
|
||||
ensureInBounds(zoomLevel);
|
||||
|
||||
if (cameraDevice.getCapabilities().isZoomSupported()) {
|
||||
cameraDevice.setZoom(zoomLevel);
|
||||
}
|
||||
}
|
||||
|
||||
private void ensureInBounds(float zoomLevel) {
|
||||
if (zoomLevel < 0f || zoomLevel > 1f) {
|
||||
throw new LevelOutOfRangeException(zoomLevel);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Thrown when zoom level is outside of [0..1] range.
|
||||
*/
|
||||
static class LevelOutOfRangeException extends RuntimeException {
|
||||
|
||||
public LevelOutOfRangeException(float zoomLevel) {
|
||||
super(zoomLevel + " is out of range [0..1]");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,12 +1,19 @@
|
||||
package io.fotoapparat.view;
|
||||
|
||||
import io.fotoapparat.hardware.CameraDevice;
|
||||
import io.fotoapparat.parameter.ScaleType;
|
||||
|
||||
/**
|
||||
* Renders the stream from {@link io.fotoapparat.Fotoapparat}.
|
||||
*/
|
||||
public interface CameraRenderer {
|
||||
|
||||
/**
|
||||
* Sets the scale type of the preview to the renderer. This method will be called from camera
|
||||
* thread, so it is safe to perform blocking operations here.
|
||||
*/
|
||||
void setScaleType(ScaleType scaleType);
|
||||
|
||||
/**
|
||||
* Attaches renderer to camera, so that it will display the preview when camera is started. This
|
||||
* method will be called from camera thread, so it is safe to perform blocking operations here.
|
||||
|
||||
@@ -11,6 +11,7 @@ import android.util.AttributeSet;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import io.fotoapparat.hardware.CameraDevice;
|
||||
import io.fotoapparat.parameter.ScaleType;
|
||||
|
||||
/**
|
||||
* Displays stream from camera.
|
||||
@@ -55,6 +56,11 @@ public class CameraView extends FrameLayout implements CameraRenderer {
|
||||
addView(rendererView);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setScaleType(ScaleType scaleType) {
|
||||
rendererView.setScaleType(scaleType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void attachCamera(CameraDevice camera) {
|
||||
rendererView.attachCamera(camera);
|
||||
|
||||
@@ -16,6 +16,7 @@ import java.util.concurrent.CountDownLatch;
|
||||
|
||||
import io.fotoapparat.hardware.CameraDevice;
|
||||
import io.fotoapparat.parameter.RendererParameters;
|
||||
import io.fotoapparat.parameter.ScaleType;
|
||||
import io.fotoapparat.parameter.Size;
|
||||
|
||||
/**
|
||||
@@ -29,6 +30,7 @@ class TextureRendererView extends FrameLayout implements CameraRenderer {
|
||||
private TextureView textureView;
|
||||
|
||||
private Size previewSize = null;
|
||||
private ScaleType scaleType;
|
||||
|
||||
public TextureRendererView(@NonNull Context context) {
|
||||
super(context);
|
||||
@@ -75,14 +77,30 @@ class TextureRendererView extends FrameLayout implements CameraRenderer {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void attachCamera(CameraDevice camera) {
|
||||
awaitSurfaceTexture();
|
||||
updateLayout(camera);
|
||||
protected void onDetachedFromWindow() {
|
||||
super.onDetachedFromWindow();
|
||||
|
||||
camera.setDisplaySurface(textureView);
|
||||
textureLatch.countDown();
|
||||
}
|
||||
|
||||
private void updateLayout(CameraDevice camera) {
|
||||
@Override
|
||||
public void setScaleType(ScaleType scaleType) {
|
||||
this.scaleType = scaleType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void attachCamera(CameraDevice camera) {
|
||||
try {
|
||||
awaitSurfaceTexture();
|
||||
updateLayout(camera);
|
||||
|
||||
camera.setDisplaySurface(textureView);
|
||||
} catch (InterruptedException e) {
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
|
||||
private void updateLayout(final CameraDevice camera) {
|
||||
final Size previewSize = toPreviewSize(
|
||||
camera.getRendererParameters()
|
||||
);
|
||||
@@ -103,25 +121,53 @@ class TextureRendererView extends FrameLayout implements CameraRenderer {
|
||||
: rendererParameters.previewSize.flip();
|
||||
}
|
||||
|
||||
private void awaitSurfaceTexture() {
|
||||
private void awaitSurfaceTexture() throws InterruptedException {
|
||||
if (surfaceTexture != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
textureLatch.await();
|
||||
} catch (InterruptedException e) {
|
||||
// Do nothing
|
||||
textureLatch.await();
|
||||
|
||||
if (surfaceTexture == null) {
|
||||
throw new InterruptedException("No surface became available.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
|
||||
if (previewSize == null) {
|
||||
if (previewSize == null || scaleType == null) {
|
||||
super.onLayout(changed, left, top, right, bottom);
|
||||
return;
|
||||
}
|
||||
|
||||
if (scaleType == ScaleType.CENTER_INSIDE) {
|
||||
centerInside(previewSize);
|
||||
} else {
|
||||
centerCrop(previewSize);
|
||||
}
|
||||
}
|
||||
|
||||
private void centerInside(Size previewSize) {
|
||||
final float scale = Math.min(
|
||||
getMeasuredWidth() / (float) previewSize.width,
|
||||
getMeasuredHeight() / (float) previewSize.height
|
||||
);
|
||||
|
||||
final int width = (int) (previewSize.width * scale);
|
||||
final int height = (int) (previewSize.height * scale);
|
||||
|
||||
final int extraX = Math.max(0, getMeasuredWidth() - width);
|
||||
final int extraY = Math.max(0, getMeasuredHeight() - height);
|
||||
|
||||
getChildAt(0).layout(
|
||||
extraX / 2,
|
||||
extraY / 2,
|
||||
width + (extraX / 2),
|
||||
height + (extraY / 2)
|
||||
);
|
||||
}
|
||||
|
||||
private void centerCrop(Size previewSize) {
|
||||
final float scale = Math.max(
|
||||
getMeasuredWidth() / (float) previewSize.width,
|
||||
getMeasuredHeight() / (float) previewSize.height
|
||||
@@ -157,7 +203,6 @@ class TextureRendererView extends FrameLayout implements CameraRenderer {
|
||||
@Override
|
||||
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
|
||||
// Do nothing
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -10,11 +10,13 @@ import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import io.fotoapparat.error.CameraErrorCallback;
|
||||
import io.fotoapparat.hardware.provider.CameraProvider;
|
||||
import io.fotoapparat.log.Logger;
|
||||
import io.fotoapparat.parameter.Flash;
|
||||
import io.fotoapparat.parameter.FocusMode;
|
||||
import io.fotoapparat.parameter.LensPosition;
|
||||
import io.fotoapparat.parameter.ScaleType;
|
||||
import io.fotoapparat.parameter.Size;
|
||||
import io.fotoapparat.parameter.selector.SelectorFunction;
|
||||
import io.fotoapparat.preview.FrameProcessor;
|
||||
@@ -28,227 +30,274 @@ import static org.mockito.BDDMockito.given;
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class FotoapparatBuilderTest {
|
||||
|
||||
@Mock
|
||||
Context context;
|
||||
@Mock
|
||||
CameraProvider cameraProvider;
|
||||
@Mock
|
||||
CameraRenderer cameraRenderer;
|
||||
@Mock
|
||||
Context context;
|
||||
@Mock
|
||||
CameraProvider cameraProvider;
|
||||
@Mock
|
||||
CameraRenderer cameraRenderer;
|
||||
|
||||
@Mock
|
||||
SelectorFunction<Size> photoSizeSelector;
|
||||
@Mock
|
||||
SelectorFunction<Size> previewSizeSelector;
|
||||
@Mock
|
||||
SelectorFunction<LensPosition> lensPositionSelector;
|
||||
@Mock
|
||||
SelectorFunction<FocusMode> focusModeSelector;
|
||||
@Mock
|
||||
SelectorFunction<Flash> flashSelector;
|
||||
@Mock
|
||||
SelectorFunction<Size> photoSizeSelector;
|
||||
@Mock
|
||||
SelectorFunction<Size> previewSizeSelector;
|
||||
@Mock
|
||||
SelectorFunction<LensPosition> lensPositionSelector;
|
||||
@Mock
|
||||
SelectorFunction<FocusMode> focusModeSelector;
|
||||
@Mock
|
||||
SelectorFunction<Flash> flashSelector;
|
||||
|
||||
@Mock
|
||||
FrameProcessor frameProcessor;
|
||||
@Mock
|
||||
FrameProcessor frameProcessor;
|
||||
|
||||
@Mock
|
||||
Logger logger;
|
||||
@Mock
|
||||
Logger logger;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
given(context.getSystemService(Context.WINDOW_SERVICE))
|
||||
.willReturn(Mockito.mock(WindowManager.class));
|
||||
}
|
||||
@Mock
|
||||
CameraErrorCallback cameraErrorCallback;
|
||||
|
||||
@Test
|
||||
public void onlyMandatoryParameters() throws Exception {
|
||||
// Given
|
||||
FotoapparatBuilder builder = builderWithMandatoryArguments();
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
given(context.getSystemService(Context.WINDOW_SERVICE))
|
||||
.willReturn(Mockito.mock(WindowManager.class));
|
||||
}
|
||||
|
||||
// When
|
||||
Fotoapparat result = builder.build();
|
||||
@Test
|
||||
public void onlyMandatoryParameters() throws Exception {
|
||||
// Given
|
||||
FotoapparatBuilder builder = builderWithMandatoryArguments();
|
||||
|
||||
// Then
|
||||
assertNotNull(result);
|
||||
}
|
||||
// When
|
||||
Fotoapparat result = builder.build();
|
||||
|
||||
@Test
|
||||
public void cameraProvider_HasDefault() throws Exception {
|
||||
// When
|
||||
FotoapparatBuilder builder = builderWithMandatoryArguments();
|
||||
// Then
|
||||
assertNotNull(result);
|
||||
}
|
||||
|
||||
// Then
|
||||
assertNotNull(builder.cameraProvider);
|
||||
}
|
||||
@Test
|
||||
public void cameraProvider_HasDefault() throws Exception {
|
||||
// When
|
||||
FotoapparatBuilder builder = builderWithMandatoryArguments();
|
||||
|
||||
@Test
|
||||
public void cameraProvider_IsConfigurable() throws Exception {
|
||||
// When
|
||||
FotoapparatBuilder builder = builderWithMandatoryArguments()
|
||||
.cameraProvider(cameraProvider);
|
||||
// Then
|
||||
assertNotNull(builder.cameraProvider);
|
||||
}
|
||||
|
||||
// Then
|
||||
assertEquals(
|
||||
cameraProvider,
|
||||
builder.cameraProvider
|
||||
);
|
||||
}
|
||||
@Test
|
||||
public void cameraProvider_IsConfigurable() throws Exception {
|
||||
// When
|
||||
FotoapparatBuilder builder = builderWithMandatoryArguments()
|
||||
.cameraProvider(cameraProvider);
|
||||
|
||||
@Test
|
||||
public void logger_HasDefault() throws Exception {
|
||||
// When
|
||||
FotoapparatBuilder builder = builderWithMandatoryArguments();
|
||||
// Then
|
||||
assertEquals(
|
||||
cameraProvider,
|
||||
builder.cameraProvider
|
||||
);
|
||||
}
|
||||
|
||||
// Then
|
||||
assertNotNull(builder.logger);
|
||||
}
|
||||
@Test
|
||||
public void logger_HasDefault() throws Exception {
|
||||
// When
|
||||
FotoapparatBuilder builder = builderWithMandatoryArguments();
|
||||
|
||||
@Test
|
||||
public void logger_IsConfigurable() throws Exception {
|
||||
// When
|
||||
FotoapparatBuilder builder = builderWithMandatoryArguments()
|
||||
.logger(logger);
|
||||
// Then
|
||||
assertNotNull(builder.logger);
|
||||
}
|
||||
|
||||
// Then
|
||||
assertEquals(
|
||||
logger,
|
||||
builder.logger
|
||||
);
|
||||
}
|
||||
@Test
|
||||
public void logger_IsConfigurable() throws Exception {
|
||||
// When
|
||||
FotoapparatBuilder builder = builderWithMandatoryArguments()
|
||||
.logger(logger);
|
||||
|
||||
@Test
|
||||
public void focusMode_HasDefault() throws Exception {
|
||||
// When
|
||||
FotoapparatBuilder builder = builderWithMandatoryArguments();
|
||||
// Then
|
||||
assertEquals(
|
||||
logger,
|
||||
builder.logger
|
||||
);
|
||||
}
|
||||
|
||||
// Then
|
||||
assertNotNull(builder.focusModeSelector);
|
||||
}
|
||||
@Test
|
||||
public void focusMode_HasDefault() throws Exception {
|
||||
// When
|
||||
FotoapparatBuilder builder = builderWithMandatoryArguments();
|
||||
|
||||
@Test
|
||||
public void focusMode_IsConfigurable() throws Exception {
|
||||
// When
|
||||
FotoapparatBuilder builder = builderWithMandatoryArguments()
|
||||
.focusMode(focusModeSelector);
|
||||
// Then
|
||||
assertNotNull(builder.focusModeSelector);
|
||||
}
|
||||
|
||||
// Then
|
||||
assertEquals(
|
||||
focusModeSelector,
|
||||
builder.focusModeSelector
|
||||
);
|
||||
}
|
||||
@Test
|
||||
public void focusMode_IsConfigurable() throws Exception {
|
||||
// When
|
||||
FotoapparatBuilder builder = builderWithMandatoryArguments()
|
||||
.focusMode(focusModeSelector);
|
||||
|
||||
@Test
|
||||
public void flashMode_IsConfigurable() throws Exception {
|
||||
// When
|
||||
FotoapparatBuilder builder = builderWithMandatoryArguments()
|
||||
.flash(flashSelector);
|
||||
// Then
|
||||
assertEquals(
|
||||
focusModeSelector,
|
||||
builder.focusModeSelector
|
||||
);
|
||||
}
|
||||
|
||||
// Then
|
||||
assertEquals(
|
||||
flashSelector,
|
||||
builder.flashSelector
|
||||
);
|
||||
}
|
||||
@Test
|
||||
public void flashMode_IsConfigurable() throws Exception {
|
||||
// When
|
||||
FotoapparatBuilder builder = builderWithMandatoryArguments()
|
||||
.flash(flashSelector);
|
||||
|
||||
@Test
|
||||
public void frameProcessor_NullByDefault() throws Exception {
|
||||
// When
|
||||
FotoapparatBuilder builder = builderWithMandatoryArguments();
|
||||
// Then
|
||||
assertEquals(
|
||||
flashSelector,
|
||||
builder.flashSelector
|
||||
);
|
||||
}
|
||||
|
||||
// Then
|
||||
assertNull(builder.frameProcessor);
|
||||
}
|
||||
@Test
|
||||
public void frameProcessor_NullByDefault() throws Exception {
|
||||
// When
|
||||
FotoapparatBuilder builder = builderWithMandatoryArguments();
|
||||
|
||||
@Test
|
||||
public void frameProcessor_IsConfigurable() throws Exception {
|
||||
// When
|
||||
FotoapparatBuilder builder = builderWithMandatoryArguments()
|
||||
.frameProcessor(frameProcessor);
|
||||
// Then
|
||||
assertNull(builder.frameProcessor);
|
||||
}
|
||||
|
||||
// Then
|
||||
assertEquals(
|
||||
frameProcessor,
|
||||
builder.frameProcessor
|
||||
);
|
||||
}
|
||||
@Test
|
||||
public void frameProcessor_IsConfigurable() throws Exception {
|
||||
// When
|
||||
FotoapparatBuilder builder = builderWithMandatoryArguments()
|
||||
.frameProcessor(frameProcessor);
|
||||
|
||||
@Test
|
||||
public void photoSize_IsConfigurable() throws Exception {
|
||||
// When
|
||||
FotoapparatBuilder builder = builderWithMandatoryArguments()
|
||||
.photoSize(photoSizeSelector);
|
||||
// Then
|
||||
assertEquals(
|
||||
frameProcessor,
|
||||
builder.frameProcessor
|
||||
);
|
||||
}
|
||||
|
||||
// Then
|
||||
assertEquals(
|
||||
photoSizeSelector,
|
||||
builder.photoSizeSelector
|
||||
);
|
||||
}
|
||||
@Test
|
||||
public void photoSize_IsConfigurable() throws Exception {
|
||||
// When
|
||||
FotoapparatBuilder builder = builderWithMandatoryArguments()
|
||||
.photoSize(photoSizeSelector);
|
||||
|
||||
@Test
|
||||
public void previewSize_HasDefault() throws Exception {
|
||||
// When
|
||||
FotoapparatBuilder builder = builderWithMandatoryArguments();
|
||||
// Then
|
||||
assertEquals(
|
||||
photoSizeSelector,
|
||||
builder.photoSizeSelector
|
||||
);
|
||||
}
|
||||
|
||||
// Then
|
||||
assertNotNull(builder.previewSizeSelector);
|
||||
}
|
||||
@Test
|
||||
public void previewSize_HasDefault() throws Exception {
|
||||
// When
|
||||
FotoapparatBuilder builder = builderWithMandatoryArguments();
|
||||
|
||||
@Test
|
||||
public void previewSize_IsConfigurable() throws Exception {
|
||||
// When
|
||||
FotoapparatBuilder builder = builderWithMandatoryArguments()
|
||||
.previewSize(previewSizeSelector);
|
||||
// Then
|
||||
assertNotNull(builder.previewSizeSelector);
|
||||
}
|
||||
|
||||
// Then
|
||||
assertEquals(
|
||||
previewSizeSelector,
|
||||
builder.previewSizeSelector
|
||||
);
|
||||
}
|
||||
@Test
|
||||
public void previewSize_IsConfigurable() throws Exception {
|
||||
// When
|
||||
FotoapparatBuilder builder = builderWithMandatoryArguments()
|
||||
.previewSize(previewSizeSelector);
|
||||
|
||||
// Then
|
||||
assertEquals(
|
||||
previewSizeSelector,
|
||||
builder.previewSizeSelector
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void previewStyle_HasDefault() throws Exception {
|
||||
// When
|
||||
FotoapparatBuilder builder = builderWithMandatoryArguments();
|
||||
|
||||
// Then
|
||||
assertNotNull(builder.scaleType);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void previewStyle_IsConfigurable() throws Exception {
|
||||
// When
|
||||
FotoapparatBuilder builder = builderWithMandatoryArguments()
|
||||
.previewScaleType(ScaleType.CENTER_INSIDE);
|
||||
|
||||
// Then
|
||||
assertEquals(
|
||||
ScaleType.CENTER_INSIDE,
|
||||
builder.scaleType
|
||||
);
|
||||
}
|
||||
@Test
|
||||
public void cameraErrorCallback_HasDefault() throws Exception {
|
||||
// When
|
||||
FotoapparatBuilder builder = builderWithMandatoryArguments();
|
||||
|
||||
// Then
|
||||
assertNotNull(builder.cameraErrorCallback);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cameraErrorCallback_IsConfigurable() throws Exception {
|
||||
// When
|
||||
FotoapparatBuilder builder = builderWithMandatoryArguments()
|
||||
.cameraErrorCallback(cameraErrorCallback);
|
||||
|
||||
// Then
|
||||
assertEquals(
|
||||
cameraErrorCallback,
|
||||
builder.cameraErrorCallback
|
||||
);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
public void rendererIsMandatory() throws Exception {
|
||||
// Given
|
||||
FotoapparatBuilder builder = builderWithMandatoryArguments()
|
||||
.into(null);
|
||||
|
||||
// When
|
||||
builder.build();
|
||||
|
||||
// Then
|
||||
// Expect exception
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void rendererIsMandatory() throws Exception {
|
||||
// Given
|
||||
FotoapparatBuilder builder = builderWithMandatoryArguments()
|
||||
.into(null);
|
||||
|
||||
// When
|
||||
builder.build();
|
||||
|
||||
// Then
|
||||
// Expect exception
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void lensPositionIsMandatory() throws Exception {
|
||||
@SuppressWarnings("ConstantConditions")public void lensPositionIsMandatory() throws Exception {
|
||||
// Given
|
||||
FotoapparatBuilder builder = builderWithMandatoryArguments()
|
||||
.lensPosition(null);
|
||||
|
||||
// When
|
||||
builder.build();
|
||||
// When
|
||||
builder.build();
|
||||
|
||||
// Then
|
||||
// Expect exception
|
||||
}
|
||||
// Then
|
||||
// Expect exception
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void photoSizeIsMandatory() throws Exception {
|
||||
@SuppressWarnings("ConstantConditions")public void photoSizeIsMandatory() throws Exception {
|
||||
// Given
|
||||
FotoapparatBuilder builder = builderWithMandatoryArguments()
|
||||
.photoSize(null);
|
||||
|
||||
// When
|
||||
builder.build();
|
||||
// When
|
||||
builder.build();
|
||||
|
||||
// Then
|
||||
// Expect exception
|
||||
}
|
||||
// Then
|
||||
// Expect exception
|
||||
}
|
||||
|
||||
private FotoapparatBuilder builderWithMandatoryArguments() {
|
||||
return new FotoapparatBuilder(context)
|
||||
.lensPosition(lensPositionSelector)
|
||||
.photoSize(photoSizeSelector)
|
||||
.into(cameraRenderer);
|
||||
}
|
||||
private FotoapparatBuilder builderWithMandatoryArguments() {
|
||||
return new FotoapparatBuilder(context)
|
||||
.lensPosition(lensPositionSelector)
|
||||
.photoSize(photoSizeSelector)
|
||||
.into(cameraRenderer);
|
||||
}
|
||||
}
|
||||
@@ -9,16 +9,21 @@ import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import io.fotoapparat.hardware.Capabilities;
|
||||
import io.fotoapparat.parameter.provider.CapabilitiesProvider;
|
||||
import io.fotoapparat.parameter.update.UpdateRequest;
|
||||
import io.fotoapparat.photo.Photo;
|
||||
import io.fotoapparat.result.CapabilitiesResult;
|
||||
import io.fotoapparat.result.FocusResult;
|
||||
import io.fotoapparat.result.PendingResult;
|
||||
import io.fotoapparat.result.PhotoResult;
|
||||
import io.fotoapparat.routine.AutoFocusRoutine;
|
||||
import io.fotoapparat.routine.CheckAvailabilityRoutine;
|
||||
import io.fotoapparat.routine.ConfigurePreviewStreamRoutine;
|
||||
import io.fotoapparat.routine.StartCameraRoutine;
|
||||
import io.fotoapparat.routine.StopCameraRoutine;
|
||||
import io.fotoapparat.routine.TakePictureRoutine;
|
||||
import io.fotoapparat.routine.UpdateOrientationRoutine;
|
||||
import io.fotoapparat.routine.focus.AutoFocusRoutine;
|
||||
import io.fotoapparat.routine.parameter.UpdateParametersRoutine;
|
||||
import io.fotoapparat.routine.picture.TakePictureRoutine;
|
||||
import io.fotoapparat.routine.zoom.UpdateZoomLevelRoutine;
|
||||
import io.fotoapparat.test.ImmediateExecutor;
|
||||
|
||||
import static io.fotoapparat.test.TestUtils.immediateFuture;
|
||||
@@ -37,6 +42,13 @@ public class FotoapparatTest {
|
||||
Photo.empty()
|
||||
)
|
||||
);
|
||||
|
||||
static final PendingResult<FocusResult> FOCUS_RESULT = PendingResult.fromFuture(
|
||||
immediateFuture(
|
||||
FocusResult.FOCUSED
|
||||
)
|
||||
);
|
||||
|
||||
static final CapabilitiesResult CAPABILITIES_RESULT = CapabilitiesResult.fromFuture(
|
||||
immediateFuture(
|
||||
Capabilities.empty()
|
||||
@@ -59,6 +71,10 @@ public class FotoapparatTest {
|
||||
AutoFocusRoutine autoFocusRoutine;
|
||||
@Mock
|
||||
CheckAvailabilityRoutine checkAvailabilityRoutine;
|
||||
@Mock
|
||||
UpdateParametersRoutine updateParametersRoutine;
|
||||
@Mock
|
||||
UpdateZoomLevelRoutine updateZoomLevelRoutine;
|
||||
|
||||
Fotoapparat testee;
|
||||
|
||||
@@ -73,6 +89,8 @@ public class FotoapparatTest {
|
||||
takePictureRoutine,
|
||||
autoFocusRoutine,
|
||||
checkAvailabilityRoutine,
|
||||
updateParametersRoutine,
|
||||
updateZoomLevelRoutine,
|
||||
new ImmediateExecutor()
|
||||
);
|
||||
}
|
||||
@@ -196,7 +214,7 @@ public class FotoapparatTest {
|
||||
testee.autoFocus();
|
||||
|
||||
// Then
|
||||
verify(autoFocusRoutine).run();
|
||||
verify(autoFocusRoutine).autoFocus();
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
@@ -208,6 +226,34 @@ public class FotoapparatTest {
|
||||
// Expect exception
|
||||
}
|
||||
|
||||
@Test
|
||||
public void focus() throws Exception {
|
||||
// Given
|
||||
given(autoFocusRoutine.autoFocus())
|
||||
.willReturn(FOCUS_RESULT);
|
||||
|
||||
testee.start();
|
||||
|
||||
// When
|
||||
PendingResult<FocusResult> result = testee.focus();
|
||||
|
||||
// Then
|
||||
assertEquals(
|
||||
FOCUS_RESULT,
|
||||
result
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void focus_NotStartedYet() throws Exception {
|
||||
// When
|
||||
testee.focus();
|
||||
|
||||
// Then
|
||||
// Expect exception
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void ensureNonNullContext() throws Exception {
|
||||
// Given
|
||||
@@ -245,4 +291,53 @@ public class FotoapparatTest {
|
||||
assertFalse(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateParameters() throws Exception {
|
||||
// Given
|
||||
UpdateRequest updateRequest = UpdateRequest.builder()
|
||||
.build();
|
||||
|
||||
testee.start();
|
||||
|
||||
// When
|
||||
testee.updateParameters(updateRequest);
|
||||
|
||||
// Then
|
||||
verify(updateParametersRoutine).updateParameters(updateRequest);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void updateParameters_NotStartedYet() throws Exception {
|
||||
// Given
|
||||
UpdateRequest updateRequest = UpdateRequest.builder()
|
||||
.build();
|
||||
|
||||
// When
|
||||
testee.updateParameters(updateRequest);
|
||||
|
||||
// Then
|
||||
// Expect exception
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setZoom() throws Exception {
|
||||
// Given
|
||||
testee.start();
|
||||
|
||||
// When
|
||||
testee.setZoom(0.5f);
|
||||
|
||||
// Then
|
||||
verify(updateZoomLevelRoutine).updateZoomLevel(0.5f);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void setZoom_NotStartedYet() throws Exception {
|
||||
// When
|
||||
testee.setZoom(1f);
|
||||
|
||||
// Then
|
||||
// Expect exception
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
package io.fotoapparat.hardware;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
@@ -9,6 +11,8 @@ import io.fotoapparat.parameter.FocusMode;
|
||||
import io.fotoapparat.parameter.Parameters;
|
||||
import io.fotoapparat.parameter.Size;
|
||||
|
||||
import static io.fotoapparat.parameter.Parameters.Type.FOCUS_MODE;
|
||||
import static io.fotoapparat.parameter.Parameters.Type.PICTURE_SIZE;
|
||||
import static io.fotoapparat.test.TestUtils.asSet;
|
||||
import static java.util.Collections.emptySet;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
@@ -110,4 +114,64 @@ public class ParametersTest {
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void putAll() throws Exception {
|
||||
// Given
|
||||
Parameters input = new Parameters();
|
||||
input.putValue(Parameters.Type.FOCUS_MODE, FocusMode.AUTO);
|
||||
input.putValue(Parameters.Type.PICTURE_SIZE, new Size(100, 100));
|
||||
|
||||
// When
|
||||
testee.putAll(input);
|
||||
|
||||
// Then
|
||||
assertEquals(
|
||||
input,
|
||||
testee
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void putAll_KeepOldValues() throws Exception {
|
||||
// Given
|
||||
Parameters input = new Parameters();
|
||||
input.putValue(Parameters.Type.FOCUS_MODE, FocusMode.AUTO);
|
||||
|
||||
testee.putValue(Parameters.Type.PICTURE_SIZE, new Size(100, 100));
|
||||
|
||||
// When
|
||||
testee.putAll(input);
|
||||
|
||||
// Then
|
||||
Parameters expected = new Parameters();
|
||||
expected.putValue(Parameters.Type.FOCUS_MODE, FocusMode.AUTO);
|
||||
expected.putValue(Parameters.Type.PICTURE_SIZE, new Size(100, 100));
|
||||
|
||||
assertEquals(
|
||||
expected,
|
||||
testee
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void combineParameters() throws Exception {
|
||||
// Given
|
||||
Parameters parametersA = new Parameters().putValue(PICTURE_SIZE, new Size(100, 100));
|
||||
Parameters parametersB = new Parameters().putValue(FOCUS_MODE, FocusMode.AUTO);
|
||||
|
||||
// When
|
||||
Parameters result = Parameters.combineParameters(asSet(
|
||||
parametersA,
|
||||
parametersB
|
||||
));
|
||||
|
||||
// Then
|
||||
Assert.assertEquals(
|
||||
new Parameters()
|
||||
.putValue(PICTURE_SIZE, new Size(100, 100))
|
||||
.putValue(FOCUS_MODE, FocusMode.AUTO),
|
||||
result
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -21,6 +21,7 @@ import static io.fotoapparat.test.TestUtils.asSet;
|
||||
import static java.util.Arrays.asList;
|
||||
import static java.util.Collections.singleton;
|
||||
import static junit.framework.Assert.assertEquals;
|
||||
import static junit.framework.Assert.assertTrue;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
@@ -44,6 +45,8 @@ public class CapabilitiesFactoryTest {
|
||||
.willReturn(Collections.<Camera.Size>emptyList());
|
||||
given(parameters.getSupportedPreviewSizes())
|
||||
.willReturn(Collections.<Camera.Size>emptyList());
|
||||
given(parameters.isZoomSupported())
|
||||
.willReturn(false);
|
||||
|
||||
testee = new CapabilitiesFactory();
|
||||
}
|
||||
@@ -181,6 +184,19 @@ public class CapabilitiesFactoryTest {
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void zoomSupported() throws Exception {
|
||||
// Given
|
||||
given(parameters.isZoomSupported())
|
||||
.willReturn(true);
|
||||
|
||||
// When
|
||||
Capabilities capabilities = testee.fromParameters(parameters);
|
||||
|
||||
// Then
|
||||
assertTrue(capabilities.isZoomSupported());
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private Camera.Size makeSize(int width, int height) {
|
||||
Camera.Size size = camera.new Size(0, 0);
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
package io.fotoapparat.hardware.v1.parameters;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import io.fotoapparat.hardware.operators.ParametersOperator;
|
||||
import io.fotoapparat.parameter.Parameters;
|
||||
import io.fotoapparat.parameter.Size;
|
||||
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class SplitParametersOperatorTest {
|
||||
|
||||
static final Size PICTURE_SIZE = new Size(100, 100);
|
||||
static final Size PREVIEW_SIZE = new Size(50, 50);
|
||||
|
||||
@Mock
|
||||
ParametersOperator wrapped;
|
||||
|
||||
@InjectMocks
|
||||
SplitParametersOperator testee;
|
||||
|
||||
@Test
|
||||
public void updateParameters() throws Exception {
|
||||
// Given
|
||||
Parameters parameters = new Parameters();
|
||||
parameters.putValue(Parameters.Type.PICTURE_SIZE, PICTURE_SIZE);
|
||||
parameters.putValue(Parameters.Type.PREVIEW_SIZE, PREVIEW_SIZE);
|
||||
|
||||
// When
|
||||
testee.updateParameters(parameters);
|
||||
|
||||
// Then
|
||||
verify(wrapped).updateParameters(
|
||||
parametersWithJust(Parameters.Type.PICTURE_SIZE, PICTURE_SIZE)
|
||||
);
|
||||
verify(wrapped).updateParameters(
|
||||
parametersWithJust(Parameters.Type.PREVIEW_SIZE, PREVIEW_SIZE)
|
||||
);
|
||||
|
||||
verifyNoMoreInteractions(wrapped);
|
||||
}
|
||||
|
||||
private Parameters parametersWithJust(Parameters.Type type, Object value) {
|
||||
Parameters parameters = new Parameters();
|
||||
parameters.putValue(type, value);
|
||||
|
||||
return parameters;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package io.fotoapparat.hardware.v1.parameters;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import io.fotoapparat.hardware.operators.ParametersOperator;
|
||||
import io.fotoapparat.log.Logger;
|
||||
import io.fotoapparat.parameter.Parameters;
|
||||
|
||||
import static org.mockito.Mockito.doThrow;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class SupressExceptionsParametersOperatorTest {
|
||||
|
||||
@Mock
|
||||
ParametersOperator wrapped;
|
||||
@Mock
|
||||
Logger logger;
|
||||
@Mock
|
||||
Parameters parameters;
|
||||
|
||||
@InjectMocks
|
||||
SupressExceptionsParametersOperator testee;
|
||||
|
||||
@Test
|
||||
public void updateParameters() throws Exception {
|
||||
// Given
|
||||
doThrow(new RuntimeException())
|
||||
.when(wrapped)
|
||||
.updateParameters(parameters);
|
||||
|
||||
// When
|
||||
testee.updateParameters(parameters);
|
||||
|
||||
// Then
|
||||
verify(wrapped).updateParameters(parameters);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package io.fotoapparat.hardware.v1.parameters;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import io.fotoapparat.hardware.operators.ParametersOperator;
|
||||
import io.fotoapparat.parameter.Parameters;
|
||||
|
||||
import static org.mockito.Mockito.doThrow;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyZeroInteractions;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class SwitchOnFailureParametersOperatorTest {
|
||||
|
||||
@Mock
|
||||
ParametersOperator first;
|
||||
@Mock
|
||||
ParametersOperator second;
|
||||
@Mock
|
||||
Parameters parameters;
|
||||
|
||||
SwitchOnFailureParametersOperator testee;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
testee = new SwitchOnFailureParametersOperator(
|
||||
first, second
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void firstSucceeds() throws Exception {
|
||||
// When
|
||||
testee.updateParameters(parameters);
|
||||
|
||||
// Then
|
||||
verify(first).updateParameters(parameters);
|
||||
|
||||
verifyZeroInteractions(second);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void firstFails() throws Exception {
|
||||
// Given
|
||||
doThrow(new RuntimeException())
|
||||
.when(first)
|
||||
.updateParameters(parameters);
|
||||
|
||||
// When
|
||||
testee.updateParameters(parameters);
|
||||
|
||||
// Then
|
||||
verify(second).updateParameters(parameters);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -156,7 +156,8 @@ public class Camera2Test {
|
||||
Collections.<Size>emptySet(),
|
||||
Collections.<Size>emptySet(),
|
||||
singleton(FocusMode.MACRO),
|
||||
Collections.<Flash>emptySet()
|
||||
Collections.<Flash>emptySet(),
|
||||
false
|
||||
);
|
||||
given(capabilitiesOperator.getCapabilities())
|
||||
.willReturn(capabilities);
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
package io.fotoapparat.parameter.factory;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import io.fotoapparat.hardware.Capabilities;
|
||||
import io.fotoapparat.parameter.Flash;
|
||||
import io.fotoapparat.parameter.FocusMode;
|
||||
import io.fotoapparat.parameter.Parameters;
|
||||
import io.fotoapparat.parameter.Size;
|
||||
|
||||
import static io.fotoapparat.util.TestSelectors.select;
|
||||
import static junit.framework.Assert.assertEquals;
|
||||
|
||||
public class ParametersFactoryTest {
|
||||
|
||||
static final Capabilities CAPABILITIES = Capabilities.empty();
|
||||
|
||||
@Test
|
||||
public void selectPictureSize() throws Exception {
|
||||
// Given
|
||||
Size size = new Size(100, 100);
|
||||
|
||||
// When
|
||||
Parameters result = ParametersFactory.selectPictureSize(CAPABILITIES, select(size));
|
||||
|
||||
// Then
|
||||
assertEquals(
|
||||
new Parameters().putValue(Parameters.Type.PICTURE_SIZE, size),
|
||||
result
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void selectPreviewSize() throws Exception {
|
||||
// Given
|
||||
Size size = new Size(100, 100);
|
||||
|
||||
// When
|
||||
Parameters result = ParametersFactory.selectPreviewSize(CAPABILITIES, select(size));
|
||||
|
||||
// Then
|
||||
assertEquals(
|
||||
new Parameters().putValue(Parameters.Type.PREVIEW_SIZE, size),
|
||||
result
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void selectFocusMode() throws Exception {
|
||||
// Given
|
||||
FocusMode focusMode = FocusMode.AUTO;
|
||||
|
||||
// When
|
||||
Parameters result = ParametersFactory.selectFocusMode(CAPABILITIES, select(focusMode));
|
||||
|
||||
// Then
|
||||
assertEquals(
|
||||
new Parameters().putValue(Parameters.Type.FOCUS_MODE, focusMode),
|
||||
result
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void selectFlashMode() throws Exception {
|
||||
// Given
|
||||
Flash flash = Flash.AUTO;
|
||||
|
||||
// When
|
||||
Parameters result = ParametersFactory.selectFlashMode(CAPABILITIES, select(flash));
|
||||
|
||||
// Then
|
||||
assertEquals(
|
||||
new Parameters().putValue(Parameters.Type.FLASH, flash),
|
||||
result
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
package io.fotoapparat.parameter.provider;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
@@ -8,18 +7,19 @@ import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import io.fotoapparat.hardware.CameraDevice;
|
||||
import io.fotoapparat.hardware.Capabilities;
|
||||
import io.fotoapparat.hardware.operators.CapabilitiesOperator;
|
||||
import io.fotoapparat.parameter.Flash;
|
||||
import io.fotoapparat.parameter.FocusMode;
|
||||
import io.fotoapparat.parameter.Parameters;
|
||||
import io.fotoapparat.parameter.Size;
|
||||
import io.fotoapparat.parameter.selector.SelectorFunction;
|
||||
import io.fotoapparat.parameter.selector.SizeSelectors;
|
||||
|
||||
import static io.fotoapparat.parameter.selector.FlashSelectors.torch;
|
||||
import static io.fotoapparat.parameter.selector.FocusModeSelectors.autoFocus;
|
||||
import static io.fotoapparat.test.TestUtils.asSet;
|
||||
import static java.util.Collections.singleton;
|
||||
import static io.fotoapparat.util.TestSelectors.select;
|
||||
import static junit.framework.Assert.assertEquals;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
@@ -30,148 +30,100 @@ public class InitialParametersProviderTest {
|
||||
static final Size PREVIEW_SIZE = new Size(2000, 1500);
|
||||
static final Size PREVIEW_SIZE_WRONG_ASPECT_RATIO = new Size(1000, 1000);
|
||||
|
||||
static final Set<FocusMode> FOCUS_MODES = asSet(FocusMode.FIXED);
|
||||
static final Set<Flash> FLASH = asSet(Flash.AUTO_RED_EYE);
|
||||
|
||||
static final Set<Size> PHOTO_SIZES = asSet(PHOTO_SIZE);
|
||||
static final Set<Size> VALID_PREVIEW_SIZES = asSet(PREVIEW_SIZE);
|
||||
static final Set<Size> ALL_PREVIEW_SIZES = asSet(
|
||||
PREVIEW_SIZE,
|
||||
PREVIEW_SIZE_WRONG_ASPECT_RATIO
|
||||
);
|
||||
|
||||
@Mock
|
||||
CameraDevice cameraDevice;
|
||||
@Mock
|
||||
SelectorFunction<Size> photoSizeSelector;
|
||||
@Mock
|
||||
SelectorFunction<Size> previewSizeSelector;
|
||||
@Mock
|
||||
SelectorFunction<FocusMode> focusModeSelector;
|
||||
@Mock
|
||||
SelectorFunction<Flash> flashModeSelector;
|
||||
@Mock
|
||||
InitialParametersValidator initialParametersValidator;
|
||||
@Mock
|
||||
CapabilitiesOperator capabilitiesOperator;
|
||||
|
||||
InitialParametersProvider testee;
|
||||
@Test
|
||||
public void validPreviewSizeSelector_WithValidAspectRatio() throws Exception {
|
||||
// When
|
||||
Size result = InitialParametersProvider
|
||||
.validPreviewSizeSelector(
|
||||
PHOTO_SIZE,
|
||||
select(PREVIEW_SIZE)
|
||||
)
|
||||
.select(ALL_PREVIEW_SIZES);
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
testee = new InitialParametersProvider(
|
||||
cameraDevice,
|
||||
photoSizeSelector,
|
||||
previewSizeSelector,
|
||||
focusModeSelector,
|
||||
flashModeSelector,
|
||||
// Then
|
||||
assertEquals(
|
||||
PREVIEW_SIZE,
|
||||
result
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void validPreviewSizeSelector_NoPreviewSizeWithSameAspectRatio() throws Exception {
|
||||
// Given
|
||||
Size photoSize = new Size(10000, 100);
|
||||
|
||||
// When
|
||||
Size result = InitialParametersProvider
|
||||
.validPreviewSizeSelector(
|
||||
photoSize,
|
||||
select(PREVIEW_SIZE)
|
||||
)
|
||||
.select(ALL_PREVIEW_SIZES);
|
||||
|
||||
// Then
|
||||
assertEquals(
|
||||
PREVIEW_SIZE,
|
||||
result
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void initialParameters() throws Exception {
|
||||
// Given
|
||||
given(capabilitiesOperator.getCapabilities())
|
||||
.willReturn(new Capabilities(
|
||||
asSet(PHOTO_SIZE),
|
||||
ALL_PREVIEW_SIZES,
|
||||
asSet(FocusMode.AUTO),
|
||||
asSet(Flash.TORCH),
|
||||
true
|
||||
));
|
||||
|
||||
InitialParametersProvider testee = new InitialParametersProvider(
|
||||
capabilitiesOperator,
|
||||
SizeSelectors.biggestSize(),
|
||||
SizeSelectors.biggestSize(),
|
||||
autoFocus(),
|
||||
torch(),
|
||||
initialParametersValidator
|
||||
);
|
||||
|
||||
given(cameraDevice.getCapabilities())
|
||||
.willReturn(new Capabilities(
|
||||
PHOTO_SIZES,
|
||||
ALL_PREVIEW_SIZES,
|
||||
FOCUS_MODES,
|
||||
FLASH
|
||||
));
|
||||
|
||||
given(photoSizeSelector.select(PHOTO_SIZES))
|
||||
.willReturn(PHOTO_SIZE);
|
||||
given(previewSizeSelector.select(VALID_PREVIEW_SIZES))
|
||||
.willReturn(PREVIEW_SIZE);
|
||||
given(focusModeSelector.select(FOCUS_MODES))
|
||||
.willReturn(FocusMode.FIXED);
|
||||
given(flashModeSelector.select(FLASH))
|
||||
.willReturn(Flash.AUTO_RED_EYE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void selectFocusMode() throws Exception {
|
||||
// When
|
||||
Parameters parameters = testee.initialParameters();
|
||||
|
||||
// Then
|
||||
assertEquals(
|
||||
FocusMode.FIXED,
|
||||
parameters.getValue(Parameters.Type.FOCUS_MODE)
|
||||
new Parameters()
|
||||
.putValue(
|
||||
Parameters.Type.PICTURE_SIZE,
|
||||
PHOTO_SIZE
|
||||
)
|
||||
.putValue(
|
||||
Parameters.Type.PREVIEW_SIZE,
|
||||
PREVIEW_SIZE
|
||||
)
|
||||
.putValue(
|
||||
Parameters.Type.FOCUS_MODE,
|
||||
FocusMode.AUTO
|
||||
)
|
||||
.putValue(
|
||||
Parameters.Type.FLASH,
|
||||
Flash.TORCH
|
||||
),
|
||||
parameters
|
||||
);
|
||||
|
||||
verify(initialParametersValidator).validate(parameters);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void selectFlashMode() throws Exception {
|
||||
// When
|
||||
Parameters parameters = testee.initialParameters();
|
||||
|
||||
// Then
|
||||
assertEquals(
|
||||
Flash.AUTO_RED_EYE,
|
||||
parameters.getValue(Parameters.Type.FLASH)
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void selectPhotoSize() throws Exception {
|
||||
// When
|
||||
Parameters parameters = testee.initialParameters();
|
||||
|
||||
// Then
|
||||
assertEquals(
|
||||
PHOTO_SIZE,
|
||||
parameters.getValue(Parameters.Type.PICTURE_SIZE)
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void selectPreviewSize_WithValidAspectRatio() throws Exception {
|
||||
// When
|
||||
Parameters parameters = testee.initialParameters();
|
||||
|
||||
// Then
|
||||
verify(previewSizeSelector).select(VALID_PREVIEW_SIZES);
|
||||
|
||||
assertEquals(
|
||||
PREVIEW_SIZE,
|
||||
parameters.getValue(Parameters.Type.PREVIEW_SIZE)
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void selectPreviewSize_SameAspectRatioNotAvailable() throws Exception {
|
||||
// Given
|
||||
Size photoSize = new Size(10000, 100);
|
||||
Set<Size> photoSizes = singleton(photoSize);
|
||||
|
||||
given(photoSizeSelector.select(photoSizes))
|
||||
.willReturn(photoSize);
|
||||
|
||||
given(cameraDevice.getCapabilities())
|
||||
.willReturn(new Capabilities(
|
||||
photoSizes,
|
||||
ALL_PREVIEW_SIZES,
|
||||
FOCUS_MODES,
|
||||
FLASH
|
||||
));
|
||||
|
||||
given(previewSizeSelector.select(ALL_PREVIEW_SIZES))
|
||||
.willReturn(PREVIEW_SIZE);
|
||||
|
||||
// When
|
||||
Parameters parameters = testee.initialParameters();
|
||||
|
||||
// Then
|
||||
assertEquals(
|
||||
PREVIEW_SIZE,
|
||||
parameters.getValue(Parameters.Type.PREVIEW_SIZE)
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parameterValidation() throws Exception {
|
||||
// Given
|
||||
|
||||
// When
|
||||
testee.initialParameters();
|
||||
|
||||
// Then
|
||||
verify(initialParametersValidator).validate(any(Parameters.class));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package io.fotoapparat.parameter.update;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import io.fotoapparat.parameter.Flash;
|
||||
import io.fotoapparat.parameter.FocusMode;
|
||||
import io.fotoapparat.parameter.selector.SelectorFunction;
|
||||
|
||||
import static org.junit.Assert.assertSame;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class UpdateRequestTest {
|
||||
|
||||
@Mock
|
||||
SelectorFunction<Flash> flashSelector;
|
||||
@Mock
|
||||
SelectorFunction<FocusMode> focusModeSelector;
|
||||
|
||||
@Test
|
||||
public void build() throws Exception {
|
||||
// When
|
||||
UpdateRequest updateRequest = UpdateRequest.builder()
|
||||
.flash(flashSelector)
|
||||
.focusMode(focusModeSelector)
|
||||
.build();
|
||||
|
||||
// Then
|
||||
assertSame(flashSelector, updateRequest.flashSelector);
|
||||
assertSame(focusModeSelector, updateRequest.focusModeSelector);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
package io.fotoapparat.routine;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import io.fotoapparat.hardware.CameraDevice;
|
||||
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class AutoFocusRoutineTest {
|
||||
|
||||
@Mock
|
||||
CameraDevice cameraDevice;
|
||||
|
||||
@InjectMocks
|
||||
AutoFocusRoutine testee;
|
||||
|
||||
@Test
|
||||
public void autoFocus() throws Exception {
|
||||
// When
|
||||
testee.run();
|
||||
|
||||
// Then
|
||||
verify(cameraDevice).autoFocus();
|
||||
}
|
||||
}
|
||||
@@ -1,98 +1,162 @@
|
||||
package io.fotoapparat.routine;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentMatchers;
|
||||
import org.mockito.InOrder;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import io.fotoapparat.error.CameraErrorCallback;
|
||||
import io.fotoapparat.hardware.CameraDevice;
|
||||
import io.fotoapparat.hardware.CameraException;
|
||||
import io.fotoapparat.hardware.orientation.ScreenOrientationProvider;
|
||||
import io.fotoapparat.parameter.LensPosition;
|
||||
import io.fotoapparat.parameter.Parameters;
|
||||
import io.fotoapparat.parameter.ScaleType;
|
||||
import io.fotoapparat.parameter.provider.InitialParametersProvider;
|
||||
import io.fotoapparat.parameter.selector.SelectorFunction;
|
||||
import io.fotoapparat.view.CameraRenderer;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.doThrow;
|
||||
import static org.mockito.Mockito.inOrder;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
import static org.mockito.Mockito.verifyZeroInteractions;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class StartCameraRoutineTest {
|
||||
|
||||
static final int SCREEN_ROTATION_DEGREES = 90;
|
||||
static final Parameters INITIAL_PARAMETERS = new Parameters();
|
||||
static final int SCREEN_ROTATION_DEGREES = 90;
|
||||
static final Parameters INITIAL_PARAMETERS = new Parameters();
|
||||
|
||||
@Mock
|
||||
CameraDevice cameraDevice;
|
||||
@Mock
|
||||
CameraRenderer cameraRenderer;
|
||||
@Mock
|
||||
SelectorFunction<LensPosition> lensPositionSelector;
|
||||
@Mock
|
||||
ScreenOrientationProvider screenOrientationProvider;
|
||||
@Mock
|
||||
InitialParametersProvider initialParametersProvider;
|
||||
@SuppressWarnings("ThrowableInstanceNeverThrown")
|
||||
static final CameraException CAMERA_EXCEPTION = new CameraException("test");
|
||||
|
||||
@InjectMocks
|
||||
StartCameraRoutine testee;
|
||||
@Mock
|
||||
CameraDevice cameraDevice;
|
||||
@Mock
|
||||
CameraRenderer cameraRenderer;
|
||||
@Mock
|
||||
SelectorFunction<LensPosition> lensPositionSelector;
|
||||
@Mock
|
||||
ScreenOrientationProvider screenOrientationProvider;
|
||||
@Mock
|
||||
InitialParametersProvider initialParametersProvider;
|
||||
@Mock
|
||||
CameraErrorCallback cameraErrorCallback;
|
||||
|
||||
@Test
|
||||
public void routine() throws Exception {
|
||||
// Given
|
||||
List<LensPosition> availableLensPositions = asList(
|
||||
LensPosition.FRONT,
|
||||
LensPosition.BACK
|
||||
);
|
||||
StartCameraRoutine testee;
|
||||
|
||||
LensPosition preferredLensPosition = LensPosition.FRONT;
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
testee = new StartCameraRoutine(
|
||||
cameraDevice,
|
||||
cameraRenderer,
|
||||
ScaleType.CENTER_INSIDE,
|
||||
lensPositionSelector,
|
||||
screenOrientationProvider,
|
||||
initialParametersProvider,
|
||||
cameraErrorCallback
|
||||
);
|
||||
}
|
||||
|
||||
givenLensPositionsAvailable(availableLensPositions);
|
||||
givenPositionSelected(preferredLensPosition);
|
||||
givenScreenRotation();
|
||||
givenInitialParametersAvailable();
|
||||
@Test
|
||||
public void routine() throws Exception {
|
||||
// Given
|
||||
StartCameraRoutine testee = new StartCameraRoutine(
|
||||
cameraDevice,
|
||||
cameraRenderer,
|
||||
ScaleType.CENTER_INSIDE,
|
||||
lensPositionSelector,
|
||||
screenOrientationProvider,
|
||||
initialParametersProvider,
|
||||
cameraErrorCallback
|
||||
);
|
||||
List<LensPosition> availableLensPositions = asList(
|
||||
LensPosition.FRONT,
|
||||
LensPosition.BACK
|
||||
);
|
||||
|
||||
// When
|
||||
testee.run();
|
||||
LensPosition preferredLensPosition = LensPosition.FRONT;
|
||||
ScaleType scaleType = ScaleType.CENTER_INSIDE;
|
||||
|
||||
// Then
|
||||
InOrder inOrder = inOrder(
|
||||
cameraDevice,
|
||||
cameraRenderer,
|
||||
lensPositionSelector
|
||||
);
|
||||
givenLensPositionsAvailable(availableLensPositions);
|
||||
givenPositionSelected(preferredLensPosition);
|
||||
givenScreenRotation();
|
||||
givenInitialParametersAvailable();
|
||||
|
||||
inOrder.verify(lensPositionSelector).select(availableLensPositions);
|
||||
inOrder.verify(cameraDevice).open(preferredLensPosition);
|
||||
inOrder.verify(cameraDevice).updateParameters(INITIAL_PARAMETERS);
|
||||
inOrder.verify(cameraDevice).setDisplayOrientation(SCREEN_ROTATION_DEGREES);
|
||||
inOrder.verify(cameraRenderer).attachCamera(cameraDevice);
|
||||
inOrder.verify(cameraDevice).startPreview();
|
||||
}
|
||||
// When
|
||||
testee.run();
|
||||
|
||||
private void givenInitialParametersAvailable() {
|
||||
given(initialParametersProvider.initialParameters())
|
||||
.willReturn(INITIAL_PARAMETERS);
|
||||
}
|
||||
// Then
|
||||
InOrder inOrder = inOrder(
|
||||
cameraDevice,
|
||||
cameraRenderer,
|
||||
lensPositionSelector
|
||||
);
|
||||
|
||||
private void givenScreenRotation() {
|
||||
given(screenOrientationProvider.getScreenRotation())
|
||||
.willReturn(SCREEN_ROTATION_DEGREES);
|
||||
}
|
||||
inOrder.verify(lensPositionSelector).select(availableLensPositions);
|
||||
inOrder.verify(cameraDevice).open(preferredLensPosition);
|
||||
inOrder.verify(cameraDevice).updateParameters(INITIAL_PARAMETERS);
|
||||
inOrder.verify(cameraDevice).setDisplayOrientation(SCREEN_ROTATION_DEGREES);
|
||||
inOrder.verify(cameraRenderer).setScaleType(scaleType);
|
||||
inOrder.verify(cameraRenderer).attachCamera(cameraDevice);
|
||||
inOrder.verify(cameraDevice).startPreview();
|
||||
verifyZeroInteractions(cameraErrorCallback);
|
||||
}
|
||||
|
||||
private void givenPositionSelected(LensPosition lensPosition) {
|
||||
given(lensPositionSelector.select(ArgumentMatchers.<LensPosition>anyCollection()))
|
||||
.willReturn(lensPosition);
|
||||
}
|
||||
@Test
|
||||
public void failedToOpenCamera() throws Exception {
|
||||
// Given
|
||||
List<LensPosition> availableLensPositions = asList(
|
||||
LensPosition.FRONT,
|
||||
LensPosition.BACK
|
||||
);
|
||||
|
||||
private void givenLensPositionsAvailable(List<LensPosition> lensPositions) {
|
||||
given(cameraDevice.getAvailableLensPositions())
|
||||
.willReturn(lensPositions);
|
||||
}
|
||||
LensPosition preferredLensPosition = LensPosition.FRONT;
|
||||
|
||||
givenLensPositionsAvailable(availableLensPositions);
|
||||
givenPositionSelected(preferredLensPosition);
|
||||
|
||||
doThrow(CAMERA_EXCEPTION)
|
||||
.when(cameraDevice)
|
||||
.open(preferredLensPosition);
|
||||
|
||||
// When
|
||||
testee.run();
|
||||
|
||||
// Then
|
||||
verify(cameraErrorCallback).onError(CAMERA_EXCEPTION);
|
||||
|
||||
verify(cameraDevice).getAvailableLensPositions();
|
||||
verify(cameraDevice).open(preferredLensPosition);
|
||||
verifyNoMoreInteractions(cameraDevice);
|
||||
}
|
||||
|
||||
private void givenInitialParametersAvailable() {
|
||||
given(initialParametersProvider.initialParameters())
|
||||
.willReturn(INITIAL_PARAMETERS);
|
||||
}
|
||||
|
||||
private void givenScreenRotation() {
|
||||
given(screenOrientationProvider.getScreenRotation())
|
||||
.willReturn(SCREEN_ROTATION_DEGREES);
|
||||
}
|
||||
|
||||
private void givenPositionSelected(LensPosition lensPosition) {
|
||||
given(lensPositionSelector.select(ArgumentMatchers.<LensPosition>anyCollection()))
|
||||
.willReturn(lensPosition);
|
||||
}
|
||||
|
||||
private void givenLensPositionsAvailable(List<LensPosition> lensPositions) {
|
||||
given(cameraDevice.getAvailableLensPositions())
|
||||
.willReturn(lensPositions);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package io.fotoapparat.routine.focus;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Spy;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import io.fotoapparat.hardware.CameraDevice;
|
||||
import io.fotoapparat.result.FocusResult;
|
||||
import io.fotoapparat.result.PendingResult;
|
||||
import io.fotoapparat.test.ImmediateExecutor;
|
||||
|
||||
import static junit.framework.Assert.assertNotNull;
|
||||
import static org.mockito.ArgumentMatchers.isA;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class AutoFocusRoutineTest {
|
||||
|
||||
@Mock
|
||||
CameraDevice cameraDevice;
|
||||
@Spy
|
||||
Executor executor = new ImmediateExecutor();
|
||||
|
||||
@InjectMocks
|
||||
AutoFocusRoutine testee;
|
||||
|
||||
@Test
|
||||
public void autoFocus() throws Exception {
|
||||
// When
|
||||
PendingResult<FocusResult> result = testee.autoFocus();
|
||||
|
||||
// Then
|
||||
verify(executor).execute(isA(AutoFocusTask.class));
|
||||
|
||||
assertNotNull(result);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package io.fotoapparat.routine.focus;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import io.fotoapparat.hardware.CameraDevice;
|
||||
import io.fotoapparat.lens.FocusResult;
|
||||
|
||||
import static io.fotoapparat.result.FocusResult.FOCUSED;
|
||||
import static io.fotoapparat.result.FocusResult.UNABLE_TO_FOCUS;
|
||||
import static io.fotoapparat.test.TestUtils.resultOf;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class AutoFocusTaskTest {
|
||||
|
||||
@Mock
|
||||
CameraDevice cameraDevice;
|
||||
|
||||
@InjectMocks
|
||||
AutoFocusTask testee;
|
||||
|
||||
@Test
|
||||
public void autoFocus_Focused() throws Exception {
|
||||
// Given
|
||||
given(cameraDevice.autoFocus())
|
||||
.willReturn(new FocusResult(true, false));
|
||||
|
||||
// When
|
||||
io.fotoapparat.result.FocusResult result = resultOf(testee);
|
||||
|
||||
// Then
|
||||
assertEquals(result, FOCUSED);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void autoFocus_UnableToFocus() throws Exception {
|
||||
// Given
|
||||
given(cameraDevice.autoFocus())
|
||||
.willReturn(new FocusResult(false, false));
|
||||
|
||||
// When
|
||||
io.fotoapparat.result.FocusResult result = resultOf(testee);
|
||||
|
||||
// Then
|
||||
assertEquals(result, UNABLE_TO_FOCUS);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package io.fotoapparat.routine.parameter;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import io.fotoapparat.hardware.CameraDevice;
|
||||
import io.fotoapparat.hardware.Capabilities;
|
||||
import io.fotoapparat.parameter.Flash;
|
||||
import io.fotoapparat.parameter.FocusMode;
|
||||
import io.fotoapparat.parameter.Parameters;
|
||||
import io.fotoapparat.parameter.Size;
|
||||
import io.fotoapparat.parameter.update.UpdateRequest;
|
||||
|
||||
import static io.fotoapparat.parameter.selector.FlashSelectors.torch;
|
||||
import static io.fotoapparat.parameter.selector.FocusModeSelectors.autoFocus;
|
||||
import static io.fotoapparat.test.TestUtils.asSet;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class UpdateParametersRoutineTest {
|
||||
|
||||
@Mock
|
||||
CameraDevice cameraDevice;
|
||||
|
||||
@InjectMocks
|
||||
UpdateParametersRoutine testee;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
given(cameraDevice.getCapabilities())
|
||||
.willReturn(new Capabilities(
|
||||
Collections.<Size>emptySet(),
|
||||
Collections.<Size>emptySet(),
|
||||
asSet(FocusMode.AUTO),
|
||||
asSet(Flash.TORCH),
|
||||
false
|
||||
));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateParameters() throws Exception {
|
||||
// Given
|
||||
UpdateRequest request = UpdateRequest.builder()
|
||||
.flash(torch())
|
||||
.focusMode(autoFocus())
|
||||
.build();
|
||||
|
||||
// When
|
||||
testee.updateParameters(request);
|
||||
|
||||
// Then
|
||||
verify(cameraDevice).updateParameters(
|
||||
new Parameters()
|
||||
.putValue(
|
||||
Parameters.Type.FLASH,
|
||||
Flash.TORCH
|
||||
)
|
||||
.putValue(
|
||||
Parameters.Type.FOCUS_MODE,
|
||||
FocusMode.AUTO
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package io.fotoapparat.routine;
|
||||
package io.fotoapparat.routine.picture;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
@@ -11,6 +11,8 @@ import java.util.concurrent.Executor;
|
||||
|
||||
import io.fotoapparat.hardware.CameraDevice;
|
||||
import io.fotoapparat.result.PhotoResult;
|
||||
import io.fotoapparat.routine.picture.TakePictureRoutine;
|
||||
import io.fotoapparat.routine.picture.TakePictureTask;
|
||||
import io.fotoapparat.test.ImmediateExecutor;
|
||||
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
@@ -1,4 +1,4 @@
|
||||
package io.fotoapparat.routine;
|
||||
package io.fotoapparat.routine.picture;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
@@ -9,14 +9,17 @@ import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import io.fotoapparat.hardware.CameraDevice;
|
||||
import io.fotoapparat.hardware.CameraException;
|
||||
import io.fotoapparat.lens.FocusResult;
|
||||
import io.fotoapparat.photo.Photo;
|
||||
|
||||
import static io.fotoapparat.test.TestUtils.resultOf;
|
||||
import static junit.framework.Assert.assertEquals;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.doThrow;
|
||||
import static org.mockito.Mockito.inOrder;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class TakePictureTaskTest {
|
||||
@@ -89,4 +92,24 @@ public class TakePictureTaskTest {
|
||||
|
||||
assertEquals(result, PHOTO);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void startPreviewFailed() throws Exception {
|
||||
// Given
|
||||
given(cameraDevice.autoFocus())
|
||||
.willReturn(new FocusResult(true, false));
|
||||
|
||||
doThrow(new CameraException("test"))
|
||||
.when(cameraDevice)
|
||||
.startPreview();
|
||||
|
||||
// When
|
||||
Photo result = resultOf(testee);
|
||||
|
||||
// Then
|
||||
verify(cameraDevice).startPreview();
|
||||
|
||||
assertEquals(result, PHOTO);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
package io.fotoapparat.routine.zoom;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import io.fotoapparat.hardware.CameraDevice;
|
||||
import io.fotoapparat.hardware.Capabilities;
|
||||
import io.fotoapparat.parameter.Flash;
|
||||
import io.fotoapparat.parameter.FocusMode;
|
||||
import io.fotoapparat.parameter.Size;
|
||||
import io.fotoapparat.routine.zoom.UpdateZoomLevelRoutine.LevelOutOfRangeException;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.anyFloat;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class UpdateZoomLevelRoutineTest {
|
||||
|
||||
@Mock
|
||||
CameraDevice cameraDevice;
|
||||
|
||||
@InjectMocks
|
||||
UpdateZoomLevelRoutine testee;
|
||||
|
||||
@SuppressWarnings("Range")
|
||||
@Test(expected = LevelOutOfRangeException.class)
|
||||
public void outOfRange_Higher() throws Exception {
|
||||
// When
|
||||
testee.updateZoomLevel(1.1f);
|
||||
|
||||
// Then
|
||||
// Expect exception
|
||||
}
|
||||
|
||||
@SuppressWarnings("Range")
|
||||
@Test(expected = LevelOutOfRangeException.class)
|
||||
public void outOfRange_Lower() throws Exception {
|
||||
// When
|
||||
testee.updateZoomLevel(-0.1f);
|
||||
|
||||
// Then
|
||||
// Expect exception
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateZoomLevel() throws Exception {
|
||||
// Given
|
||||
givenZoomSupported();
|
||||
|
||||
// When
|
||||
testee.updateZoomLevel(0.5f);
|
||||
|
||||
// Then
|
||||
verify(cameraDevice).setZoom(0.5f);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void zoomNotSupported() throws Exception {
|
||||
// Given
|
||||
givenZoomNotSupported();
|
||||
|
||||
// When
|
||||
testee.updateZoomLevel(0.5f);
|
||||
|
||||
// Then
|
||||
verify(cameraDevice, never()).setZoom(anyFloat());
|
||||
}
|
||||
|
||||
private void givenZoomNotSupported() {
|
||||
givenZoom(false);
|
||||
}
|
||||
|
||||
private void givenZoomSupported() {
|
||||
givenZoom(true);
|
||||
}
|
||||
|
||||
private void givenZoom(boolean supported) {
|
||||
given(cameraDevice.getCapabilities())
|
||||
.willReturn(new Capabilities(
|
||||
Collections.<Size>emptySet(),
|
||||
Collections.<Size>emptySet(),
|
||||
Collections.<FocusMode>emptySet(),
|
||||
Collections.<Flash>emptySet(),
|
||||
supported
|
||||
));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -28,7 +28,8 @@ public class GetCapabilitiesTaskTest {
|
||||
Collections.singleton(new Size(1400, 1080)),
|
||||
Collections.singleton(new Size(1400, 1080)),
|
||||
Collections.singleton(FocusMode.CONTINUOUS_FOCUS),
|
||||
Collections.singleton(Flash.OFF)
|
||||
Collections.singleton(Flash.OFF),
|
||||
false
|
||||
);
|
||||
|
||||
@Mock
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
package io.fotoapparat.util;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import io.fotoapparat.parameter.selector.SelectorFunction;
|
||||
|
||||
/**
|
||||
* Selectors which are convenient for tests.
|
||||
*/
|
||||
public class TestSelectors {
|
||||
|
||||
/**
|
||||
* @return selector which always returns given object as a result of selection.
|
||||
*/
|
||||
public static <T> SelectorFunction<T> select(final T object) {
|
||||
return new SelectorFunction<T>() {
|
||||
@Override
|
||||
public T select(Collection<T> items) {
|
||||
return object;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
androidBuildToolsVersion=2.3.2
|
||||
buildToolsVersion=25.0.2
|
||||
compileSdkVersion=25
|
||||
minSdkVersion=15
|
||||
minSdkVersion=14
|
||||
targetSdkVersion=25
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ mockitoVersion=2.2.28
|
||||
|
||||
|
||||
#Gradle Properties
|
||||
gradleVersion=3.3
|
||||
gradleVersion=4.0
|
||||
org.gradle.daemon=true
|
||||
org.gradle.parallel=true
|
||||
org.gradle.jvmargs=-Xmx1536m
|
||||
|
||||
@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.0-all.zip
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
android:allowBackup="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/AppTheme">
|
||||
<activity
|
||||
|
||||
@@ -3,14 +3,22 @@ package io.fotoapparat.sample;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.support.v7.widget.SwitchCompat;
|
||||
import android.view.View;
|
||||
import android.widget.CompoundButton;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.SeekBar;
|
||||
import android.widget.Toast;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import io.fotoapparat.Fotoapparat;
|
||||
import io.fotoapparat.FotoapparatSwitcher;
|
||||
import io.fotoapparat.error.CameraErrorCallback;
|
||||
import io.fotoapparat.hardware.CameraException;
|
||||
import io.fotoapparat.parameter.LensPosition;
|
||||
import io.fotoapparat.parameter.ScaleType;
|
||||
import io.fotoapparat.parameter.update.UpdateRequest;
|
||||
import io.fotoapparat.photo.BitmapPhoto;
|
||||
import io.fotoapparat.preview.Frame;
|
||||
import io.fotoapparat.preview.FrameProcessor;
|
||||
@@ -58,24 +66,77 @@ public class MainActivity extends AppCompatActivity {
|
||||
permissionsDelegate.requestCameraPermission();
|
||||
}
|
||||
|
||||
setupFotoapparat();
|
||||
|
||||
takePictureOnClick();
|
||||
focusOnLongClick();
|
||||
switchCameraOnClick();
|
||||
toggleTorchOnSwitch();
|
||||
zoomSeekBar();
|
||||
}
|
||||
|
||||
private void setupFotoapparat() {
|
||||
frontFotoapparat = createFotoapparat(LensPosition.FRONT);
|
||||
backFotoapparat = createFotoapparat(LensPosition.BACK);
|
||||
fotoapparatSwitcher = FotoapparatSwitcher.withDefault(backFotoapparat);
|
||||
}
|
||||
|
||||
cameraView.setOnClickListener(new View.OnClickListener() {
|
||||
private void zoomSeekBar() {
|
||||
SeekBar seekBar = (SeekBar) findViewById(R.id.zoomSeekBar);
|
||||
|
||||
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
takePicture();
|
||||
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
|
||||
fotoapparatSwitcher
|
||||
.getCurrentFotoapparat()
|
||||
.setZoom(progress / (float) seekBar.getMax());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStartTrackingTouch(SeekBar seekBar) {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStopTrackingTouch(SeekBar seekBar) {
|
||||
// Do nothing
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void toggleTorchOnSwitch() {
|
||||
SwitchCompat torchSwitch = (SwitchCompat) findViewById(R.id.torchSwitch);
|
||||
|
||||
torchSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
||||
@Override
|
||||
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
||||
fotoapparatSwitcher
|
||||
.getCurrentFotoapparat()
|
||||
.updateParameters(
|
||||
UpdateRequest.builder()
|
||||
.flash(
|
||||
isChecked
|
||||
? torch()
|
||||
: off()
|
||||
)
|
||||
.build()
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void switchCameraOnClick() {
|
||||
View switchCameraButton = findViewById(R.id.switchCamera);
|
||||
switchCameraButton.setVisibility(
|
||||
canSwitchCameras()
|
||||
? View.VISIBLE
|
||||
: View.GONE
|
||||
);
|
||||
switchCameraButton.setOnClickListener(new View.OnClickListener() {
|
||||
switchCameraOnClick(switchCameraButton);
|
||||
}
|
||||
|
||||
private void switchCameraOnClick(View view) {
|
||||
view.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
switchCamera();
|
||||
@@ -83,6 +144,26 @@ public class MainActivity extends AppCompatActivity {
|
||||
});
|
||||
}
|
||||
|
||||
private void focusOnLongClick() {
|
||||
cameraView.setOnLongClickListener(new View.OnLongClickListener() {
|
||||
@Override
|
||||
public boolean onLongClick(View v) {
|
||||
fotoapparatSwitcher.getCurrentFotoapparat().autoFocus();
|
||||
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void takePictureOnClick() {
|
||||
cameraView.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
takePicture();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private boolean canSwitchCameras() {
|
||||
return frontFotoapparat.isAvailable() == backFotoapparat.isAvailable();
|
||||
}
|
||||
@@ -91,6 +172,7 @@ public class MainActivity extends AppCompatActivity {
|
||||
return Fotoapparat
|
||||
.with(this)
|
||||
.into(cameraView)
|
||||
.previewScaleType(ScaleType.CENTER_CROP)
|
||||
.photoSize(standardRatio(biggestSize()))
|
||||
.lensPosition(lensPosition(position))
|
||||
.focusMode(firstAvailable(
|
||||
@@ -109,6 +191,12 @@ public class MainActivity extends AppCompatActivity {
|
||||
logcat(),
|
||||
fileLogger(this)
|
||||
))
|
||||
.cameraErrorCallback(new CameraErrorCallback() {
|
||||
@Override
|
||||
public void onError(CameraException e) {
|
||||
Toast.makeText(MainActivity.this, e.toString(), Toast.LENGTH_LONG).show();
|
||||
}
|
||||
})
|
||||
.build();
|
||||
}
|
||||
|
||||
|
||||
@@ -39,4 +39,19 @@
|
||||
android:layout_margin="8dp"
|
||||
android:text="Switch camera"/>
|
||||
|
||||
<android.support.v7.widget.SwitchCompat
|
||||
android:id="@+id/torchSwitch"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="top|left"
|
||||
android:layout_margin="8dp"/>
|
||||
|
||||
<SeekBar
|
||||
android:id="@+id/zoomSeekBar"
|
||||
android:layout_width="200dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom|center_horizontal"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:max="30"/>
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
|
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 5.6 KiB |
|
Before Width: | Height: | Size: 4.1 KiB |
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 2.5 KiB |
|
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 8.4 KiB |
|
Before Width: | Height: | Size: 6.0 KiB |
|
Before Width: | Height: | Size: 7.5 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 9.8 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 14 KiB |