Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


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

* Implement setDescriptionWhileRecording with android camerax (Fixes flutter/flutter#148013).
* Updates minimum supported SDK version to Flutter 3.29/Dart 3.7.
* Updates README to reflect that only Android API 24+ is supported.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,9 @@ void main() {
return completer.future;
}

testWidgets('Set description while recording', (WidgetTester tester) async {
testWidgets('Set description while recording captures full video', (
WidgetTester tester,
) async {
final List<CameraDescription> cameras = await availableCameras();
if (cameras.length < 2) {
return;
Expand All @@ -269,7 +271,6 @@ void main() {
final CameraController controller = CameraController(
cameras[0],
ResolutionPreset.low,
enableAudio: false,
);

await controller.initialize();
Expand All @@ -278,7 +279,27 @@ void main() {
await controller.startVideoRecording();
await controller.setDescription(cameras[1]);

expect(controller.description, cameras[1]);
await tester.pumpAndSettle(const Duration(seconds: 4));

await controller.setDescription(cameras[0]);

await tester.pumpAndSettle(const Duration(seconds: 1));

final XFile file = await controller.stopVideoRecording();

final File videoFile = File(file.path);
final VideoPlayerController videoController = VideoPlayerController.file(
videoFile,
);
await videoController.initialize();
final int duration = videoController.value.duration.inMilliseconds;
await videoController.dispose();

expect(
duration,
greaterThanOrEqualTo(const Duration(seconds: 4).inMilliseconds),
);
await controller.dispose();
});

testWidgets('Set description', (WidgetTester tester) async {
Expand Down
17 changes: 16 additions & 1 deletion packages/camera/camera/lib/src/camera_controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,10 @@ class CameraController extends ValueNotifier<CameraValue> {

/// Sets the description of the camera.
///
/// On Android, you must start the recording with [startVideoRecording]
/// with `enablePersistentRecording` set to `true`
/// to avoid cancelling any active recording.
///
/// Throws a [CameraException] if setting the description fails.
Future<void> setDescription(CameraDescription description) async {
if (value.isRecordingVideo) {
Expand Down Expand Up @@ -554,8 +558,15 @@ class CameraController extends ValueNotifier<CameraValue> {
///
/// The video is returned as a [XFile] after calling [stopVideoRecording].
/// Throws a [CameraException] if the capture fails.
///
/// `enablePersistentRecording` parameter configures the recording to be a persistent recording.
/// A persistent recording can only be stopped by explicitly calling [stopVideoRecording]
/// and will ignore events that would normally cause recording to stop,
/// such as lifecycle events or explicit calls to [setDescription] while recording is in progress.
/// Currently a no-op on platforms other than Android.
Future<void> startVideoRecording({
onLatestImageAvailable? onAvailable,
bool enablePersistentRecording = true,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Setting enablePersistentRecording to true by default changes the existing behavior of video recording. As the documentation states, a persistent recording will ignore events that would normally stop it, such as lifecycle events. This is a behavioral breaking change for users who might be relying on the previous behavior.

For a patch release, it's best to avoid such breaking changes. I recommend changing the default value to false to make this new persistent recording behavior opt-in. This maintains backward compatibility, and developers who need to switch cameras during recording can explicitly enable it.

If you apply this change, please remember to update the integration test in packages/camera/camera/example/integration_test/camera_test.dart to explicitly call startVideoRecording(enablePersistentRecording: true) to ensure the test for the new functionality continues to pass.

Suggested change
bool enablePersistentRecording = true,
bool enablePersistentRecording = false,

}) async {
_throwIfNotInitialized('startVideoRecording');
if (value.isRecordingVideo) {
Expand All @@ -574,7 +585,11 @@ class CameraController extends ValueNotifier<CameraValue> {

try {
await CameraPlatform.instance.startVideoCapturing(
VideoCaptureOptions(_cameraId, streamCallback: streamCallback),
VideoCaptureOptions(
_cameraId,
streamCallback: streamCallback,
enablePersistentRecording: enablePersistentRecording,
),
);
value = value.copyWith(
isRecordingVideo: true,
Expand Down
6 changes: 3 additions & 3 deletions packages/camera/camera/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ description: A Flutter plugin for controlling the camera. Supports previewing
Dart.
repository: https://github.com/flutter/packages/tree/main/packages/camera/camera
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+camera%22
version: 0.11.2
version: 0.11.2+1

environment:
sdk: ^3.7.0
Expand All @@ -21,9 +21,9 @@ flutter:
default_package: camera_web

dependencies:
camera_android_camerax: ^0.6.13
camera_android_camerax: ^0.6.22
camera_avfoundation: ^0.9.18
camera_platform_interface: ^2.10.0
camera_platform_interface: ^2.11.0
camera_web: ^0.3.3
flutter:
sdk: flutter
Expand Down
1 change: 1 addition & 0 deletions packages/camera/camera/test/camera_preview_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ class FakeController extends ValueNotifier<CameraValue>
@override
Future<void> startVideoRecording({
onLatestImageAvailable? onAvailable,
bool enablePersistentRecording = true,
}) async {}

@override
Expand Down