Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
0e59dbc
Fixes flutter/flutter#148013: setDescriptionWhileRecording with andro…
blackorbs-dev Aug 24, 2025
fcc11be
Fixes flutter/flutter#148013: updated Version and Changelog
blackorbs-dev Aug 24, 2025
971ebc8
Address review feedback: code fix
blackorbs-dev Aug 25, 2025
87c985e
Address review feedback: implement code fixes and suggestions
blackorbs-dev Aug 25, 2025
80d3c61
Merge branch 'main' into fix-issue-148013
blackorbs-dev Aug 27, 2025
0461e63
Update camera_android_camerax readme, revert changes for unaffected c…
blackorbs-dev Aug 27, 2025
f4a076d
Merge branch 'main' into fix-issue-148013
blackorbs-dev Aug 27, 2025
1a8397e
Merge branch 'main' into fix-issue-148013
blackorbs-dev Aug 28, 2025
a631f15
fix merge issue with main
blackorbs-dev Aug 28, 2025
4eece12
update version and changelog
blackorbs-dev Aug 28, 2025
3ac789c
Implement code fixes and suggestions
blackorbs-dev Aug 29, 2025
53e3aa3
Merge branch 'main' into fix-issue-148013
blackorbs-dev Aug 29, 2025
8fbb01c
Address some nits
blackorbs-dev Sep 3, 2025
41aac10
Merge branch 'main' into fix-issue-148013
blackorbs-dev Sep 3, 2025
b1c2ac1
Reformat merge from main
blackorbs-dev Sep 3, 2025
1ddc209
Merge branch 'main' into fix-issue-148013
blackorbs-dev Sep 9, 2025
3b2164f
checkout camera_avfoundation to upstream main
blackorbs-dev Sep 9, 2025
d73bccb
update camera_android_camerax readme
blackorbs-dev Sep 9, 2025
69eb480
Merge branch 'main' into fix-issue-148013
blackorbs-dev Sep 10, 2025
3e799c2
implement version bump for camera_platform_interface
blackorbs-dev Sep 11, 2025
5520c89
implement changes for platform consistency
blackorbs-dev Sep 11, 2025
8614a35
format code changes
blackorbs-dev Sep 11, 2025
d9ce45b
platform changes for setDescriptionWhileRecording with android camerax
blackorbs-dev Sep 13, 2025
5bc3992
platform changes for setDescriptionWhileRecording with android camerax
blackorbs-dev Sep 13, 2025
34f3862
Merge branch 'main' into split-camera-interface
blackorbs-dev Sep 13, 2025
8d971a4
update doc and changelog
blackorbs-dev Sep 13, 2025
3373107
Merge branch 'main' into split-camera-interface
blackorbs-dev Sep 16, 2025
3a74560
update changelog
blackorbs-dev Sep 16, 2025
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
Prev Previous commit
Next Next commit
implement changes for platform consistency
  • Loading branch information
