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

Commit fd8dd40

Browse files
committed
Added auto exposure implementations for Android and iOS
1 parent 1844b24 commit fd8dd40

File tree

18 files changed

+1478
-142
lines changed

18 files changed

+1478
-142
lines changed

packages/camera/camera/CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
## 0.6.4
2+
3+
* Adds auto exposure support for Android and iOS implementations.
4+
5+
## 0.6.3+1
6+
7+
* Fixes flash & torch modes not working on some Android devices.
8+
19
## 0.6.3
210

311
* Adds torch mode as a flash mode for Android and iOS implementations.

packages/camera/camera/android/src/main/java/io/flutter/plugins/camera/Camera.java

Lines changed: 332 additions & 31 deletions
Large diffs are not rendered by default.

packages/camera/camera/android/src/main/java/io/flutter/plugins/camera/DartMessenger.java

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import androidx.annotation.Nullable;
55
import io.flutter.plugin.common.BinaryMessenger;
66
import io.flutter.plugin.common.MethodChannel;
7+
import io.flutter.plugins.camera.types.ExposureMode;
78
import java.util.HashMap;
89
import java.util.Map;
910

@@ -20,13 +21,23 @@ enum EventType {
2021
channel = new MethodChannel(messenger, "flutter.io/cameraPlugin/camera" + cameraId);
2122
}
2223

