From 9ce9abc23968f9155ea2dff4ad7cfdf872f9fb24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?O=C4=9Fulcan=20=C3=87elik?= Date: Sat, 11 Jul 2020 20:36:10 +0300 Subject: [PATCH 1/9] test jpeg implementation with example --- packages/camera/android/build.gradle | 1 + .../gradle/wrapper/gradle-wrapper.properties | 6 + .../io/flutter/plugins/camera/Camera.java | 18 +- .../plugins/camera/MethodCallHandlerImpl.java | 286 +++++++++--------- packages/camera/example/lib/main.dart | 39 ++- packages/camera/example/pubspec.yaml | 1 + packages/camera/lib/camera.dart | 17 ++ packages/camera/lib/camera_image.dart | 14 +- 8 files changed, 222 insertions(+), 160 deletions(-) create mode 100644 packages/camera/android/gradle/wrapper/gradle-wrapper.properties diff --git a/packages/camera/android/build.gradle b/packages/camera/android/build.gradle index 95f5a22cfb6d..1a1180a7b115 100644 --- a/packages/camera/android/build.gradle +++ b/packages/camera/android/build.gradle @@ -46,4 +46,5 @@ android { dependencies { testImplementation 'junit:junit:4.12' +// implementation files('C:\\src\\flutter\\bin\\cache\\artifacts\\engine\\android-x64\\flutter.jar') } diff --git a/packages/camera/android/gradle/wrapper/gradle-wrapper.properties b/packages/camera/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 000000000000..a129e49781e7 --- /dev/null +++ b/packages/camera/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Sat Jul 11 18:16:50 EET 2020 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https://services.gradle.org/distributions/gradle-4.10.1-all.zip diff --git a/packages/camera/android/src/main/java/io/flutter/plugins/camera/Camera.java b/packages/camera/android/src/main/java/io/flutter/plugins/camera/Camera.java index 0fcda278d836..1b15866d5de7 100644 --- a/packages/camera/android/src/main/java/io/flutter/plugins/camera/Camera.java +++ b/packages/camera/android/src/main/java/io/flutter/plugins/camera/Camera.java @@ -49,6 +49,7 @@ public class Camera { private final Size captureSize; private final Size previewSize; private final boolean enableAudio; + private final int imageFormat; private CameraDevice cameraDevice; private CameraCaptureSession cameraCaptureSession; @@ -77,7 +78,8 @@ public Camera( final DartMessenger dartMessenger, final String cameraName, final String resolutionPreset, - final boolean enableAudio) + final boolean enableAudio, + final int imageFormat) throws CameraAccessException { if (activity == null) { throw new IllegalStateException("No activity available!"); @@ -85,6 +87,11 @@ public Camera( this.cameraName = cameraName; this.enableAudio = enableAudio; + if (imageFormat != 256 || imageFormat != 35) { + this.imageFormat = 35; + }else{ + this.imageFormat = imageFormat; + } this.flutterTexture = flutterTexture; this.dartMessenger = dartMessenger; this.cameraManager = (CameraManager) activity.getSystemService(Context.CAMERA_SERVICE); @@ -114,6 +121,7 @@ public void onOrientationChanged(int i) { CameraUtils.getBestAvailableCamcorderProfileForResolutionPreset(cameraName, preset); captureSize = new Size(recordingProfile.videoFrameWidth, recordingProfile.videoFrameHeight); previewSize = computeBestPreviewSize(cameraName, preset); + } private void prepareMediaRecorder(String outputFilePath) throws IOException { @@ -146,9 +154,11 @@ public void open(@NonNull final Result result) throws CameraAccessException { captureSize.getWidth(), captureSize.getHeight(), ImageFormat.JPEG, 2); // Used to steam image byte data to dart side. - imageStreamReader = - ImageReader.newInstance( - previewSize.getWidth(), previewSize.getHeight(), ImageFormat.YUV_420_888, 2); + imageStreamReader = + ImageReader.newInstance( + previewSize.getWidth(), previewSize.getHeight(), this.imageFormat, 2); + + cameraManager.openCamera( cameraName, diff --git a/packages/camera/android/src/main/java/io/flutter/plugins/camera/MethodCallHandlerImpl.java b/packages/camera/android/src/main/java/io/flutter/plugins/camera/MethodCallHandlerImpl.java index cb58d19a9a02..a563ba683dd3 100644 --- a/packages/camera/android/src/main/java/io/flutter/plugins/camera/MethodCallHandlerImpl.java +++ b/packages/camera/android/src/main/java/io/flutter/plugins/camera/MethodCallHandlerImpl.java @@ -2,8 +2,10 @@ import android.app.Activity; import android.hardware.camera2.CameraAccessException; + import androidx.annotation.NonNull; import androidx.annotation.Nullable; + import io.flutter.plugin.common.BinaryMessenger; import io.flutter.plugin.common.EventChannel; import io.flutter.plugin.common.MethodCall; @@ -13,162 +15,156 @@ import io.flutter.view.TextureRegistry; final class MethodCallHandlerImpl implements MethodChannel.MethodCallHandler { - private final Activity activity; - private final BinaryMessenger messenger; - private final CameraPermissions cameraPermissions; - private final PermissionsRegistry permissionsRegistry; - private final TextureRegistry textureRegistry; - private final MethodChannel methodChannel; - private final EventChannel imageStreamChannel; - private @Nullable Camera camera; + private final Activity activity; + private final BinaryMessenger messenger; + private final CameraPermissions cameraPermissions; + private final PermissionsRegistry permissionsRegistry; + private final TextureRegistry textureRegistry; + private final MethodChannel methodChannel; + private final EventChannel imageStreamChannel; + private @Nullable + Camera camera; - MethodCallHandlerImpl( - Activity activity, - BinaryMessenger messenger, - CameraPermissions cameraPermissions, - PermissionsRegistry permissionsAdder, - TextureRegistry textureRegistry) { - this.activity = activity; - this.messenger = messenger; - this.cameraPermissions = cameraPermissions; - this.permissionsRegistry = permissionsAdder; - this.textureRegistry = textureRegistry; + MethodCallHandlerImpl( + Activity activity, + BinaryMessenger messenger, + CameraPermissions cameraPermissions, + PermissionsRegistry permissionsAdder, + TextureRegistry textureRegistry) { + this.activity = activity; + this.messenger = messenger; + this.cameraPermissions = cameraPermissions; + this.permissionsRegistry = permissionsAdder; + this.textureRegistry = textureRegistry; - methodChannel = new MethodChannel(messenger, "plugins.flutter.io/camera"); - imageStreamChannel = new EventChannel(messenger, "plugins.flutter.io/camera/imageStream"); - methodChannel.setMethodCallHandler(this); - } + methodChannel = new MethodChannel(messenger, "plugins.flutter.io/camera"); + imageStreamChannel = new EventChannel(messenger, "plugins.flutter.io/camera/imageStream"); + methodChannel.setMethodCallHandler(this); + } - @Override - public void onMethodCall(@NonNull MethodCall call, @NonNull final Result result) { - switch (call.method) { - case "availableCameras": - try { - result.success(CameraUtils.getAvailableCameras(activity)); - } catch (Exception e) { - handleException(e, result); - } - break; - case "initialize": - { - if (camera != null) { - camera.close(); - } - cameraPermissions.requestPermissions( - activity, - permissionsRegistry, - call.argument("enableAudio"), - (String errCode, String errDesc) -> { - if (errCode == null) { - try { - instantiateCamera(call, result); - } catch (Exception e) { + @Override + public void onMethodCall(@NonNull MethodCall call, @NonNull final Result result) { + switch (call.method) { + case "availableCameras": + try { + result.success(CameraUtils.getAvailableCameras(activity)); + } catch (Exception e) { handleException(e, result); - } - } else { - result.error(errCode, errDesc, null); } - }); + break; + case "initialize": { + if (camera != null) { + camera.close(); + } + cameraPermissions.requestPermissions( + activity, + permissionsRegistry, + call.argument("enableAudio"), + (String errCode, String errDesc) -> { + if (errCode == null) { + try { + instantiateCamera(call, result); + } catch (Exception e) { + handleException(e, result); + } + } else { + result.error(errCode, errDesc, null); + } + }); - break; - } - case "takePicture": - { - camera.takePicture(call.argument("path"), result); - break; - } - case "prepareForVideoRecording": - { - // This optimization is not required for Android. - result.success(null); - break; - } - case "startVideoRecording": - { - camera.startVideoRecording(call.argument("filePath"), result); - break; - } - case "stopVideoRecording": - { - camera.stopVideoRecording(result); - break; - } - case "pauseVideoRecording": - { - camera.pauseVideoRecording(result); - break; - } - case "resumeVideoRecording": - { - camera.resumeVideoRecording(result); - break; - } - case "startImageStream": - { - try { - camera.startPreviewWithImageStream(imageStreamChannel); - result.success(null); - } catch (Exception e) { - handleException(e, result); - } - break; - } - case "stopImageStream": - { - try { - camera.startPreview(); - result.success(null); - } catch (Exception e) { - handleException(e, result); - } - break; - } - case "dispose": - { - if (camera != null) { - camera.dispose(); - } - result.success(null); - break; + break; + } + case "takePicture": { + camera.takePicture(call.argument("path"), result); + break; + } + case "prepareForVideoRecording": { + // This optimization is not required for Android. + result.success(null); + break; + } + case "startVideoRecording": { + camera.startVideoRecording(call.argument("filePath"), result); + break; + } + case "stopVideoRecording": { + camera.stopVideoRecording(result); + break; + } + case "pauseVideoRecording": { + camera.pauseVideoRecording(result); + break; + } + case "resumeVideoRecording": { + camera.resumeVideoRecording(result); + break; + } + case "startImageStream": { + try { + call.arguments(); + camera.startPreviewWithImageStream(imageStreamChannel); + result.success(null); + } catch (Exception e) { + handleException(e, result); + } + break; + } + case "stopImageStream": { + try { + camera.startPreview(); + result.success(null); + } catch (Exception e) { + handleException(e, result); + } + break; + } + case "dispose": { + if (camera != null) { + camera.dispose(); + } + result.success(null); + break; + } + default: + result.notImplemented(); + break; } - default: - result.notImplemented(); - break; } - } - - void stopListening() { - methodChannel.setMethodCallHandler(null); - } - private void instantiateCamera(MethodCall call, Result result) throws CameraAccessException { - String cameraName = call.argument("cameraName"); - String resolutionPreset = call.argument("resolutionPreset"); - boolean enableAudio = call.argument("enableAudio"); - TextureRegistry.SurfaceTextureEntry flutterSurfaceTexture = - textureRegistry.createSurfaceTexture(); - DartMessenger dartMessenger = new DartMessenger(messenger, flutterSurfaceTexture.id()); - camera = - new Camera( - activity, - flutterSurfaceTexture, - dartMessenger, - cameraName, - resolutionPreset, - enableAudio); + void stopListening() { + methodChannel.setMethodCallHandler(null); + } - camera.open(result); - } + 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 androidFormatCode = call.argument("androidFormatCode"); + TextureRegistry.SurfaceTextureEntry flutterSurfaceTexture = + textureRegistry.createSurfaceTexture(); + DartMessenger dartMessenger = new DartMessenger(messenger, flutterSurfaceTexture.id()); + camera = + new Camera( + activity, + flutterSurfaceTexture, + dartMessenger, + cameraName, + resolutionPreset, + enableAudio, + androidFormatCode); - // We move catching CameraAccessException out of onMethodCall because it causes a crash - // on plugin registration for sdks incompatible with Camera2 (< 21). We want this plugin to - // to be able to compile with <21 sdks for apps that want the camera and support earlier version. - @SuppressWarnings("ConstantConditions") - private void handleException(Exception exception, Result result) { - if (exception instanceof CameraAccessException) { - result.error("CameraAccess", exception.getMessage(), null); + camera.open(result); } - throw (RuntimeException) exception; - } + // We move catching CameraAccessException out of onMethodCall because it causes a crash + // on plugin registration for sdks incompatible with Camera2 (< 21). We want this plugin to + // to be able to compile with <21 sdks for apps that want the camera and support earlier version. + @SuppressWarnings("ConstantConditions") + private void handleException(Exception exception, Result result) { + if (exception instanceof CameraAccessException) { + result.error("CameraAccess", exception.getMessage(), null); + } + + throw (RuntimeException) exception; + } } diff --git a/packages/camera/example/lib/main.dart b/packages/camera/example/lib/main.dart index ce8d37457123..978e84e81257 100644 --- a/packages/camera/example/lib/main.dart +++ b/packages/camera/example/lib/main.dart @@ -6,12 +6,17 @@ import 'dart:async'; import 'dart:io'; +implimport 'dart:typed_data'; import 'package:camera/camera.dart'; +import 'package:flutter/foundation.dart'; + import 'package:flutter/material.dart'; import 'package:path_provider/path_provider.dart'; import 'package:video_player/video_player.dart'; +import 'package:image/image.dart' as imglib; + class CameraExampleHome extends StatefulWidget { @override _CameraExampleHomeState createState() { @@ -43,6 +48,7 @@ class _CameraExampleHomeState extends State VideoPlayerController videoController; VoidCallback videoPlayerListener; bool enableAudio = true; + CameraImage _cameraImage; @override void initState() { @@ -118,9 +124,20 @@ class _CameraExampleHomeState extends State ); } + Uint8List concatenatePlanes(List planes) { + WriteBuffer allBytes = WriteBuffer(); + + planes.forEach((Plane plane) => allBytes.putUint8List(plane.bytes)); + + return allBytes.done().buffer.asUint8List(); + } + /// Display the preview from the camera (or a message if the preview is not available). Widget _cameraPreviewWidget() { - if (controller == null || !controller.value.isInitialized) { + if (_cameraImage != null) print(_cameraImage.format.raw); + if (controller == null || + !controller.value.isInitialized || + _cameraImage == null) { return const Text( 'Tap a camera', style: TextStyle( @@ -130,10 +147,15 @@ class _CameraExampleHomeState extends State ), ); } else { - return AspectRatio( - aspectRatio: controller.value.aspectRatio, - child: CameraPreview(controller), + return Image.memory( + imglib.encodeJpg(imglib.copyRotate( + imglib.decodeJpg(_cameraImage.planes[0].bytes), 90)), + gaplessPlayback: true, ); + // return AspectRatio( + // aspectRatio: controller.value.aspectRatio, + // child: CameraPreview(controller), + // ); } } @@ -279,11 +301,8 @@ class _CameraExampleHomeState extends State if (controller != null) { await controller.dispose(); } - controller = CameraController( - cameraDescription, - ResolutionPreset.medium, - enableAudio: enableAudio, - ); + controller = CameraController(cameraDescription, ResolutionPreset.medium, + enableAudio: enableAudio, androidFormatCode: 256); // If the controller is updated then update the UI. controller.addListener(() { @@ -295,6 +314,8 @@ class _CameraExampleHomeState extends State try { await controller.initialize(); + await controller + .startImageStream((image) => setState(() => _cameraImage = image)); } on CameraException catch (e) { _showCameraException(e); } diff --git a/packages/camera/example/pubspec.yaml b/packages/camera/example/pubspec.yaml index a066129eebd4..17b400e5bdda 100644 --- a/packages/camera/example/pubspec.yaml +++ b/packages/camera/example/pubspec.yaml @@ -9,6 +9,7 @@ dependencies: sdk: flutter video_player: ^0.10.0 e2e: "^0.2.0" + image: ^2.1.14 dev_dependencies: flutter_test: diff --git a/packages/camera/lib/camera.dart b/packages/camera/lib/camera.dart index ce9fd9430dde..f3f93b04eca0 100644 --- a/packages/camera/lib/camera.dart +++ b/packages/camera/lib/camera.dart @@ -4,6 +4,7 @@ import 'dart:async'; import 'dart:typed_data'; +import 'dart:io' show Platform; import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; @@ -245,6 +246,7 @@ class CameraController extends ValueNotifier { this.description, this.resolutionPreset, { this.enableAudio = true, + this.androidFormatCode = 35, }) : super(const CameraValue.uninitialized()); final CameraDescription description; @@ -253,6 +255,16 @@ class CameraController extends ValueNotifier { /// Whether to include audio when recording a video. final bool enableAudio; + /// Define streaming image format for Android. + /// + /// Default is `35` which is `YUV_420_888` on Android. See: + /// https://developer.android.com/reference/android/graphics/ImageFormat#YUV_420_888 + /// + /// Other option is `256` which is `JPEG`. When you specified the JPEG option, + /// [CameraImage] will have only one plane which is encoded JPEG bytes. + /// https://developer.android.com/reference/android/graphics/ImageFormat#JPEG + final int androidFormatCode; + int _textureId; bool _isDisposed = false; StreamSubscription _eventSubscription; @@ -266,6 +278,10 @@ class CameraController extends ValueNotifier { if (_isDisposed) { return Future.value(); } + if (androidFormatCode != 256 && androidFormatCode != 35) { + throw CameraException('Unknown Image Format Code.', + 'CameraController initialized with an unknown Image Format Code.'); + } try { _creatingCompleter = Completer(); final Map reply = @@ -275,6 +291,7 @@ class CameraController extends ValueNotifier { 'cameraName': description.name, 'resolutionPreset': serializeResolutionPreset(resolutionPreset), 'enableAudio': enableAudio, + 'androidFormatCode': androidFormatCode, }, ); _textureId = reply['textureId']; diff --git a/packages/camera/lib/camera_image.dart b/packages/camera/lib/camera_image.dart index cebc14873f52..27029150e61b 100644 --- a/packages/camera/lib/camera_image.dart +++ b/packages/camera/lib/camera_image.dart @@ -61,7 +61,15 @@ enum ImageFormatGroup { /// /// On iOS, this is `kCVPixelFormatType_32BGRA`. See /// https://developer.apple.com/documentation/corevideo/1563591-pixel_format_identifiers/kcvpixelformattype_32bgra?language=objc + /// bgra8888, + + /// 32-big RGB image encoded into JPEG bytes. + /// + /// On Android, this is `android.graphics.ImageFormat.JPEG`. See + /// https://developer.android.com/reference/android/graphics/ImageFormat#FLEX_RGBA_8888 + /// + jpeg } /// Describes how pixels are represented in an image. @@ -84,8 +92,10 @@ class ImageFormat { ImageFormatGroup _asImageFormatGroup(dynamic rawFormat) { if (defaultTargetPlatform == TargetPlatform.android) { // android.graphics.ImageFormat.YUV_420_888 - if (rawFormat == 35) { - return ImageFormatGroup.yuv420; + if (rawFormat == 256) { + return ImageFormatGroup.jpeg; + } else if (rawFormat == 42) { + return ImageFormatGroup.bgra8888; } } From 20b25aaa458a1eb8e6d7c5199e0d224303050c2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?O=C4=9Fulcan=20=C3=87elik?= Date: Sat, 11 Jul 2020 20:41:41 +0300 Subject: [PATCH 2/9] prepration for pull request --- packages/camera/android/build.gradle | 1 - .../gradle/wrapper/gradle-wrapper.properties | 6 --- packages/camera/example/lib/main.dart | 39 +++++-------------- packages/camera/example/pubspec.yaml | 1 - 4 files changed, 9 insertions(+), 38 deletions(-) delete mode 100644 packages/camera/android/gradle/wrapper/gradle-wrapper.properties diff --git a/packages/camera/android/build.gradle b/packages/camera/android/build.gradle index 1a1180a7b115..95f5a22cfb6d 100644 --- a/packages/camera/android/build.gradle +++ b/packages/camera/android/build.gradle @@ -46,5 +46,4 @@ android { dependencies { testImplementation 'junit:junit:4.12' -// implementation files('C:\\src\\flutter\\bin\\cache\\artifacts\\engine\\android-x64\\flutter.jar') } diff --git a/packages/camera/android/gradle/wrapper/gradle-wrapper.properties b/packages/camera/android/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index a129e49781e7..000000000000 --- a/packages/camera/android/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,6 +0,0 @@ -#Sat Jul 11 18:16:50 EET 2020 -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists -distributionUrl=https://services.gradle.org/distributions/gradle-4.10.1-all.zip diff --git a/packages/camera/example/lib/main.dart b/packages/camera/example/lib/main.dart index 978e84e81257..ce8d37457123 100644 --- a/packages/camera/example/lib/main.dart +++ b/packages/camera/example/lib/main.dart @@ -6,17 +6,12 @@ import 'dart:async'; import 'dart:io'; -implimport 'dart:typed_data'; import 'package:camera/camera.dart'; -import 'package:flutter/foundation.dart'; - import 'package:flutter/material.dart'; import 'package:path_provider/path_provider.dart'; import 'package:video_player/video_player.dart'; -import 'package:image/image.dart' as imglib; - class CameraExampleHome extends StatefulWidget { @override _CameraExampleHomeState createState() { @@ -48,7 +43,6 @@ class _CameraExampleHomeState extends State VideoPlayerController videoController; VoidCallback videoPlayerListener; bool enableAudio = true; - CameraImage _cameraImage; @override void initState() { @@ -124,20 +118,9 @@ class _CameraExampleHomeState extends State ); } - Uint8List concatenatePlanes(List planes) { - WriteBuffer allBytes = WriteBuffer(); - - planes.forEach((Plane plane) => allBytes.putUint8List(plane.bytes)); - - return allBytes.done().buffer.asUint8List(); - } - /// Display the preview from the camera (or a message if the preview is not available). Widget _cameraPreviewWidget() { - if (_cameraImage != null) print(_cameraImage.format.raw); - if (controller == null || - !controller.value.isInitialized || - _cameraImage == null) { + if (controller == null || !controller.value.isInitialized) { return const Text( 'Tap a camera', style: TextStyle( @@ -147,15 +130,10 @@ class _CameraExampleHomeState extends State ), ); } else { - return Image.memory( - imglib.encodeJpg(imglib.copyRotate( - imglib.decodeJpg(_cameraImage.planes[0].bytes), 90)), - gaplessPlayback: true, + return AspectRatio( + aspectRatio: controller.value.aspectRatio, + child: CameraPreview(controller), ); - // return AspectRatio( - // aspectRatio: controller.value.aspectRatio, - // child: CameraPreview(controller), - // ); } } @@ -301,8 +279,11 @@ class _CameraExampleHomeState extends State if (controller != null) { await controller.dispose(); } - controller = CameraController(cameraDescription, ResolutionPreset.medium, - enableAudio: enableAudio, androidFormatCode: 256); + controller = CameraController( + cameraDescription, + ResolutionPreset.medium, + enableAudio: enableAudio, + ); // If the controller is updated then update the UI. controller.addListener(() { @@ -314,8 +295,6 @@ class _CameraExampleHomeState extends State try { await controller.initialize(); - await controller - .startImageStream((image) => setState(() => _cameraImage = image)); } on CameraException catch (e) { _showCameraException(e); } diff --git a/packages/camera/example/pubspec.yaml b/packages/camera/example/pubspec.yaml index 17b400e5bdda..a066129eebd4 100644 --- a/packages/camera/example/pubspec.yaml +++ b/packages/camera/example/pubspec.yaml @@ -9,7 +9,6 @@ dependencies: sdk: flutter video_player: ^0.10.0 e2e: "^0.2.0" - image: ^2.1.14 dev_dependencies: flutter_test: From 2ae8275cc99eeec6962305d713213e29ea00dbc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?O=C4=9Fulcan=20=C3=87elik?= Date: Sat, 11 Jul 2020 20:54:50 +0300 Subject: [PATCH 3/9] darty analyze pass --- packages/camera/lib/camera.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/camera/lib/camera.dart b/packages/camera/lib/camera.dart index f3f93b04eca0..7084339d8665 100644 --- a/packages/camera/lib/camera.dart +++ b/packages/camera/lib/camera.dart @@ -4,7 +4,6 @@ import 'dart:async'; import 'dart:typed_data'; -import 'dart:io' show Platform; import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; From 5812ec7449661ae517dd3a72c92b78b7108ef820 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?O=C4=9Fulcan=20=C3=87elik?= Date: Sat, 11 Jul 2020 21:13:00 +0300 Subject: [PATCH 4/9] preparation for pr --- packages/camera/CHANGELOG.md | 171 ++++++++++++++++++----------------- packages/camera/pubspec.yaml | 2 +- 2 files changed, 89 insertions(+), 84 deletions(-) diff --git a/packages/camera/CHANGELOG.md b/packages/camera/CHANGELOG.md index 43e5f463604c..d18296402ef4 100644 --- a/packages/camera/CHANGELOG.md +++ b/packages/camera/CHANGELOG.md @@ -1,185 +1,188 @@ +## 0.5.9+4 + +- Android: Added support for JPEG callback in image stream. + ## 0.5.8+3 -* Fix bug in usage example in README.md +- Fix bug in usage example in README.md ## 0.5.8+2 -* Post-v2 embedding cleanups. +- Post-v2 embedding cleanups. ## 0.5.8+1 -* Update lower bound of dart dependency to 2.1.0. +- Update lower bound of dart dependency to 2.1.0. ## 0.5.8 -* Remove Android dependencies fallback. -* Require Flutter SDK 1.12.13+hotfix.5 or greater. +- Remove Android dependencies fallback. +- Require Flutter SDK 1.12.13+hotfix.5 or greater. ## 0.5.7+5 -* Replace deprecated `getFlutterEngine` call on Android. +- Replace deprecated `getFlutterEngine` call on Android. ## 0.5.7+4 -* Add `pedantic` to dev_dependency. +- Add `pedantic` to dev_dependency. ## 0.5.7+3 -* Fix an Android crash when permissions are requested multiple times. +- Fix an Android crash when permissions are requested multiple times. ## 0.5.7+2 -* Remove the deprecated `author:` field from pubspec.yaml -* Migrate the plugin to the pubspec platforms manifest. -* Require Flutter SDK 1.10.0 or greater. +- Remove the deprecated `author:` field from pubspec.yaml +- Migrate the plugin to the pubspec platforms manifest. +- Require Flutter SDK 1.10.0 or greater. ## 0.5.7+1 -* Fix example null exception. +- Fix example null exception. ## 0.5.7 -* Fix unawaited futures. +- Fix unawaited futures. ## 0.5.6+4 -* Android: Use CameraDevice.TEMPLATE_RECORD to improve image streaming. +- Android: Use CameraDevice.TEMPLATE_RECORD to improve image streaming. ## 0.5.6+3 -* Remove AndroidX warning. +- Remove AndroidX warning. ## 0.5.6+2 -* Include lifecycle dependency as a compileOnly one on Android to resolve +- Include lifecycle dependency as a compileOnly one on Android to resolve potential version conflicts with other transitive libraries. ## 0.5.6+1 -* Android: Use android.arch.lifecycle instead of androidx.lifecycle:lifecycle in `build.gradle` to support apps that has not been migrated to AndroidX. +- Android: Use android.arch.lifecycle instead of androidx.lifecycle:lifecycle in `build.gradle` to support apps that has not been migrated to AndroidX. ## 0.5.6 -* Add support for the v2 Android embedding. This shouldn't affect existing +- Add support for the v2 Android embedding. This shouldn't affect existing functionality. ## 0.5.5+1 -* Fix event type check +- Fix event type check ## 0.5.5 -* Define clang modules for iOS. +- Define clang modules for iOS. ## 0.5.4+3 -* Update and migrate iOS example project. +- Update and migrate iOS example project. ## 0.5.4+2 -* Fix Android NullPointerException on devices with only front-facing camera. +- Fix Android NullPointerException on devices with only front-facing camera. ## 0.5.4+1 -* Fix Android pause and resume video crash when executing in APIs below 24. +- Fix Android pause and resume video crash when executing in APIs below 24. ## 0.5.4 -* Add feature to pause and resume video recording. +- Add feature to pause and resume video recording. ## 0.5.3+1 -* Fix too large request code for FragmentActivity users. +- 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. +- Added new quality presets. +- Now all quality presets can be used to control image capture quality. ## 0.5.2+2 -* Fix memory leak related to not unregistering stream handler in FlutterEventChannel when disposing camera. +- Fix memory leak related to not unregistering stream handler in FlutterEventChannel when disposing camera. ## 0.5.2+1 -* Fix bug that prevented video recording with audio. +- Fix bug that prevented video recording with audio. ## 0.5.2 -* Added capability to disable audio for the `CameraController`. (e.g. `CameraController(_, _, - enableAudio: false);`) +- Added capability to disable audio for the `CameraController`. (e.g. `CameraController(_, _, enableAudio: false);`) ## 0.5.1 -* Can now be compiled with earlier Android sdks below 21 when -`` has been added to the project -`AndroidManifest.xml`. For sdks below 21, the plugin won't be registered and calls to it will throw -a `MissingPluginException.` +- Can now be compiled with earlier Android sdks below 21 when + `` has been added to the project + `AndroidManifest.xml`. For sdks below 21, the plugin won't be registered and calls to it will throw + a `MissingPluginException.` ## 0.5.0 -* **Breaking Change** This plugin no longer handles closing and opening the camera on Android +- **Breaking Change** This plugin no longer handles closing and opening the camera on Android lifecycle changes. Please use `WidgetsBindingObserver` to control camera resources on lifecycle changes. See example project for example using `WidgetsBindingObserver`. ## 0.4.3+2 -* Bump the minimum Flutter version to 1.2.0. -* Add template type parameter to `invokeMethod` calls. +- Bump the minimum Flutter version to 1.2.0. +- Add template type parameter to `invokeMethod` calls. ## 0.4.3+1 -* Catch additional `Exception`s from Android and throw as `CameraException`s. +- Catch additional `Exception`s from Android and throw as `CameraException`s. ## 0.4.3 -* Add capability to prepare the capture session for video recording on iOS. +- Add capability to prepare the capture session for video recording on iOS. ## 0.4.2 -* Add sensor orientation value to `CameraDescription`. +- Add sensor orientation value to `CameraDescription`. ## 0.4.1 -* Camera methods are ran in a background thread on iOS. +- Camera methods are ran in a background thread on iOS. ## 0.4.0+3 -* Fixed a crash when the plugin is registered by a background FlutterView. +- Fixed a crash when the plugin is registered by a background FlutterView. ## 0.4.0+2 -* Fix orientation of captured photos when camera is used for the first time on Android. +- Fix orientation of captured photos when camera is used for the first time on Android. ## 0.4.0+1 -* Remove categories. +- Remove categories. ## 0.4.0 -* **Breaking Change** Change iOS image stream format to `ImageFormatGroup.bgra8888` from +- **Breaking Change** Change iOS image stream format to `ImageFormatGroup.bgra8888` from `ImageFormatGroup.yuv420`. ## 0.3.0+4 -* Fixed bug causing black screen on some Android devices. +- Fixed bug causing black screen on some Android devices. ## 0.3.0+3 -* Log a more detailed warning at build time about the previous AndroidX +- Log a more detailed warning at build time about the previous AndroidX migration. ## 0.3.0+2 -* Fix issue with calculating iOS image orientation in certain edge cases. +- Fix issue with calculating iOS image orientation in certain edge cases. ## 0.3.0+1 -* Remove initial method call invocation from static camera method. +- Remove initial method call invocation from static camera method. ## 0.3.0 -* **Breaking change**. Migrate from the deprecated original Android Support +- **Breaking change**. Migrate from the deprecated original Android Support Library to AndroidX. This shouldn't result in any functional changes, but it requires any Android apps using this plugin to [also migrate](https://developer.android.com/jetpack/androidx/migrate) if they're @@ -187,94 +190,96 @@ a `MissingPluginException.` ## 0.2.9+1 -* Fix a crash when failing to start preview. +- Fix a crash when failing to start preview. ## 0.2.9 -* Save photo orientation data on iOS. +- Save photo orientation data on iOS. ## 0.2.8 -* Add access to the image stream from Dart. -* Use `cameraController.startImageStream(listener)` to process the images. +- Add access to the image stream from Dart. +- Use `cameraController.startImageStream(listener)` to process the images. ## 0.2.7 -* Fix issue with crash when the physical device's orientation is unknown. +- Fix issue with crash when the physical device's orientation is unknown. ## 0.2.6 -* Update the camera to use the physical device's orientation instead of the UI +- Update the camera to use the physical device's orientation instead of the UI orientation on Android. ## 0.2.5 -* Fix preview and video size with satisfying conditions of multiple outputs. +- Fix preview and video size with satisfying conditions of multiple outputs. ## 0.2.4 -* Unregister the activity lifecycle callbacks when disposing the camera. +- Unregister the activity lifecycle callbacks when disposing the camera. ## 0.2.3 -* Added path_provider and video_player as dev dependencies because the example uses them. -* Updated example path_provider version to get Dart 2 support. +- Added path_provider and video_player as dev dependencies because the example uses them. +- Updated example path_provider version to get Dart 2 support. ## 0.2.2 -* iOS image capture is done in high quality (full camera size) +- iOS image capture is done in high quality (full camera size) ## 0.2.1 -* Updated Gradle tooling to match Android Studio 3.1.2. +- Updated Gradle tooling to match Android Studio 3.1.2. ## 0.2.0 -* Added support for video recording. -* Changed the example app to add video recording. +- Added support for video recording. +- Changed the example app to add video recording. A lot of **breaking changes** in this version: Getter changes: - - Removed `isStarted` - - Renamed `initialized` to `isInitialized` - - Added `isRecordingVideo` + +- Removed `isStarted` +- Renamed `initialized` to `isInitialized` +- Added `isRecordingVideo` Method changes: - - Renamed `capture` to `takePicture` - - Removed `start` (the preview starts automatically when `initialize` is called) - - Added `startVideoRecording(String filePath)` - - Removed `stop` (the preview stops automatically when `dispose` is called) - - Added `stopVideoRecording` + +- Renamed `capture` to `takePicture` +- Removed `start` (the preview starts automatically when `initialize` is called) +- Added `startVideoRecording(String filePath)` +- Removed `stop` (the preview stops automatically when `dispose` is called) +- Added `stopVideoRecording` ## 0.1.2 -* Fix Dart 2 runtime errors. +- Fix Dart 2 runtime errors. ## 0.1.1 -* Fix Dart 2 runtime error. +- Fix Dart 2 runtime error. ## 0.1.0 -* **Breaking change**. Set SDK constraints to match the Flutter beta release. +- **Breaking change**. Set SDK constraints to match the Flutter beta release. ## 0.0.4 -* Revert regression of `CameraController.capture()` introduced in v. 0.0.3. +- Revert regression of `CameraController.capture()` introduced in v. 0.0.3. ## 0.0.3 -* Improved resource cleanup on Android. Avoids crash on Activity restart. -* Made the Future returned by `CameraController.dispose()` and `CameraController.capture()` actually complete on +- Improved resource cleanup on Android. Avoids crash on Activity restart. +- Made the Future returned by `CameraController.dispose()` and `CameraController.capture()` actually complete on Android. ## 0.0.2 -* Simplified and upgraded Android project template to Android SDK 27. -* Moved Android package to io.flutter.plugins. -* Fixed warnings from the Dart 2.0 analyzer. +- Simplified and upgraded Android project template to Android SDK 27. +- Moved Android package to io.flutter.plugins. +- Fixed warnings from the Dart 2.0 analyzer. ## 0.0.1 -* Initial release +- Initial release diff --git a/packages/camera/pubspec.yaml b/packages/camera/pubspec.yaml index a1ce42370191..a93c016e1f10 100644 --- a/packages/camera/pubspec.yaml +++ b/packages/camera/pubspec.yaml @@ -2,7 +2,7 @@ name: camera description: A Flutter plugin for getting information about and controlling the camera on Android and iOS. Supports previewing the camera feed, capturing images, capturing video, and streaming image buffers to dart. -version: 0.5.8+3 +version: 0.5.8+4 homepage: https://github.com/flutter/plugins/tree/master/packages/camera From 4cab8a853687ddd432b92fd909dfaee285dc8c41 Mon Sep 17 00:00:00 2001 From: Ogulcan Celik Date: Sat, 11 Jul 2020 21:43:32 +0300 Subject: [PATCH 5/9] pub format analyze and test passed --- .../io/flutter/plugins/camera/Camera.java | 11 +- .../plugins/camera/MethodCallHandlerImpl.java | 289 +++++++++--------- 2 files changed, 152 insertions(+), 148 deletions(-) diff --git a/packages/camera/android/src/main/java/io/flutter/plugins/camera/Camera.java b/packages/camera/android/src/main/java/io/flutter/plugins/camera/Camera.java index 1b15866d5de7..1459788b4580 100644 --- a/packages/camera/android/src/main/java/io/flutter/plugins/camera/Camera.java +++ b/packages/camera/android/src/main/java/io/flutter/plugins/camera/Camera.java @@ -89,7 +89,7 @@ public Camera( this.enableAudio = enableAudio; if (imageFormat != 256 || imageFormat != 35) { this.imageFormat = 35; - }else{ + } else { this.imageFormat = imageFormat; } this.flutterTexture = flutterTexture; @@ -121,7 +121,6 @@ public void onOrientationChanged(int i) { CameraUtils.getBestAvailableCamcorderProfileForResolutionPreset(cameraName, preset); captureSize = new Size(recordingProfile.videoFrameWidth, recordingProfile.videoFrameHeight); previewSize = computeBestPreviewSize(cameraName, preset); - } private void prepareMediaRecorder(String outputFilePath) throws IOException { @@ -154,11 +153,9 @@ public void open(@NonNull final Result result) throws CameraAccessException { captureSize.getWidth(), captureSize.getHeight(), ImageFormat.JPEG, 2); // Used to steam image byte data to dart side. - imageStreamReader = - ImageReader.newInstance( - previewSize.getWidth(), previewSize.getHeight(), this.imageFormat, 2); - - + imageStreamReader = + ImageReader.newInstance( + previewSize.getWidth(), previewSize.getHeight(), this.imageFormat, 2); cameraManager.openCamera( cameraName, diff --git a/packages/camera/android/src/main/java/io/flutter/plugins/camera/MethodCallHandlerImpl.java b/packages/camera/android/src/main/java/io/flutter/plugins/camera/MethodCallHandlerImpl.java index a563ba683dd3..41a3730eb0bc 100644 --- a/packages/camera/android/src/main/java/io/flutter/plugins/camera/MethodCallHandlerImpl.java +++ b/packages/camera/android/src/main/java/io/flutter/plugins/camera/MethodCallHandlerImpl.java @@ -2,10 +2,8 @@ import android.app.Activity; import android.hardware.camera2.CameraAccessException; - import androidx.annotation.NonNull; import androidx.annotation.Nullable; - import io.flutter.plugin.common.BinaryMessenger; import io.flutter.plugin.common.EventChannel; import io.flutter.plugin.common.MethodCall; @@ -15,156 +13,165 @@ import io.flutter.view.TextureRegistry; final class MethodCallHandlerImpl implements MethodChannel.MethodCallHandler { - private final Activity activity; - private final BinaryMessenger messenger; - private final CameraPermissions cameraPermissions; - private final PermissionsRegistry permissionsRegistry; - private final TextureRegistry textureRegistry; - private final MethodChannel methodChannel; - private final EventChannel imageStreamChannel; - private @Nullable - Camera camera; + private final Activity activity; + private final BinaryMessenger messenger; + private final CameraPermissions cameraPermissions; + private final PermissionsRegistry permissionsRegistry; + private final TextureRegistry textureRegistry; + private final MethodChannel methodChannel; + private final EventChannel imageStreamChannel; + private @Nullable Camera camera; - MethodCallHandlerImpl( - Activity activity, - BinaryMessenger messenger, - CameraPermissions cameraPermissions, - PermissionsRegistry permissionsAdder, - TextureRegistry textureRegistry) { - this.activity = activity; - this.messenger = messenger; - this.cameraPermissions = cameraPermissions; - this.permissionsRegistry = permissionsAdder; - this.textureRegistry = textureRegistry; + MethodCallHandlerImpl( + Activity activity, + BinaryMessenger messenger, + CameraPermissions cameraPermissions, + PermissionsRegistry permissionsAdder, + TextureRegistry textureRegistry) { + this.activity = activity; + this.messenger = messenger; + this.cameraPermissions = cameraPermissions; + this.permissionsRegistry = permissionsAdder; + this.textureRegistry = textureRegistry; - methodChannel = new MethodChannel(messenger, "plugins.flutter.io/camera"); - imageStreamChannel = new EventChannel(messenger, "plugins.flutter.io/camera/imageStream"); - methodChannel.setMethodCallHandler(this); - } + methodChannel = new MethodChannel(messenger, "plugins.flutter.io/camera"); + imageStreamChannel = new EventChannel(messenger, "plugins.flutter.io/camera/imageStream"); + methodChannel.setMethodCallHandler(this); + } - @Override - public void onMethodCall(@NonNull MethodCall call, @NonNull final Result result) { - switch (call.method) { - case "availableCameras": - try { - result.success(CameraUtils.getAvailableCameras(activity)); - } catch (Exception e) { + @Override + public void onMethodCall(@NonNull MethodCall call, @NonNull final Result result) { + switch (call.method) { + case "availableCameras": + try { + result.success(CameraUtils.getAvailableCameras(activity)); + } catch (Exception e) { + handleException(e, result); + } + break; + case "initialize": + { + if (camera != null) { + camera.close(); + } + cameraPermissions.requestPermissions( + activity, + permissionsRegistry, + call.argument("enableAudio"), + (String errCode, String errDesc) -> { + if (errCode == null) { + try { + instantiateCamera(call, result); + } catch (Exception e) { handleException(e, result); + } + } else { + result.error(errCode, errDesc, null); } - break; - case "initialize": { - if (camera != null) { - camera.close(); - } - cameraPermissions.requestPermissions( - activity, - permissionsRegistry, - call.argument("enableAudio"), - (String errCode, String errDesc) -> { - if (errCode == null) { - try { - instantiateCamera(call, result); - } catch (Exception e) { - handleException(e, result); - } - } else { - result.error(errCode, errDesc, null); - } - }); + }); - break; - } - case "takePicture": { - camera.takePicture(call.argument("path"), result); - break; - } - case "prepareForVideoRecording": { - // This optimization is not required for Android. - result.success(null); - break; - } - case "startVideoRecording": { - camera.startVideoRecording(call.argument("filePath"), result); - break; - } - case "stopVideoRecording": { - camera.stopVideoRecording(result); - break; - } - case "pauseVideoRecording": { - camera.pauseVideoRecording(result); - break; - } - case "resumeVideoRecording": { - camera.resumeVideoRecording(result); - break; - } - case "startImageStream": { - try { - call.arguments(); - camera.startPreviewWithImageStream(imageStreamChannel); - result.success(null); - } catch (Exception e) { - handleException(e, result); - } - break; - } - case "stopImageStream": { - try { - camera.startPreview(); - result.success(null); - } catch (Exception e) { - handleException(e, result); - } - break; - } - case "dispose": { - if (camera != null) { - camera.dispose(); - } - result.success(null); - break; - } - default: - result.notImplemented(); - break; + break; } + case "takePicture": + { + camera.takePicture(call.argument("path"), result); + break; + } + case "prepareForVideoRecording": + { + // This optimization is not required for Android. + result.success(null); + break; + } + case "startVideoRecording": + { + camera.startVideoRecording(call.argument("filePath"), result); + break; + } + case "stopVideoRecording": + { + camera.stopVideoRecording(result); + break; + } + case "pauseVideoRecording": + { + camera.pauseVideoRecording(result); + break; + } + case "resumeVideoRecording": + { + camera.resumeVideoRecording(result); + break; + } + case "startImageStream": + { + try { + call.arguments(); + camera.startPreviewWithImageStream(imageStreamChannel); + result.success(null); + } catch (Exception e) { + handleException(e, result); + } + break; + } + case "stopImageStream": + { + try { + camera.startPreview(); + result.success(null); + } catch (Exception e) { + handleException(e, result); + } + break; + } + case "dispose": + { + if (camera != null) { + camera.dispose(); + } + result.success(null); + break; + } + default: + result.notImplemented(); + break; } + } - void stopListening() { - methodChannel.setMethodCallHandler(null); - } - - 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 androidFormatCode = call.argument("androidFormatCode"); - TextureRegistry.SurfaceTextureEntry flutterSurfaceTexture = - textureRegistry.createSurfaceTexture(); - DartMessenger dartMessenger = new DartMessenger(messenger, flutterSurfaceTexture.id()); - camera = - new Camera( - activity, - flutterSurfaceTexture, - dartMessenger, - cameraName, - resolutionPreset, - enableAudio, - androidFormatCode); + void stopListening() { + methodChannel.setMethodCallHandler(null); + } - camera.open(result); - } + 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 androidFormatCode = call.argument("androidFormatCode"); + TextureRegistry.SurfaceTextureEntry flutterSurfaceTexture = + textureRegistry.createSurfaceTexture(); + DartMessenger dartMessenger = new DartMessenger(messenger, flutterSurfaceTexture.id()); + camera = + new Camera( + activity, + flutterSurfaceTexture, + dartMessenger, + cameraName, + resolutionPreset, + enableAudio, + androidFormatCode); - // We move catching CameraAccessException out of onMethodCall because it causes a crash - // on plugin registration for sdks incompatible with Camera2 (< 21). We want this plugin to - // to be able to compile with <21 sdks for apps that want the camera and support earlier version. - @SuppressWarnings("ConstantConditions") - private void handleException(Exception exception, Result result) { - if (exception instanceof CameraAccessException) { - result.error("CameraAccess", exception.getMessage(), null); - } + camera.open(result); + } - throw (RuntimeException) exception; + // We move catching CameraAccessException out of onMethodCall because it causes a crash + // on plugin registration for sdks incompatible with Camera2 (< 21). We want this plugin to + // to be able to compile with <21 sdks for apps that want the camera and support earlier version. + @SuppressWarnings("ConstantConditions") + private void handleException(Exception exception, Result result) { + if (exception instanceof CameraAccessException) { + result.error("CameraAccess", exception.getMessage(), null); } + + throw (RuntimeException) exception; + } } From ef43d515577a831479938177a5d74a94a7fbd83c Mon Sep 17 00:00:00 2001 From: Ogulcan Celik Date: Sat, 11 Jul 2020 21:48:06 +0300 Subject: [PATCH 6/9] authors md update --- AUTHORS | 1 + 1 file changed, 1 insertion(+) diff --git a/AUTHORS b/AUTHORS index 51345c9a3481..4adbbbce34a2 100644 --- a/AUTHORS +++ b/AUTHORS @@ -59,3 +59,4 @@ Kazuki Yamaguchi Eitan Schwartz Chris Rutkowski Juan Alvarez +Ogulcan Celik \ No newline at end of file From 4ea21dfaaa8c7f1c280e93e5f20e511da0c0358d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?O=C4=9Fulcan=20=C3=87elik?= Date: Sat, 11 Jul 2020 23:09:01 +0300 Subject: [PATCH 7/9] fixes for changelog --- packages/camera/CHANGELOG.md | 164 +++++++++++++++++------------------ 1 file changed, 82 insertions(+), 82 deletions(-) diff --git a/packages/camera/CHANGELOG.md b/packages/camera/CHANGELOG.md index d18296402ef4..08314bd38596 100644 --- a/packages/camera/CHANGELOG.md +++ b/packages/camera/CHANGELOG.md @@ -1,188 +1,188 @@ -## 0.5.9+4 +## 0.5.8+4 -- Android: Added support for JPEG callback in image stream. +* Android: Added support for JPEG callback in image stream. ## 0.5.8+3 -- Fix bug in usage example in README.md +* Fix bug in usage example in README.md ## 0.5.8+2 -- Post-v2 embedding cleanups. +* Post*v2 embedding cleanups. ## 0.5.8+1 -- Update lower bound of dart dependency to 2.1.0. +* Update lower bound of dart dependency to 2.1.0. ## 0.5.8 -- Remove Android dependencies fallback. -- Require Flutter SDK 1.12.13+hotfix.5 or greater. +* Remove Android dependencies fallback. +* Require Flutter SDK 1.12.13+hotfix.5 or greater. ## 0.5.7+5 -- Replace deprecated `getFlutterEngine` call on Android. +* Replace deprecated `getFlutterEngine` call on Android. ## 0.5.7+4 -- Add `pedantic` to dev_dependency. +* Add `pedantic` to dev_dependency. ## 0.5.7+3 -- Fix an Android crash when permissions are requested multiple times. +* Fix an Android crash when permissions are requested multiple times. ## 0.5.7+2 -- Remove the deprecated `author:` field from pubspec.yaml -- Migrate the plugin to the pubspec platforms manifest. -- Require Flutter SDK 1.10.0 or greater. +* Remove the deprecated `author:` field from pubspec.yaml +* Migrate the plugin to the pubspec platforms manifest. +* Require Flutter SDK 1.10.0 or greater. ## 0.5.7+1 -- Fix example null exception. +* Fix example null exception. ## 0.5.7 -- Fix unawaited futures. +* Fix unawaited futures. ## 0.5.6+4 -- Android: Use CameraDevice.TEMPLATE_RECORD to improve image streaming. +* Android: Use CameraDevice.TEMPLATE_RECORD to improve image streaming. ## 0.5.6+3 -- Remove AndroidX warning. +* Remove AndroidX warning. ## 0.5.6+2 -- Include lifecycle dependency as a compileOnly one on Android to resolve +* Include lifecycle dependency as a compileOnly one on Android to resolve potential version conflicts with other transitive libraries. ## 0.5.6+1 -- Android: Use android.arch.lifecycle instead of androidx.lifecycle:lifecycle in `build.gradle` to support apps that has not been migrated to AndroidX. +* Android: Use android.arch.lifecycle instead of androidx.lifecycle:lifecycle in `build.gradle` to support apps that has not been migrated to AndroidX. ## 0.5.6 -- Add support for the v2 Android embedding. This shouldn't affect existing +* Add support for the v2 Android embedding. This shouldn't affect existing functionality. ## 0.5.5+1 -- Fix event type check +* Fix event type check ## 0.5.5 -- Define clang modules for iOS. +* Define clang modules for iOS. ## 0.5.4+3 -- Update and migrate iOS example project. +* Update and migrate iOS example project. ## 0.5.4+2 -- Fix Android NullPointerException on devices with only front-facing camera. +* Fix Android NullPointerException on devices with only front*facing camera. ## 0.5.4+1 -- Fix Android pause and resume video crash when executing in APIs below 24. +* Fix Android pause and resume video crash when executing in APIs below 24. ## 0.5.4 -- Add feature to pause and resume video recording. +* Add feature to pause and resume video recording. ## 0.5.3+1 -- Fix too large request code for FragmentActivity users. +* 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. +* Added new quality presets. +* Now all quality presets can be used to control image capture quality. ## 0.5.2+2 -- Fix memory leak related to not unregistering stream handler in FlutterEventChannel when disposing camera. +* Fix memory leak related to not unregistering stream handler in FlutterEventChannel when disposing camera. ## 0.5.2+1 -- Fix bug that prevented video recording with audio. +* Fix bug that prevented video recording with audio. ## 0.5.2 -- Added capability to disable audio for the `CameraController`. (e.g. `CameraController(_, _, enableAudio: false);`) +* Added capability to disable audio for the `CameraController`. (e.g. `CameraController(_, _, enableAudio: false);`) ## 0.5.1 -- Can now be compiled with earlier Android sdks below 21 when - `` has been added to the project +* Can now be compiled with earlier Android sdks below 21 when + `` has been added to the project `AndroidManifest.xml`. For sdks below 21, the plugin won't be registered and calls to it will throw a `MissingPluginException.` ## 0.5.0 -- **Breaking Change** This plugin no longer handles closing and opening the camera on Android +* **Breaking Change** This plugin no longer handles closing and opening the camera on Android lifecycle changes. Please use `WidgetsBindingObserver` to control camera resources on lifecycle changes. See example project for example using `WidgetsBindingObserver`. ## 0.4.3+2 -- Bump the minimum Flutter version to 1.2.0. -- Add template type parameter to `invokeMethod` calls. +* Bump the minimum Flutter version to 1.2.0. +* Add template type parameter to `invokeMethod` calls. ## 0.4.3+1 -- Catch additional `Exception`s from Android and throw as `CameraException`s. +* Catch additional `Exception`s from Android and throw as `CameraException`s. ## 0.4.3 -- Add capability to prepare the capture session for video recording on iOS. +* Add capability to prepare the capture session for video recording on iOS. ## 0.4.2 -- Add sensor orientation value to `CameraDescription`. +* Add sensor orientation value to `CameraDescription`. ## 0.4.1 -- Camera methods are ran in a background thread on iOS. +* Camera methods are ran in a background thread on iOS. ## 0.4.0+3 -- Fixed a crash when the plugin is registered by a background FlutterView. +* Fixed a crash when the plugin is registered by a background FlutterView. ## 0.4.0+2 -- Fix orientation of captured photos when camera is used for the first time on Android. +* Fix orientation of captured photos when camera is used for the first time on Android. ## 0.4.0+1 -- Remove categories. +* Remove categories. ## 0.4.0 -- **Breaking Change** Change iOS image stream format to `ImageFormatGroup.bgra8888` from +* **Breaking Change** Change iOS image stream format to `ImageFormatGroup.bgra8888` from `ImageFormatGroup.yuv420`. ## 0.3.0+4 -- Fixed bug causing black screen on some Android devices. +* Fixed bug causing black screen on some Android devices. ## 0.3.0+3 -- Log a more detailed warning at build time about the previous AndroidX +* Log a more detailed warning at build time about the previous AndroidX migration. ## 0.3.0+2 -- Fix issue with calculating iOS image orientation in certain edge cases. +* Fix issue with calculating iOS image orientation in certain edge cases. ## 0.3.0+1 -- Remove initial method call invocation from static camera method. +* Remove initial method call invocation from static camera method. ## 0.3.0 -- **Breaking change**. Migrate from the deprecated original Android Support +* **Breaking change**. Migrate from the deprecated original Android Support Library to AndroidX. This shouldn't result in any functional changes, but it requires any Android apps using this plugin to [also migrate](https://developer.android.com/jetpack/androidx/migrate) if they're @@ -190,96 +190,96 @@ ## 0.2.9+1 -- Fix a crash when failing to start preview. +* Fix a crash when failing to start preview. ## 0.2.9 -- Save photo orientation data on iOS. +* Save photo orientation data on iOS. ## 0.2.8 -- Add access to the image stream from Dart. -- Use `cameraController.startImageStream(listener)` to process the images. +* Add access to the image stream from Dart. +* Use `cameraController.startImageStream(listener)` to process the images. ## 0.2.7 -- Fix issue with crash when the physical device's orientation is unknown. +* Fix issue with crash when the physical device's orientation is unknown. ## 0.2.6 -- Update the camera to use the physical device's orientation instead of the UI +* Update the camera to use the physical device's orientation instead of the UI orientation on Android. ## 0.2.5 -- Fix preview and video size with satisfying conditions of multiple outputs. +* Fix preview and video size with satisfying conditions of multiple outputs. ## 0.2.4 -- Unregister the activity lifecycle callbacks when disposing the camera. +* Unregister the activity lifecycle callbacks when disposing the camera. ## 0.2.3 -- Added path_provider and video_player as dev dependencies because the example uses them. -- Updated example path_provider version to get Dart 2 support. +* Added path_provider and video_player as dev dependencies because the example uses them. +* Updated example path_provider version to get Dart 2 support. ## 0.2.2 -- iOS image capture is done in high quality (full camera size) +* iOS image capture is done in high quality (full camera size) ## 0.2.1 -- Updated Gradle tooling to match Android Studio 3.1.2. +* Updated Gradle tooling to match Android Studio 3.1.2. ## 0.2.0 -- Added support for video recording. -- Changed the example app to add video recording. +* Added support for video recording. +* Changed the example app to add video recording. A lot of **breaking changes** in this version: Getter changes: -- Removed `isStarted` -- Renamed `initialized` to `isInitialized` -- Added `isRecordingVideo` +* Removed `isStarted` +* Renamed `initialized` to `isInitialized` +* Added `isRecordingVideo` Method changes: -- Renamed `capture` to `takePicture` -- Removed `start` (the preview starts automatically when `initialize` is called) -- Added `startVideoRecording(String filePath)` -- Removed `stop` (the preview stops automatically when `dispose` is called) -- Added `stopVideoRecording` +* Renamed `capture` to `takePicture` +* Removed `start` (the preview starts automatically when `initialize` is called) +* Added `startVideoRecording(String filePath)` +* Removed `stop` (the preview stops automatically when `dispose` is called) +* Added `stopVideoRecording` ## 0.1.2 -- Fix Dart 2 runtime errors. +* Fix Dart 2 runtime errors. ## 0.1.1 -- Fix Dart 2 runtime error. +* Fix Dart 2 runtime error. ## 0.1.0 -- **Breaking change**. Set SDK constraints to match the Flutter beta release. +* **Breaking change**. Set SDK constraints to match the Flutter beta release. ## 0.0.4 -- Revert regression of `CameraController.capture()` introduced in v. 0.0.3. +* Revert regression of `CameraController.capture()` introduced in v. 0.0.3. ## 0.0.3 -- Improved resource cleanup on Android. Avoids crash on Activity restart. -- Made the Future returned by `CameraController.dispose()` and `CameraController.capture()` actually complete on +* Improved resource cleanup on Android. Avoids crash on Activity restart. +* Made the Future returned by `CameraController.dispose()` and `CameraController.capture()` actually complete on Android. ## 0.0.2 -- Simplified and upgraded Android project template to Android SDK 27. -- Moved Android package to io.flutter.plugins. -- Fixed warnings from the Dart 2.0 analyzer. +* Simplified and upgraded Android project template to Android SDK 27. +* Moved Android package to io.flutter.plugins. +* Fixed warnings from the Dart 2.0 analyzer. ## 0.0.1 -- Initial release +* Initial release From cd7b678ff548c93fe377c5d16dede2210a959917 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?O=C4=9Fulcan=20=C3=87elik?= Date: Sat, 11 Jul 2020 23:10:54 +0300 Subject: [PATCH 8/9] fixes changelog --- packages/camera/CHANGELOG.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/camera/CHANGELOG.md b/packages/camera/CHANGELOG.md index 08314bd38596..7da63713a511 100644 --- a/packages/camera/CHANGELOG.md +++ b/packages/camera/CHANGELOG.md @@ -8,7 +8,7 @@ ## 0.5.8+2 -* Post*v2 embedding cleanups. +* Post-v2 embedding cleanups. ## 0.5.8+1 @@ -81,7 +81,7 @@ ## 0.5.4+2 -* Fix Android NullPointerException on devices with only front*facing camera. +* Fix Android NullPointerException on devices with only front-facing camera. ## 0.5.4+1 @@ -115,7 +115,7 @@ ## 0.5.1 * Can now be compiled with earlier Android sdks below 21 when - `` has been added to the project + `` has been added to the project `AndroidManifest.xml`. For sdks below 21, the plugin won't be registered and calls to it will throw a `MissingPluginException.` From caf092e51d6151adc25cb1d6d9134280119103eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?O=C4=9Fulcan=20=C3=87elik?= Date: Sun, 30 Aug 2020 18:39:48 +0300 Subject: [PATCH 9/9] fix of 2870#discussion_r477435844 --- packages/camera/lib/camera_image.dart | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/packages/camera/lib/camera_image.dart b/packages/camera/lib/camera_image.dart index 27029150e61b..983bbc405c20 100644 --- a/packages/camera/lib/camera_image.dart +++ b/packages/camera/lib/camera_image.dart @@ -67,7 +67,7 @@ enum ImageFormatGroup { /// 32-big RGB image encoded into JPEG bytes. /// /// On Android, this is `android.graphics.ImageFormat.JPEG`. See - /// https://developer.android.com/reference/android/graphics/ImageFormat#FLEX_RGBA_8888 + /// https://developer.android.com/reference/android/graphics/ImageFormat#JPEG /// jpeg } @@ -91,11 +91,13 @@ class ImageFormat { ImageFormatGroup _asImageFormatGroup(dynamic rawFormat) { if (defaultTargetPlatform == TargetPlatform.android) { - // android.graphics.ImageFormat.YUV_420_888 - if (rawFormat == 256) { - return ImageFormatGroup.jpeg; - } else if (rawFormat == 42) { - return ImageFormatGroup.bgra8888; + switch (rawFormat) { + // android.graphics.ImageFormat.JPEG + case 256: + return ImageFormatGroup.jpeg; + // android.graphics.ImageFormat.YUV_420_888 + case 42: + return ImageFormatGroup.yuv420; } }