blackorbs-dev committed Sep 11, 2025
commit 5520c8956ab8a56d09629bcc39daa4045c0abe4c
Original file line number Diff line number Diff line change
Expand Up @@ -276,11 +276,7 @@ void main() {
await controller.initialize();
await controller.prepareForVideoRecording();

if (Platform.isAndroid) {
await controller.startVideoRecording(enablePersistentRecording: true);
} else {
await controller.startVideoRecording();
}
await controller.startVideoRecording();
await controller.setDescription(cameras[1]);

await tester.pumpAndSettle(const Duration(seconds: 4));
Expand Down
6 changes: 3 additions & 3 deletions packages/camera/camera/lib/src/camera_controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -559,14 +559,14 @@ class CameraController extends ValueNotifier<CameraValue> {
/// The video is returned as a [XFile] after calling [stopVideoRecording].
/// Throws a [CameraException] if the capture fails.
///
/// If [enablePersistentRecording] parameter is set to true, configures the recording to be a persistent recording.
/// A persistent recording will only be stopped by explicitly calling [stopVideoRecording]
/// `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 = false,
bool enablePersistentRecording = true,
}) async {
_throwIfNotInitialized('startVideoRecording');
if (value.isRecordingVideo) {
Expand Down
2 changes: 1 addition & 1 deletion packages/camera/camera/test/camera_preview_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ class FakeController extends ValueNotifier<CameraValue>
@override
Future<void> startVideoRecording({
onLatestImageAvailable? onAvailable,
bool enablePersistentRecording = false,
bool enablePersistentRecording = true,
}) async {}

@override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ void main() {
await controller.initialize();
await controller.prepareForVideoRecording();

await controller.startVideoRecording(enablePersistentRecording: true);
await controller.startVideoRecording();

await controller.setDescription(cameras[1]);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -503,13 +503,13 @@ class CameraController extends ValueNotifier<CameraValue> {
/// The video is returned as a [XFile] after calling [stopVideoRecording].
/// Throws a [CameraException] if the capture fails.
///
/// If [enablePersistentRecording] is set to true, configures the recording to be a persistent recording.
/// `enablePersistentRecording` parameter configures the recording to be a persistent recording.
/// A persistent recording will 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.
Future<void> startVideoRecording({
onLatestImageAvailable? onAvailable,
bool enablePersistentRecording = false,
bool enablePersistentRecording = true,
}) async {
_throwIfNotInitialized('startVideoRecording');
if (value.isRecordingVideo) {
Expand Down Expand Up @@ -617,11 +617,8 @@ class CameraController extends ValueNotifier<CameraValue> {

/// Sets the description of the camera.
///
/// By default, if a video recording is in progress, calling this method will cancel the current recording.
///
/// To keep recording active while switching camera, start the
/// recording with [startVideoRecording] and set
/// `enablePersistentRecording` to `true`.
/// To avoid cancelling any active recording when calling this method,
/// start the recording with [startVideoRecording] with `enablePersistentRecording` to `true`.
///
/// Throws a [CameraException] if setting the description fails.
Future<void> setDescription(CameraDescription description) async {
Expand Down
18 changes: 2 additions & 16 deletions packages/camera/camera_android_camerax/example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -549,8 +549,6 @@ class _CameraExampleHomeState extends State<CameraExampleHome>
color: Colors.blue,
onPressed:
cameraController == null ? null : onVideoRecordButtonPressed,
onLongPress:
cameraController == null ? null : onVideoRecordButtonLongPressed,
),
IconButton(
icon:
Expand Down Expand Up @@ -838,14 +836,6 @@ class _CameraExampleHomeState extends State<CameraExampleHome>
});
}

void onVideoRecordButtonLongPressed() {
startVideoRecording(enablePersistentRecording: true).then((_) {
if (mounted) {
setState(() {});
}
});
}

void onStopButtonPressed() {
stopVideoRecording().then((XFile? file) {
if (mounted) {
Expand Down Expand Up @@ -896,9 +886,7 @@ class _CameraExampleHomeState extends State<CameraExampleHome>
});
}

Future<void> startVideoRecording({
bool enablePersistentRecording = false,
}) async {
Future<void> startVideoRecording() async {
final CameraController? cameraController = controller;

if (cameraController == null || !cameraController.value.isInitialized) {
Expand All @@ -912,9 +900,7 @@ class _CameraExampleHomeState extends State<CameraExampleHome>
}

try {
await cameraController.startVideoRecording(
enablePersistentRecording: enablePersistentRecording,
);
await cameraController.startVideoRecording();
} on CameraException catch (e) {
_showCameraException(e);
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3346,6 +3346,9 @@ void main() {
when(
mockPendingRecording.withAudioEnabled(!enableAudio),
).thenAnswer((_) async => mockPendingRecordingWithAudio);
when(
mockPendingRecording.asPersistentRecording(),
).thenAnswer((_) async => mockPendingRecording);
when(
mockPendingRecordingWithAudio.start(any),
).thenAnswer((_) async => mockRecording);
Expand Down Expand Up @@ -3512,6 +3515,9 @@ void main() {
when(
mockPendingRecording.withAudioEnabled(!camera.enableRecordingAudio),
).thenAnswer((_) async => mockPendingRecording);
when(
mockPendingRecording.asPersistentRecording(),
).thenAnswer((_) async => mockPendingRecording);
when(
mockPendingRecording.start(any),
).thenAnswer((_) async => mockRecording);
Expand Down Expand Up @@ -3567,6 +3573,7 @@ void main() {
verifyNoMoreInteractions(camera.recorder);
verify(mockPendingRecording.start(any)).called(1);
verify(mockPendingRecording.withAudioEnabled(any)).called(1);
verify(mockPendingRecording.asPersistentRecording()).called(1);
verifyNoMoreInteractions(mockPendingRecording);
},
);
Expand Down Expand Up @@ -3701,6 +3708,9 @@ void main() {
when(
mockPendingRecording.withAudioEnabled(!camera.enableRecordingAudio),
).thenAnswer((_) async => mockPendingRecording);
when(
mockPendingRecording.asPersistentRecording(),
).thenAnswer((_) async => mockPendingRecording);
when(
mockProcessCameraProvider.bindToLifecycle(any, any),
).thenAnswer((_) => Future<Camera>.value(camera.camera));
Expand Down Expand Up @@ -3850,6 +3860,9 @@ void main() {
when(
mockPendingRecording.withAudioEnabled(!camera.enableRecordingAudio),
).thenAnswer((_) async => mockPendingRecording);
when(
mockPendingRecording.asPersistentRecording(),
).thenAnswer((_) async => mockPendingRecording);
when(
mockPendingRecording.start(any),
).thenAnswer((_) async => mockRecording);
Expand Down Expand Up @@ -4388,7 +4401,6 @@ void main() {
await camera.startVideoCapturing(
VideoCaptureOptions(
flutterSurfaceTextureId,
enablePersistentRecording: true,
),
);
await camera.setDescriptionWhileRecording(testFrontCameraDescription);
Expand Down Expand Up @@ -7181,6 +7193,9 @@ void main() {
when(
mockPendingRecording.withAudioEnabled(!camera.enableRecordingAudio),
).thenAnswer((_) async => mockPendingRecording);
when(
mockPendingRecording.asPersistentRecording(),
).thenAnswer((_) async => mockPendingRecording);
when(
mockPendingRecording.start(any),
).thenAnswer((_) async => mockRecording);
Expand Down Expand Up @@ -7322,6 +7337,9 @@ void main() {
when(
mockPendingRecording.withAudioEnabled(!camera.enableRecordingAudio),
).thenAnswer((_) async => mockPendingRecording);
when(
mockPendingRecording.asPersistentRecording(),
).thenAnswer((_) async => mockPendingRecording);
when(
mockPendingRecording.start(any),
).thenAnswer((_) async => mockRecording);
Expand Down Expand Up @@ -7463,6 +7481,9 @@ void main() {
when(
mockPendingRecording.withAudioEnabled(!camera.enableRecordingAudio),
).thenAnswer((_) async => mockPendingRecording);
when(
mockPendingRecording.asPersistentRecording(),
).thenAnswer((_) async => mockPendingRecording);
when(
mockPendingRecording.start(any),
).thenAnswer((_) async => mockRecording);
Expand Down Expand Up @@ -7624,6 +7645,9 @@ void main() {
when(
mockPendingRecording.withAudioEnabled(!camera.enableRecordingAudio),
).thenAnswer((_) async => mockPendingRecording);
when(
mockPendingRecording.asPersistentRecording(),
).thenAnswer((_) async => mockPendingRecording);
when(
mockPendingRecording.start(any),
).thenAnswer((_) async => mockRecording);
Expand Down Expand Up @@ -7789,6 +7813,9 @@ void main() {
when(
mockPendingRecording.withAudioEnabled(!camera.enableRecordingAudio),
).thenAnswer((_) async => mockPendingRecording);
when(
mockPendingRecording.asPersistentRecording(),
).thenAnswer((_) async => mockPendingRecording);
when(
mockPendingRecording.start(any),
).thenAnswer((_) async => mockRecording);
Expand Down Expand Up @@ -7946,6 +7973,9 @@ void main() {
when(
mockPendingRecording.withAudioEnabled(!camera.enableRecordingAudio),
).thenAnswer((_) async => mockPendingRecording);
when(
mockPendingRecording.asPersistentRecording(),
).thenAnswer((_) async => mockPendingRecording);
when(
mockPendingRecording.start(any),
).thenAnswer((_) async => mockRecording);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class VideoCaptureOptions {
this.maxDuration,
this.streamCallback,
this.streamOptions,
this.enablePersistentRecording = false,
this.enablePersistentRecording = true,
}) : assert(
streamOptions == null || streamCallback != null,
'Must specify streamCallback if providing streamOptions.',
Expand All @@ -44,15 +44,15 @@ class VideoCaptureOptions {
/// Should only be set if a streamCallback is also present.
final CameraImageStreamOptions? streamOptions;

/// When `true`, configures the recording to be a persistent recording.
/// Configures the recording to be a persistent recording.
///
/// A persistent recording will only be stopped by explicitly calling [CameraController.stopVideoRecording]
/// A persistent recording can only be stopped by explicitly calling [CameraController.stopVideoRecording]
/// and will ignore events that would normally cause recording to stop, such as lifecycle events.
///
/// On Android, you must set this parameter to `true`
/// to avoid cancelling any active recording when calling [CameraController.setDescription].
///
/// Defaults to `false`.
/// Defaults to `true`.
final bool enablePersistentRecording;

@override
Expand Down