Skip to content

Commit d3bfaff

Browse files
[camera_android] Begin conversion to Pigeon (flutter#7755)
Convert one method to use Pigeon to setup the backbone of future conversions. Android analog of flutter/packages#6553 Part of 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 44e7d73 commit d3bfaff

File tree

14 files changed

+628
-103
lines changed

14 files changed

+628
-103
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+13
2+
3+
* Converts `getAvailableCameras` to Pigeon.
4+
15
## 0.10.9+12
26

37
* Updates Java compatibility version to 11.

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

Lines changed: 31 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,7 @@
1313
import androidx.annotation.NonNull;
1414
import io.flutter.embedding.engine.systemchannels.PlatformChannel;
1515
import java.util.ArrayList;
16-
import java.util.HashMap;
1716
import java.util.List;
18-
import java.util.Map;
1917

2018
/** Provides various utilities for camera. */
2119
public final class CameraUtils {
@@ -85,6 +83,27 @@ static PlatformChannel.DeviceOrientation deserializeDeviceOrientation(String ori
8583
}
8684
}
8785

86+
/**
87+
* Converts a raw integer to a PlatformCameraLensDirection enum.
88+
*
89+
* @param lensDirection One of CameraMetadata.LENS_FACING_FRONT, LENS_FACING_BACK, or
90+
* LENS_FACING_EXTERNAL.
91+
* @return One of Messages.PlatformCameraLensDirection.FRONT, BACK, or EXTERNAL.
92+
*/
93+
static Messages.PlatformCameraLensDirection lensDirectionFromInteger(int lensDirection) {
94+
switch (lensDirection) {
95+
case CameraMetadata.LENS_FACING_FRONT:
96+
return Messages.PlatformCameraLensDirection.FRONT;
97+
case CameraMetadata.LENS_FACING_BACK:
98+
return Messages.PlatformCameraLensDirection.BACK;
99+
case CameraMetadata.LENS_FACING_EXTERNAL:
100+
return Messages.PlatformCameraLensDirection.EXTERNAL;
101+
}
102+
// CameraMetadata is defined in the Android API. In the event that a new value is added, a
103+
// default fallback value of FRONT is returned.
104+
return Messages.PlatformCameraLensDirection.FRONT;
105+
}
106+
88107
/**
89108
* Gets all the available cameras for the device.
90109
*
@@ -93,11 +112,11 @@ static PlatformChannel.DeviceOrientation deserializeDeviceOrientation(String ori
93112
* @throws CameraAccessException when the camera could not be accessed.
94113
*/
95114
@NonNull
96-
public static List<Map<String, Object>> getAvailableCameras(@NonNull Activity activity)
97-
throws CameraAccessException {
115+
public static List<Messages.PlatformCameraDescription> getAvailableCameras(
116+
@NonNull Activity activity) throws CameraAccessException {
98117
CameraManager cameraManager = (CameraManager) activity.getSystemService(Context.CAMERA_SERVICE);
99118
String[] cameraNames = cameraManager.getCameraIdList();
100-
List<Map<String, Object>> cameras = new ArrayList<>();
119+
List<Messages.PlatformCameraDescription> cameras = new ArrayList<>();
101120
for (String cameraName : cameraNames) {
102121
int cameraId;
103122
try {
@@ -109,24 +128,17 @@ public static List<Map<String, Object>> getAvailableCameras(@NonNull Activity ac
109128
continue;
110129
}
111130

112-
HashMap<String, Object> details = new HashMap<>();
113131
CameraCharacteristics characteristics = cameraManager.getCameraCharacteristics(cameraName);
114-
details.put("name", cameraName);
115132
int sensorOrientation = characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
116-
details.put("sensorOrientation", sensorOrientation);
117133

118134
int lensFacing = characteristics.get(CameraCharacteristics.LENS_FACING);
119-
switch (lensFacing) {
120-
case CameraMetadata.LENS_FACING_FRONT:
121-
details.put("lensFacing", "front");
122-
break;
123-
case CameraMetadata.LENS_FACING_BACK:
124-
details.put("lensFacing", "back");
125-
break;
126-
case CameraMetadata.LENS_FACING_EXTERNAL:
127-
details.put("lensFacing", "external");
128-
break;
129-
}
135+
Messages.PlatformCameraLensDirection lensDirection = lensDirectionFromInteger(lensFacing);
136+
Messages.PlatformCameraDescription details =
137+
new Messages.PlatformCameraDescription.Builder()
138+
.setName(cameraName)
139+
.setSensorOrientation((long) sensorOrientation)
140+
.setLensDirection(lensDirection)
141+
.build();
130142
cameras.add(details);
131143
}
132144
return cameras;
Lines changed: 280 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,280 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
// Autogenerated from Pigeon (v22.4.1), do not edit directly.
5+
// See also: https://pub.dev/packages/pigeon
6+
7+
package io.flutter.plugins.camera;
8+
9+
import static java.lang.annotation.ElementType.METHOD;
10+
import static java.lang.annotation.RetentionPolicy.CLASS;
11+
12+
import android.util.Log;
13+
import androidx.annotation.NonNull;
14+
import androidx.annotation.Nullable;
15+
import io.flutter.plugin.common.BasicMessageChannel;
16+
import io.flutter.plugin.common.BinaryMessenger;
17+
import io.flutter.plugin.common.MessageCodec;
18+
import io.flutter.plugin.common.StandardMessageCodec;
19+
import java.io.ByteArrayOutputStream;
20+
import java.lang.annotation.Retention;
21+
import java.lang.annotation.Target;
22+
import java.nio.ByteBuffer;
23+
import java.util.ArrayList;
24+
import java.util.List;
25+
import java.util.Objects;
26+
27+
/** Generated class from Pigeon. */
28+
@SuppressWarnings({"unused", "unchecked", "CodeBlock2Expr", "RedundantSuppression", "serial"})
29+
public class Messages {
30+
31+
/** Error class for passing custom error details to Flutter via a thrown PlatformException. */
32+
public static class FlutterError extends RuntimeException {
33+
34+
/** The error code. */
35+
public final String code;
36+
37+
/** The error details. Must be a datatype supported by the api codec. */
38+
public final Object details;
39+
40+
public FlutterError(@NonNull String code, @Nullable String message, @Nullable Object details) {
41+
super(message);
42+
this.code = code;
43+
this.details = details;
44+
}
45+
}
46+
47+
@NonNull
48+
protected static ArrayList<Object> wrapError(@NonNull Throwable exception) {
49+
ArrayList<Object> errorList = new ArrayList<>(3);
50+
if (exception instanceof FlutterError) {
51+
FlutterError error = (FlutterError) exception;
52+
errorList.add(error.code);
53+
errorList.add(error.getMessage());
54+
errorList.add(error.details);
55+
} else {
56+
errorList.add(exception.toString());
57+
errorList.add(exception.getClass().getSimpleName());
58+
errorList.add(
59+
"Cause: " + exception.getCause() + ", Stacktrace: " + Log.getStackTraceString(exception));
60+
}
61+
return errorList;
62+
}
63+
64+
@Target(METHOD)
65+
@Retention(CLASS)
66+
@interface CanIgnoreReturnValue {}
67+
68+
public enum PlatformCameraLensDirection {
69+
FRONT(0),
70+
BACK(1),
71+
EXTERNAL(2);
72+
73+
final int index;
74+
75+
PlatformCameraLensDirection(final int index) {
76+
this.index = index;
77+
}
78+
}
79+
80+
/** Generated class from Pigeon that represents data sent in messages. */
81+
public static final class PlatformCameraDescription {
82+
private @NonNull String name;
83+
84+
public @NonNull String getName() {
85+
return name;
86+
}
87+
88+
public void setName(@NonNull String setterArg) {
89+
if (setterArg == null) {
90+
throw new IllegalStateException("Nonnull field \"name\" is null.");
91+
}
92+
this.name = setterArg;
93+
}
94+
95+
private @NonNull PlatformCameraLensDirection lensDirection;
96+
97+
public @NonNull PlatformCameraLensDirection getLensDirection() {
98+
return lensDirection;
99+
}
100+
101+
public void setLensDirection(@NonNull PlatformCameraLensDirection setterArg) {
102+
if (setterArg == null) {
103+
throw new IllegalStateException("Nonnull field \"lensDirection\" is null.");
104+
}
105+
this.lensDirection = setterArg;
106+
}
107+
108+
private @NonNull Long sensorOrientation;
109+
110+
public @NonNull Long getSensorOrientation() {
111+
return sensorOrientation;
112+
}
113+
114+
public void setSensorOrientation(@NonNull Long setterArg) {
115+
if (setterArg == null) {
116+
throw new IllegalStateException("Nonnull field \"sensorOrientation\" is null.");
117+
}
118+
this.sensorOrientation = setterArg;
119+
}
120+
121+
/** Constructor is non-public to enforce null safety; use Builder. */
122+
PlatformCameraDescription() {}
123+
124+
@Override
125+
public boolean equals(Object o) {
126+
if (this == o) {
127+
return true;
128+
}
129+
if (o == null || getClass() != o.getClass()) {
130+
return false;
131+
}
132+
PlatformCameraDescription that = (PlatformCameraDescription) o;
133+
return name.equals(that.name)
134+
&& lensDirection.equals(that.lensDirection)
135+
&& sensorOrientation.equals(that.sensorOrientation);
136+
}
137+
138+
@Override
139+
public int hashCode() {
140+
return Objects.hash(name, lensDirection, sensorOrientation);
141+
}
142+
143+
public static final class Builder {
144+
145+
private @Nullable String name;
146+
147+
@CanIgnoreReturnValue
148+
public @NonNull Builder setName(@NonNull String setterArg) {
149+
this.name = setterArg;
150+
return this;
151+
}
152+
153+
private @Nullable PlatformCameraLensDirection lensDirection;
154+
155+
@CanIgnoreReturnValue
156+
public @NonNull Builder setLensDirection(@NonNull PlatformCameraLensDirection setterArg) {
157+
this.lensDirection = setterArg;
158+
return this;
159+
}
160+
161+
private @Nullable Long sensorOrientation;
162+
163+
@CanIgnoreReturnValue
164+
public @NonNull Builder setSensorOrientation(@NonNull Long setterArg) {
165+
this.sensorOrientation = setterArg;
166+
return this;
167+
}
168+
169+
public @NonNull PlatformCameraDescription build() {
170+
PlatformCameraDescription pigeonReturn = new PlatformCameraDescription();
171+
pigeonReturn.setName(name);
172+
pigeonReturn.setLensDirection(lensDirection);
173+
pigeonReturn.setSensorOrientation(sensorOrientation);
174+
return pigeonReturn;
175+
}
176+
}
177+
178+
@NonNull
179+
ArrayList<Object> toList() {
180+
ArrayList<Object> toListResult = new ArrayList<>(3);
181+
toListResult.add(name);
182+
toListResult.add(lensDirection);
183+
toListResult.add(sensorOrientation);
184+
return toListResult;
185+
}
186+
187+
static @NonNull PlatformCameraDescription fromList(@NonNull ArrayList<Object> pigeonVar_list) {
188+
PlatformCameraDescription pigeonResult = new PlatformCameraDescription();
189+
Object name = pigeonVar_list.get(0);
190+
pigeonResult.setName((String) name);
191+
Object lensDirection = pigeonVar_list.get(1);
192+
pigeonResult.setLensDirection((PlatformCameraLensDirection) lensDirection);
193+
Object sensorOrientation = pigeonVar_list.get(2);
194+
pigeonResult.setSensorOrientation((Long) sensorOrientation);
195+
return pigeonResult;
196+
}
197+
}
198+
199+
private static class PigeonCodec extends StandardMessageCodec {
200+
public static final PigeonCodec INSTANCE = new PigeonCodec();
201+
202+
private PigeonCodec() {}
203+
204+
@Override
205+
protected Object readValueOfType(byte type, @NonNull ByteBuffer buffer) {
206+
switch (type) {
207+
case (byte) 129:
208+
{
209+
Object value = readValue(buffer);
210+
return value == null
211+
? null
212+
: PlatformCameraLensDirection.values()[((Long) value).intValue()];
213+
}
214+
case (byte) 130:
215+
return PlatformCameraDescription.fromList((ArrayList<Object>) readValue(buffer));
216+
default:
217+
return super.readValueOfType(type, buffer);
218+
}
219+
}
220+
221+
@Override
222+
protected void writeValue(@NonNull ByteArrayOutputStream stream, Object value) {
223+
if (value instanceof PlatformCameraLensDirection) {
224+
stream.write(129);
225+
writeValue(stream, value == null ? null : ((PlatformCameraLensDirection) value).index);
226+
} else if (value instanceof PlatformCameraDescription) {
227+
stream.write(130);
228+
writeValue(stream, ((PlatformCameraDescription) value).toList());
229+
} else {
230+
super.writeValue(stream, value);
231+
}
232+
}
233+
}
234+
235+
/** Generated interface from Pigeon that represents a handler of messages from Flutter. */
236+
public interface CameraApi {
237+
238+
@NonNull
239+
List<PlatformCameraDescription> getAvailableCameras();
240+
241+
/** The codec used by CameraApi. */
242+
static @NonNull MessageCodec<Object> getCodec() {
243+
return PigeonCodec.INSTANCE;
244+
}
245+
/** Sets up an instance of `CameraApi` to handle messages through the `binaryMessenger`. */
246+
static void setUp(@NonNull BinaryMessenger binaryMessenger, @Nullable CameraApi api) {
247+
setUp(binaryMessenger, "", api);
248+
}
249+
250+
static void setUp(
251+
@NonNull BinaryMessenger binaryMessenger,
252+
@NonNull String messageChannelSuffix,
253+
@Nullable CameraApi api) {
254+
messageChannelSuffix = messageChannelSuffix.isEmpty() ? "" : "." + messageChannelSuffix;
255+
{
256+
BasicMessageChannel<Object> channel =
257+
new BasicMessageChannel<>(
258+
binaryMessenger,
259+
"dev.flutter.pigeon.camera_android.CameraApi.getAvailableCameras"
260+
+ messageChannelSuffix,
261+
getCodec());
262+
if (api != null) {
263+
channel.setMessageHandler(
264+
(message, reply) -> {
265+
ArrayList<Object> wrapped = new ArrayList<>();
266+
try {
267+
List<PlatformCameraDescription> output = api.getAvailableCameras();
268+
wrapped.add(0, output);
269+
} catch (Throwable exception) {
270+
wrapped = wrapError(exception);
271+
}
272+
reply.reply(wrapped);
273+
});
274+
} else {
275+
channel.setMessageHandler(null);
276+
}
277+
}
278+
}
279+
}
280+
}

0 commit comments

Comments
 (0)