Skip to content

Commit ca3da1b

Browse files
[camera_android] Convert calls from native to dart side to Pigeon. (#7857)
Part of the effort to transition to typesafe implementations for platform calls. Android analog to #6568 Part of flutter/flutter#117905 ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] page, which explains my responsibilities. - [x] I read and followed the [relevant style guides] and ran the auto-formatter. (Unlike the flutter/flutter repo, the flutter/packages repo does use `dart format`.) - [ ] I signed the [CLA]. - [x] The title of the PR starts with the name of the package surrounded by square brackets, e.g. `[shared_preferences]` - [x] I [linked to at least one issue that this PR fixes] in the description above. - [x] I updated `pubspec.yaml` with an appropriate new version according to the [pub versioning philosophy], or this PR is [exempt from version changes]. - [x] I updated `CHANGELOG.md` to add a description of the change, [following repository CHANGELOG style], or this PR is [exempt from CHANGELOG changes]. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. <!-- Links --> [Contributor Guide]: https://github.com/flutter/packages/blob/main/CONTRIBUTING.md [Tree Hygiene]: https://github.com/flutter/flutter/blob/master/docs/contributing/Tree-hygiene.md [relevant style guides]: https://github.com/flutter/packages/blob/main/CONTRIBUTING.md#style [CLA]: https://cla.developers.google.com/ [Discord]: https://github.com/flutter/flutter/blob/master/docs/contributing/Chat.md [linked to at least one issue that this PR fixes]: https://github.com/flutter/flutter/blob/master/docs/contributing/Tree-hygiene.md#overview [pub versioning philosophy]: https://dart.dev/tools/pub/versioning [exempt from version changes]: https://github.com/flutter/flutter/blob/master/docs/ecosystem/contributing/README.md#version [following repository CHANGELOG style]: https://github.com/flutter/flutter/blob/master/docs/ecosystem/contributing/README.md#changelog-style [exempt from CHANGELOG changes]: https://github.com/flutter/flutter/blob/master/docs/ecosystem/contributing/README.md#changelog [test-exempt]: https://github.com/flutter/flutter/blob/master/docs/contributing/Tree-hygiene.md#tests
1 parent c4d8010 commit ca3da1b

File tree

14 files changed

+1203
-356
lines changed

14 files changed

+1203
-356
lines changed

packages/camera/camera_android/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 0.10.9+14
2+
3+
* Converts native to Dart platform calls to Pigeon.
4+
15
## 0.10.9+13
26

37
* Converts `getAvailableCameras` to Pigeon.

packages/camera/camera_android/android/src/main/java/io/flutter/plugins/camera/CameraUtils.java

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
import android.hardware.camera2.CameraMetadata;
1313
import androidx.annotation.NonNull;
1414
import io.flutter.embedding.engine.systemchannels.PlatformChannel;
15+
import io.flutter.plugins.camera.features.autofocus.FocusMode;
16+
import io.flutter.plugins.camera.features.exposurelock.ExposureMode;
1517
import java.util.ArrayList;
1618
import java.util.List;
1719

@@ -143,4 +145,62 @@ public static List<Messages.PlatformCameraDescription> getAvailableCameras(
143145
}
144146
return cameras;
145147
}
148+
149+
/**
150+
* Converts a DeviceOrientation from the systemchannels package to a PlatformDeviceOrientation
151+
* from Pigeon.
152+
*
153+
* @param orientation A DeviceOrientation.
154+
* @return The corresponding PlatformDeviceOrientation.
155+
*/
156+
@NonNull
157+
public static Messages.PlatformDeviceOrientation orientationToPigeon(
158+
@NonNull PlatformChannel.DeviceOrientation orientation) {
159+
switch (orientation) {
160+
case PORTRAIT_UP:
161+
return Messages.PlatformDeviceOrientation.PORTRAIT_UP;
162+
case PORTRAIT_DOWN:
163+
return Messages.PlatformDeviceOrientation.PORTRAIT_DOWN;
164+
case LANDSCAPE_LEFT:
165+
return Messages.PlatformDeviceOrientation.LANDSCAPE_LEFT;
166+
case LANDSCAPE_RIGHT:
167+
return Messages.PlatformDeviceOrientation.LANDSCAPE_RIGHT;
168+
}
169+
return Messages.PlatformDeviceOrientation.PORTRAIT_UP;
170+
}
171+
172+
/**
173+
* Converts a FocusMode from the autofocus package to a PlatformFocusMode from Pigeon.
174+
*
175+
* @param focusMode A FocusMode.
176+
* @return The corresponding PlatformFocusMode.
177+
*/
178+
@NonNull
179+
public static Messages.PlatformFocusMode focusModeToPigeon(@NonNull FocusMode focusMode) {
180+
switch (focusMode) {
181+
case auto:
182+
return Messages.PlatformFocusMode.AUTO;
183+
case locked:
184+
return Messages.PlatformFocusMode.LOCKED;
185+
}
186+
return Messages.PlatformFocusMode.AUTO;
187+
}
188+
189+
/**
190+
* Converts an ExposureMode from the exposurelock package to a PlatformExposureMode from Pigeon.
191+
*
192+
* @param exposureMode An ExposureMode.
193+
* @return The corresponding PlatformExposureMode.
194+
*/
195+
@NonNull
196+
public static Messages.PlatformExposureMode exposureModeToPigeon(
197+
@NonNull ExposureMode exposureMode) {
198+
switch (exposureMode) {
199+
case auto:
200+
return Messages.PlatformExposureMode.AUTO;
201+
case locked:
202+
return Messages.PlatformExposureMode.LOCKED;
203+
}
204+
return Messages.PlatformExposureMode.AUTO;
205+
}
146206
}

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