23-
void sendCameraInitializedEvent(Integer previewWidth, Integer previewHeight) {
24+
void sendCameraInitializedEvent(
25+
Integer previewWidth,
26+
Integer previewHeight,
27+
ExposureMode exposureMode,
28+
Boolean exposurePointSupported) {
29+
assert (previewWidth != null);
30+
assert (previewHeight != null);
31+
assert (exposureMode != null);
32+
assert (exposurePointSupported != null);
2433
this.send(
2534
EventType.INITIALIZED,
2635
new HashMap<String, Object>() {
2736
{
28-
if (previewWidth != null) put("previewWidth", previewWidth.doubleValue());
29-
if (previewHeight != null) put("previewHeight", previewHeight.doubleValue());
37+
put("previewWidth", previewWidth.doubleValue());
38+
put("previewHeight", previewHeight.doubleValue());
39+
put("exposureMode", exposureMode.toString());
40+
put("exposurePointSupported", exposurePointSupported);
3041
}
3142
});
3243
}

packages/camera/camera/android/src/main/java/io/flutter/plugins/camera/MethodCallHandlerImpl.java

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import io.flutter.plugin.common.MethodChannel;
1111
import io.flutter.plugin.common.MethodChannel.Result;
1212
import io.flutter.plugins.camera.CameraPermissions.PermissionsRegistry;
13+
import io.flutter.plugins.camera.types.ExposureMode;
1314
import io.flutter.plugins.camera.types.FlashMode;
1415
import io.flutter.view.TextureRegistry;
1516
import java.util.HashMap;
@@ -138,6 +139,73 @@ public void onMethodCall(@NonNull MethodCall call, @NonNull final Result result)
138139
}
139140
break;
140141
}
142+
case "setExposureMode":
143+
{
144+
String modeStr = call.argument("mode");
145+
ExposureMode mode = ExposureMode.getValueForString(modeStr);
146+
if (mode == null) {
147+
result.error("setExposureModeFailed", "Unknown exposure mode " + modeStr, null);
148+
return;
149+
}
150+
try {
151+
camera.setExposureMode(result, mode);
152+
} catch (Exception e) {
153+
handleException(e, result);
154+
}
155+
break;
156+
}
157+
case "setExposurePoint":
158+
{
159+
Boolean reset = call.argument("reset");
160+
Double x = null;
161+
Double y = null;
162+
if (reset == null || !reset) {
163+
x = call.argument("x");
164+
y = call.argument("y");
165+
}
166+
try {
167+
camera.setExposurePoint(result, x, y);
168+
} catch (Exception e) {
169+
handleException(e, result);
170+
}
171+
break;
172+
}
173+
case "getMinExposureOffset":
174+
{
175+
try {
176+
result.success(camera.getMinExposureOffset());
177+
} catch (Exception e) {
178+
handleException(e, result);
179+
}
180+
break;
181+
}
182+
case "getMaxExposureOffset":
183+
{
184+
try {
185+
result.success(camera.getMaxExposureOffset());
186+
} catch (Exception e) {
187+
handleException(e, result);
188+
}
189+
break;
190+
}
191+
case "getExposureOffsetStepSize":
192+
{
193+
try {
194+
result.success(camera.getExposureOffsetStepSize());
195+
} catch (Exception e) {
196+
handleException(e, result);
197+
}
198+
break;
199+
}
200+
case "setExposureOffset":
201+
{
202+
try {
203+
camera.setExposureOffset(result, call.argument("offset"));
204+
} catch (Exception e) {
205+
handleException(e, result);
206+
}
207+
break;
208+
}
141209
case "startImageStream":
142210
{
143211
try {

packages/camera/camera/android/src/main/java/io/flutter/plugins/camera/PictureCaptureRequest.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ class PictureCaptureRequest {
77

88
enum State {
99
idle,
10-
awaitingPreCapture,
10+
focusing,
11+
preCapture,
12+
waitingPreCaptureReady,
1113
capturing,
1214
finished,
1315
error,
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package io.flutter.plugins.camera.types;
2+
3+
// Mirrors exposure_mode.dart
4+
public enum ExposureMode {
5+
auto("auto"),
6+
locked("locked");
7+
8+
private final String strValue;
9+
10+
ExposureMode(String strValue) {
11+
this.strValue = strValue;
12+
}
13+
14+
public static ExposureMode getValueForString(String modeStr) {
15+
for (ExposureMode value : values()) {
16+
if (value.strValue.equals(modeStr)) return value;
17+
}
18+
return null;
19+
}
20+
21+
@Override
22+
public String toString() {
23+
return strValue;
24+
}
25+
}

packages/camera/camera/android/src/main/java/io/flutter/plugins/camera/types/FlashMode.java

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,26 @@
22

33
// Mirrors flash_mode.dart
44
public enum FlashMode {
5-
off,
6-
auto,
7-
always,
8-
torch;
5+
off("off"),
6+
auto("auto"),
7+
always("always"),
8+
torch("torch");
9+
10+
private final String strValue;
11+
12+
FlashMode(String strValue) {
13+
this.strValue = strValue;
14+
}
915

1016
public static FlashMode getValueForString(String modeStr) {
11-
try {
12-
return valueOf(modeStr);
13-
} catch (IllegalArgumentException | NullPointerException e) {
14-
return null;
17+
for (FlashMode value : values()) {
18+
if (value.strValue.equals(modeStr)) return value;
1519
}
20+
return null;
21+
}
22+
23+
@Override
24+
public String toString() {
25+
return strValue;
1626
}
1727
}

packages/camera/camera/android/src/test/java/io/flutter/plugins/camera/DartMessengerTest.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,14 +58,16 @@ public void sendCameraErrorEvent_includesErrorDescriptions() {
5858

5959
@Test
6060
public void sendCameraInitializedEvent_includesPreviewSize() {
61-
dartMessenger.sendCameraInitializedEvent(0, 0);
61+
dartMessenger.sendCameraInitializedEvent(0, 0, ExposureMode.auto, true);
6262

6363
List<ByteBuffer> sentMessages = fakeBinaryMessenger.getMessages();
6464
assertEquals(1, sentMessages.size());
6565
MethodCall call = decodeSentMessage(sentMessages.get(0));
6666
assertEquals("initialized", call.method);
6767
assertEquals(0, (double) call.argument("previewWidth"), 0);
6868
assertEquals(0, (double) call.argument("previewHeight"), 0);
69+
assertEquals("ExposureMode auto", call.argument("exposureMode"), "auto");
70+
assertEquals("exposurePointSupported", call.argument("exposurePointSupported"), true);
6971
}
7072

7173
@Test

packages/camera/camera/android/src/test/java/io/flutter/plugins/camera/PictureCaptureRequestTest.java

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,15 @@ public void state_is_idle_by_default() {
2020
@Test
2121
public void setState_sets_state() {
2222
PictureCaptureRequest req = new PictureCaptureRequest(null);
23-
req.setState(PictureCaptureRequest.State.awaitingPreCapture);
23+
req.setState(PictureCaptureRequest.State.focusing);
24+
assertEquals("State is focusing", req.getState(), PictureCaptureRequest.State.focusing);
25+
req.setState(PictureCaptureRequest.State.preCapture);
26+
assertEquals("State is preCapture", req.getState(), PictureCaptureRequest.State.preCapture);
27+
req.setState(PictureCaptureRequest.State.waitingPreCaptureReady);
2428
assertEquals(
25-
"State is awaitingPreCapture",
29+
"State is waitingPreCaptureReady",
2630
req.getState(),
27-
PictureCaptureRequest.State.awaitingPreCapture);
31+
PictureCaptureRequest.State.waitingPreCaptureReady);
2832
req.setState(PictureCaptureRequest.State.capturing);
2933
assertEquals(
3034
"State is awaitingPreCapture", req.getState(), PictureCaptureRequest.State.capturing);
@@ -49,7 +53,7 @@ public void isFinished_is_true_When_state_is_finished_or_error() {
4953
// Test false states
5054
req.setState(PictureCaptureRequest.State.idle);
5155
assertFalse(req.isFinished());
52-
req.setState(PictureCaptureRequest.State.awaitingPreCapture);
56+
req.setState(PictureCaptureRequest.State.preCapture);
5357
assertFalse(req.isFinished());
5458
req.setState(PictureCaptureRequest.State.capturing);
5559
assertFalse(req.isFinished());
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package io.flutter.plugins.camera.types;
2+
3+
import static org.junit.Assert.assertEquals;
4+
5+
import org.junit.Test;
6+
7+
public class ExposureModeTest {
8+
9+
@Test
10+
public void getValueForString_returns_correct_values() {
11+
assertEquals(
12+
"Returns ExposureMode.auto for 'auto'",
13+
ExposureMode.getValueForString("auto"),
14+
ExposureMode.auto);
15+
assertEquals(
16+
"Returns ExposureMode.locked for 'locked'",
17+
ExposureMode.getValueForString("locked"),
18+
ExposureMode.locked);
19+
}
20+
21+
@Test
22+
public void getValueForString_returns_null_for_nonexistant_value() {
23+
assertEquals(
24+
"Returns null for 'nonexistant'", ExposureMode.getValueForString("nonexistant"), null);
25+
}
26+
27+
@Test
28+
public void toString_returns_correct_value() {
29+
assertEquals("Returns 'auto' for ExposureMode.auto", ExposureMode.auto.toString(), "auto");
30+
assertEquals(
31+
"Returns 'locked' for ExposureMode.locked", ExposureMode.locked.toString(), "locked");
32+
}
33+
}

packages/camera/camera/android/src/test/java/io/flutter/plugins/camera/types/FlashModeTest.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,12 @@ public void getValueForString_returns_null_for_nonexistant_value() {
2727
assertEquals(
2828
"Returns null for 'nonexistant'", FlashMode.getValueForString("nonexistant"), null);
2929
}
30+
31+
@Test
32+
public void toString_returns_correct_value() {
33+
assertEquals("Returns 'off' for FlashMode.off", FlashMode.off.toString(), "off");
34+
assertEquals("Returns 'auto' for FlashMode.auto", FlashMode.auto.toString(), "auto");
35+
assertEquals("Returns 'always' for FlashMode.always", FlashMode.always.toString(), "always");
36+
assertEquals("Returns 'torch' for FlashMode.torch", FlashMode.torch.toString(), "torch");
37+
}
3038
}

0 commit comments

Comments
 (0)