Skip to content
This repository was archived by the owner on Feb 22, 2023. It is now read-only.

[camera] Add support for Torch and Auto Exposure (#19845) #1969

Closed
wants to merge 47 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
11966fa
[camera] Add support for Torch and Auto Exposure
NeKoFu Aug 8, 2019
841d3f3
[camera] set auto exposure trigger when turn on or off the torch
NeKoFu Aug 10, 2019
77fffa0
[camera] increment version in pubspec.yaml
NeKoFu Aug 10, 2019
2680f8d
[camera] update changelog
NeKoFu Aug 10, 2019
8afa990
Merge branch 'master' into camera_torch
NeKoFu Aug 10, 2019
ab961e9
[camera] fix format for default value
NeKoFu Aug 10, 2019
3e284a9
Merge branch 'camera_torch' of https://github.com/NeKoFu/plugins.git
NeKoFu Aug 10, 2019
664f566
[camera] remove commented code and fix format
NeKoFu Aug 10, 2019
cf1986d
[camera] fix format
NeKoFu Aug 10, 2019
9301cab
[camera] fix space characters
NeKoFu Aug 10, 2019
f5566ac
[camera] fix format
NeKoFu Aug 10, 2019
1111074
[camera] delete a blank line for the pleasure of the CI
NeKoFu Aug 10, 2019
21f1ddf
[camera] refactor ios code
NeKoFu Aug 10, 2019
de89946
[camera] fix ios code format
NeKoFu Aug 10, 2019
d2b876f
[camera] fix ios code
NeKoFu Aug 10, 2019
4c18d55
[camera] delete a blank line for the pleasure of the CI
NeKoFu Aug 10, 2019
6d4ef41
[camera] fix iOS mistakes like default value for the setTorchMode and…
NeKoFu Aug 11, 2019
81d35ae
[camera] resolve merge conflit
NeKoFu Aug 11, 2019
dd8f6f3
[camera] fix iOS code
NeKoFu Aug 11, 2019
02d9b40
[camera] Merge branch 'camera_torch'
NeKoFu Aug 11, 2019
1d8d34a
[camera] fix enum to choose Exposure
NeKoFu Aug 11, 2019
5b622cf
[camera] fix float casting in iOS code
NeKoFu Aug 11, 2019
05adac8
[camera] Update example
NeKoFu Aug 11, 2019
4605961
[camera] Fix format
NeKoFu Aug 11, 2019
7b64146
[camera] Replace the term 'Torch' by 'Flash'
NeKoFu Aug 16, 2019
8741890
[camera] Fix format
NeKoFu Aug 16, 2019
9724679
[camera] Fix format
NeKoFu Aug 16, 2019
cb6bc8a
Merge branch 'camera_torch' of https://github.com/NeKoFu/plugins.git
NeKoFu Aug 16, 2019
7d62af2
Merge branch 'master' into camera_torch
NeKoFu Aug 16, 2019
36ddfd6
[camera] Fix format again
NeKoFu Aug 16, 2019
44fb024
Merge branch 'camera_torch' of https://github.com/NeKoFu/plugins.git
NeKoFu Aug 16, 2019
fea203b
[camera] Fix iOS error, the iOS SDK use the term "Torch"
NeKoFu Aug 16, 2019
904c8f7
Merge branch 'master' into camera_torch
NeKoFu Aug 20, 2019
3fe609a
[camera] Control flash and focus mode
NeKoFu Sep 25, 2019
c39a6e2
[camera] Fix partial enlightenment
NeKoFu Sep 25, 2019
b2da249
Merge branch 'master' of https://github.com/flutter/plugins into flut…
NeKoFu Sep 26, 2019
4541a72
Merge branch 'flutter-master'
NeKoFu Sep 26, 2019
b03555d
Merge branch 'master' into camera_torch
NeKoFu Sep 26, 2019
7bb389c
[camera] Fix missing import and increment version
NeKoFu Sep 26, 2019
74b5a48
Merge branch 'master' into camera_torch
NeKoFu Sep 26, 2019
0f80b95
[camera] Fix continuous autofocus mode
NeKoFu Oct 8, 2019
0dccb8e
Merge branch 'camera_torch' of https://github.com/NeKoFu/plugins.git
NeKoFu Oct 8, 2019
fccf0f2
Merge branch 'master' of https://github.com/flutter/plugins into flut…
NeKoFu Nov 3, 2019
51e7ca6
Merge branch 'flutter-master'
NeKoFu Nov 3, 2019
16d5689
Merge branch 'master' into camera_torch
NeKoFu Nov 3, 2019
316869a
Merge fix
NeKoFu Nov 3, 2019
47aedeb
Merge commit 'fc45624236b8789ea2fc776a7b254cd16e9dc926'
NeKoFu Apr 7, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion packages/camera/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 0.5.8

* Add support for Flash and Auto Focus.

## 0.5.7+5

* Replace deprecated `getFlutterEngine` call on Android.
Expand Down Expand Up @@ -75,7 +79,6 @@
* Fix too large request code for FragmentActivity users.

## 0.5.3

* Added new quality presets.
* Now all quality presets can be used to control image capture quality.

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-all.zip
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ public class Camera {
private final Size previewSize;
private final boolean enableAudio;

private int flashMode;
private int autoFocusMode;
private CameraDevice cameraDevice;
private CameraCaptureSession cameraCaptureSession;
private ImageReader pictureImageReader;
Expand All @@ -71,20 +73,38 @@ public enum ResolutionPreset {
max,
}

// Flash control setting. (Mirrors FlashMode enum in camera.dart)
// Labels respect java convention to avoid conflict with reserved word or any variable name
private final int CAMERA_FLASH_MODE_OFF = 0;
private final int CAMERA_FLASH_MODE_ALWAYS_FLASH = 1;
private final int CAMERA_FLASH_MODE_AUTO_FLASH = 2;
private final int CAMERA_FLASH_MODE_TORCH = 3;

// Auto Focus setting. (Mirrors AutoFocusMode in camera.dart)
// Labels respect java convention to avoid conflict with reserved word or any variable name
private final int CAMERA_AUTO_FOCUS_MODE_OFF = 0;
private final int CAMERA_AUTO_FOCUS_MODE_AUTO = 1;
private final int CAMERA_AUTO_FOCUS_MODE_CONTINUOUS = 2;
private final int CAMERA_AUTO_FOCUS_MODE_MACRO = 3;

public Camera(
final Activity activity,
final SurfaceTextureEntry flutterTexture,
final DartMessenger dartMessenger,
final String cameraName,
final String resolutionPreset,
final boolean enableAudio)
final boolean enableAudio,
final int flashMode,
final int autoFocusMode)
throws CameraAccessException {
if (activity == null) {
throw new IllegalStateException("No activity available!");
}

this.cameraName = cameraName;
this.enableAudio = enableAudio;
this.flashMode = flashMode;
this.autoFocusMode = autoFocusMode;
this.flutterTexture = flutterTexture;
this.dartMessenger = dartMessenger;
this.cameraManager = (CameraManager) activity.getSystemService(Context.CAMERA_SERVICE);
Expand Down Expand Up @@ -249,6 +269,9 @@ public void takePicture(String filePath, @NonNull final Result result) {
cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
captureBuilder.addTarget(pictureImageReader.getSurface());
captureBuilder.set(CaptureRequest.JPEG_ORIENTATION, getMediaOrientation());
// Request initial Flash and Auto-Exposure
setFlashModeRequest(captureBuilder, flashMode);
setAutoFocusModeRequest(captureBuilder, autoFocusMode);

cameraCaptureSession.capture(
captureBuilder.build(),
Expand Down Expand Up @@ -320,6 +343,11 @@ public void onConfigured(@NonNull CameraCaptureSession session) {
cameraCaptureSession = session;
captureRequestBuilder.set(
CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO);

// Request initial Flash and Auto-Exposure
setFlashModeRequest(captureRequestBuilder, flashMode);
setAutoFocusModeRequest(captureRequestBuilder, autoFocusMode);

cameraCaptureSession.setRepeatingRequest(captureRequestBuilder.build(), null, null);
if (onSuccessCallback != null) {
onSuccessCallback.run();
Expand Down Expand Up @@ -475,6 +503,107 @@ private void setImageStreamImageAvailableListener(final EventChannel.EventSink i
null);
}

public void setFlash(@NonNull final Result result, int mode) {
try {
// Force turning off the torch to avoid keeping the
// light on when another flash mode is selected
if (mode != CAMERA_FLASH_MODE_TORCH && flashMode == CAMERA_FLASH_MODE_TORCH) {
setFlashModeRequest(captureRequestBuilder, CAMERA_FLASH_MODE_OFF);
setAutoFocusModeRequest(captureRequestBuilder, autoFocusMode);
CaptureRequest request = captureRequestBuilder.build();
cameraCaptureSession.setRepeatingRequest(request, null, null);
}

// Keep the new mode
flashMode = mode;

// Rebuild Capture Session with flash and focus settings
setFlashModeRequest(captureRequestBuilder, flashMode);
setAutoFocusModeRequest(captureRequestBuilder, autoFocusMode);
CaptureRequest request = captureRequestBuilder.build();
cameraCaptureSession.setRepeatingRequest(request, null, null);

result.success(null);
} catch (Exception e) {
result.error("cameraFlashFailed", e.getMessage(), null);
}
}

private void setFlashModeRequest(CaptureRequest.Builder builderRequest, int mode) {
// Request Flash mode and set the tightly coupled auto Exposure mode
int flashRequestMode;
int autoExposureRequestMode;
switch (mode) {
case CAMERA_FLASH_MODE_ALWAYS_FLASH:
flashRequestMode = CameraMetadata.FLASH_MODE_OFF;
autoExposureRequestMode = CameraMetadata.CONTROL_AE_MODE_ON_ALWAYS_FLASH;
break;
case CAMERA_FLASH_MODE_AUTO_FLASH:
flashRequestMode = CameraMetadata.FLASH_MODE_OFF;
autoExposureRequestMode = CameraMetadata.CONTROL_AE_MODE_ON_AUTO_FLASH;
break;
case CAMERA_FLASH_MODE_TORCH:
flashRequestMode = CameraMetadata.FLASH_MODE_TORCH;
autoExposureRequestMode = CameraMetadata.CONTROL_AE_MODE_ON;
break;
default:
flashRequestMode = CameraMetadata.FLASH_MODE_OFF;
autoExposureRequestMode = CameraMetadata.CONTROL_AE_MODE_ON;
}

builderRequest.set(CaptureRequest.FLASH_MODE, flashRequestMode);
builderRequest.set(CaptureRequest.CONTROL_AE_MODE, autoExposureRequestMode);

// Request Auto Exposure mode as recommended when you switch the Flash
// more information:
// https://developer.android.com/reference/android/hardware/camera2/CaptureRequest.html#FLASH_MODE
builderRequest.set(
CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER,
CameraMetadata.CONTROL_AE_PRECAPTURE_TRIGGER_START);
}

public void setAutoFocus(@NonNull final Result result, int mode) {
try {
// Keep the mode
autoFocusMode = mode;

// Rebuild Capture Session with flash and focus settings
setFlashModeRequest(captureRequestBuilder, flashMode);
setAutoFocusModeRequest(captureRequestBuilder, autoFocusMode);
CaptureRequest request = captureRequestBuilder.build();
cameraCaptureSession.setRepeatingRequest(request, null, null);

result.success(null);
} catch (Exception e) {
result.error("cameraAutoFocusFailed", e.getMessage(), null);
}
}

private void setAutoFocusModeRequest(CaptureRequest.Builder builderRequest, int mode) {
// Request Auto Focus Mode
int autoFocusRequestMode;
switch (mode) {
case CAMERA_AUTO_FOCUS_MODE_OFF:
autoFocusRequestMode = CameraMetadata.CONTROL_AF_MODE_AUTO;
break;
case CAMERA_AUTO_FOCUS_MODE_CONTINUOUS:
autoFocusRequestMode = CameraMetadata.CONTROL_AF_MODE_CONTINUOUS_PICTURE;
break;
case CAMERA_AUTO_FOCUS_MODE_MACRO:
autoFocusRequestMode = CameraMetadata.CONTROL_AF_MODE_MACRO;
break;
default:
autoFocusRequestMode = CameraMetadata.CONTROL_AF_MODE_AUTO;
}

builderRequest.set(CaptureRequest.CONTROL_AF_MODE, autoFocusRequestMode);

if (mode != CAMERA_AUTO_FOCUS_MODE_OFF && mode != CAMERA_AUTO_FOCUS_MODE_CONTINUOUS) {
builderRequest.set(
CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_START);
}
}

private void closeCaptureSession() {
if (cameraCaptureSession != null) {
cameraCaptureSession.close();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package io.flutter.plugins.camera;

import android.app.Activity;
import android.content.pm.PackageManager;
import android.hardware.camera2.CameraAccessException;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
Expand Down Expand Up @@ -123,6 +124,21 @@ public void onMethodCall(@NonNull MethodCall call, @NonNull final Result result)
}
break;
}
case "setFlash":
{
camera.setFlash(result, call.argument("mode"));
break;
}
case "hasFlash":
{
result.success(hasFlash());
break;
}
case "setAutoFocus":
{
camera.setAutoFocus(result, call.argument("mode"));
break;
}
case "dispose":
{
if (camera != null) {
Expand All @@ -141,10 +157,19 @@ void stopListening() {
methodChannel.setMethodCallHandler(null);
}

private boolean hasFlash() {
return activity
.getApplicationContext()
.getPackageManager()
.hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH);
}

private void instantiateCamera(MethodCall call, Result result) throws CameraAccessException {
String cameraName = call.argument("cameraName");
String resolutionPreset = call.argument("resolutionPreset");
boolean enableAudio = call.argument("enableAudio");
int flashMode = call.argument("flashMode");
int autoFocusMode = call.argument("autoFocusMode");
TextureRegistry.SurfaceTextureEntry flutterSurfaceTexture =
textureRegistry.createSurfaceTexture();
DartMessenger dartMessenger = new DartMessenger(messenger, flutterSurfaceTexture.id());
Expand All @@ -155,7 +180,9 @@ private void instantiateCamera(MethodCall call, Result result) throws CameraAcce
dartMessenger,
cameraName,
resolutionPreset,
enableAudio);
enableAudio,
flashMode,
autoFocusMode);

camera.open(result);
}
Expand Down
Loading