Lines changed: 35 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -5,69 +5,36 @@
55
package io.flutter.plugins.camera;
66

77
import android.os.Handler;
8-
import android.text.TextUtils;
98
import androidx.annotation.NonNull;
109
import androidx.annotation.Nullable;
1110
import io.flutter.embedding.engine.systemchannels.PlatformChannel;
12-
import io.flutter.plugin.common.BinaryMessenger;
1311
import io.flutter.plugin.common.MethodChannel;
1412
import io.flutter.plugins.camera.features.autofocus.FocusMode;
1513
import io.flutter.plugins.camera.features.exposurelock.ExposureMode;
16-
import java.util.HashMap;
17-
import java.util.Map;
1814

1915
/** Utility class that facilitates communication to the Flutter client */
2016
public class DartMessenger {
2117
@NonNull private final Handler handler;
22-
@Nullable MethodChannel cameraChannel;
23-
@Nullable MethodChannel deviceChannel;
24-
25-
/** Specifies the different device related message types. */
26-
enum DeviceEventType {
27-
/** Indicates the device's orientation has changed. */
28-
ORIENTATION_CHANGED("orientation_changed");
29-
final String method;
30-
31-
DeviceEventType(String method) {
32-
this.method = method;
33-
}
34-
}
35-
36-
/** Specifies the different camera related message types. */
37-
enum CameraEventType {
38-
/** Indicates that an error occurred while interacting with the camera. */
39-
ERROR("error"),
40-
/** Indicates that the camera is closing. */
41-
CLOSING("camera_closing"),
42-
/** Indicates that the camera is initialized. */
43-
INITIALIZED("initialized");
44-
45-
final String method;
46-
47-
/**
48-
* Converts the supplied method name to the matching {@link CameraEventType}.
49-
*
50-
* @param method name to be converted into a {@link CameraEventType}.
51-
*/
52-
CameraEventType(String method) {
53-
this.method = method;
54-
}
55-
}
18+
Messages.CameraGlobalEventApi globalEventApi;
19+
Messages.CameraEventApi eventApi;
5620

5721
/**
5822
* Creates a new instance of the {@link DartMessenger} class.
5923
*
60-
* @param messenger is the {@link BinaryMessenger} that is used to communicate with Flutter.
61-
* @param cameraId identifies the camera which is the source of the communication.
6224
* @param handler the handler used to manage the thread's message queue. This should always be a
6325
* handler managing the main thread since communication with Flutter should always happen on
6426
* the main thread. The handler is mainly supplied so it will be easier test this class.
27+
* @param globalEventApi the API used to consume calls to dart that are not tied to a specific
28+
* camera instance.
29+
* @param eventApi the API used to consume calls to dart that are tied to this specific camera.
6530
*/
66-
DartMessenger(BinaryMessenger messenger, long cameraId, @NonNull Handler handler) {
67-
cameraChannel =
68-
new MethodChannel(messenger, "plugins.flutter.io/camera_android/camera" + cameraId);
69-
deviceChannel = new MethodChannel(messenger, "plugins.flutter.io/camera_android/fromPlatform");
31+
DartMessenger(
32+
@NonNull Handler handler,
33+
Messages.CameraGlobalEventApi globalEventApi,
34+
Messages.CameraEventApi eventApi) {
7035
this.handler = handler;
36+
this.globalEventApi = globalEventApi;
37+
this.eventApi = eventApi;
7138
}
7239

7340
/**
@@ -77,13 +44,10 @@ enum CameraEventType {
7744
*/
7845
public void sendDeviceOrientationChangeEvent(
7946
@NonNull PlatformChannel.DeviceOrientation orientation) {
80-
this.send(
81-
DeviceEventType.ORIENTATION_CHANGED,
82-
new HashMap<String, Object>() {
83-
{
84-
put("orientation", CameraUtils.serializeDeviceOrientation(orientation));
85-
}
86-
});
47+
handler.post(
48+
() ->
49+
globalEventApi.deviceOrientationChanged(
50+
CameraUtils.orientationToPigeon(orientation), new NoOpVoidResult()));
8751
}
8852

8953
/**
@@ -109,69 +73,39 @@ void sendCameraInitializedEvent(
10973
assert (focusMode != null);
11074
assert (exposurePointSupported != null);
11175
assert (focusPointSupported != null);
112-
this.send(
113-
CameraEventType.INITIALIZED,
114-
new HashMap<String, Object>() {
115-
{
116-
put("previewWidth", previewWidth.doubleValue());
117-
put("previewHeight", previewHeight.doubleValue());
118-
put("exposureMode", exposureMode.toString());
119-
put("focusMode", focusMode.toString());
120-
put("exposurePointSupported", exposurePointSupported);
121-
put("focusPointSupported", focusPointSupported);
122-
}
123-
});
76+
handler.post(
77+
() ->
78+
eventApi.initialized(
79+
new Messages.PlatformCameraState.Builder()
80+
.setPreviewSize(
81+
new Messages.PlatformSize.Builder()
82+
.setWidth(previewWidth.doubleValue())
83+
.setHeight(previewHeight.doubleValue())
84+
.build())
85+
.setExposurePointSupported(exposurePointSupported)
86+
.setFocusPointSupported(focusPointSupported)
87+
.setExposureMode(CameraUtils.exposureModeToPigeon(exposureMode))
88+
.setFocusMode(CameraUtils.focusModeToPigeon(focusMode))
89+
.build(),
90+
new NoOpVoidResult()));
12491
}
12592

12693
/** Sends a message to the Flutter client informing that the camera is closing. */
12794
void sendCameraClosingEvent() {
128-
send(CameraEventType.CLOSING);
95+
handler.post(() -> eventApi.closed(new NoOpVoidResult()));
12996
}
13097

98+
// TODO(schectman): Make `description` non-null, see
99+
// https://github.com/flutter/flutter/issues/156729
131100
/**
132101
* Sends a message to the Flutter client informing that an error occurred while interacting with
133102
* the camera.
134103
*
135104
* @param description contains details regarding the error that occurred.
136105
*/
137106
void sendCameraErrorEvent(@Nullable String description) {
138-
this.send(
139-
CameraEventType.ERROR,
140-
new HashMap<String, Object>() {
141-
{
142-
if (!TextUtils.isEmpty(description)) put("description", description);
143-
}
144-
});
145-
}
146-
147-
private void send(CameraEventType eventType) {
148-
send(eventType, new HashMap<>());
149-
}
150-
151-
private void send(CameraEventType eventType, Map<String, Object> args) {
152-
if (cameraChannel == null) {
153-
return;
154-
}
155-
156-
handler.post(
157-
new Runnable() {
158-
@Override
159-
public void run() {
160-
cameraChannel.invokeMethod(eventType.method, args);
161-
}
162-
});
163-
}
164-
165-
private void send(DeviceEventType eventType) {
166-
send(eventType, new HashMap<>());
167-
}
168-
169-
private void send(DeviceEventType eventType, Map<String, Object> args) {
170-
if (deviceChannel == null) {
171-
return;
172-
}
173-
174-
handler.post(() -> deviceChannel.invokeMethod(eventType.method, args));
107+
String errorMessage = (description == null) ? "" : description;
108+
handler.post(() -> eventApi.error(errorMessage, new NoOpVoidResult()));
175109
}
176110

177111
/**

0 commit comments

Comments
 (0)