Skip to content

[camera_android] Fix stopVideoRecording returning JPEG when takePicture runs during recording - #13070

Merged
auto-submit[bot] merged 13 commits into
flutter:mainfrom
Azim04:camera_android-fix-stop-recording-path
Nov 10, 2026
Merged

auto-submit[bot] merged 13 commits into
flutter:mainfrom
Azim04:camera_android-fix-stop-recording-path

Conversation

@Azim04

@Azim04 Azim04 commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

Description

When takePicture() is called during an active video recording, stopVideoRecording() could return the JPEG path instead of the MP4 path because a single captureFile field was shared.

This change introduces a dedicated videoCaptureFile for video recording and keeps captureFile for still capture.

Related Issue

Fixes flutter/flutter#192927

Tests

  • Unit tests in CameraTest.java
  • Integration test: stopVideoRecording returns mp4 after takePicture during recording

Pre-Review Checklist

  • I read the Contributor Guide and followed the process outlined there for submitting PRs.
  • I read the AI contribution guidelines and understand my responsibilities, or I am not using AI tools.
  • I read the Tree Hygiene page, which explains my responsibilities.
  • I read and followed the relevant style guides and ran the auto-formatter only where appropriate (no whole-file reformat of unrelated code).
  • I signed the CLA.
  • The title of the PR starts with the name of the package surrounded by square brackets, e.g. [camera_android]
  • I linked to at least one issue that this PR fixes in the description above.
  • I followed the version and CHANGELOG instructions, using semantic versioning and the repository CHANGELOG style (## NEXT entry for this unreleased fix).
  • I updated/added any relevant documentation (doc comments with /// / Javadoc on new fields).
  • I added new tests to check the change I am making.
  • All existing and new tests are passing.

@google-cla

google-cla Bot commented Sep 30, 2026

Copy link
Copy Markdown

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a separate videoCaptureFile field in the Android camera implementation to prevent takePicture from overwriting the video path returned by stopVideoRecording when a photo is taken during an active video recording. It also adds corresponding unit tests to verify this behavior and handle cases where the video capture file is null. There are no review comments, and I have no feedback to provide.

@Azim04

Azim04 commented Sep 30, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

Thanks, I signed the CLA just now.

@Azim04 Azim04 closed this Sep 30, 2026
@Azim04

Azim04 commented Sep 30, 2026

Copy link
Copy Markdown
Contributor Author

Reopening to retrigger the CLA check. I have signed the CLA.

@Azim04 Azim04 reopened this Sep 30, 2026
@fluttergithubbot

Copy link
Copy Markdown
Contributor

An existing Git SHA, aed01593ed3154c6339121495275d00e0b90e0d4, was detected, and no actions were taken.

To re-trigger presubmits after closing or re-opeing a PR, or pushing a HEAD commit (i.e. with --force) that already was pushed before, push a blank commit (git commit --allow-empty -m "Trigger Build") or rebase to continue.

@Azim04

Azim04 commented Sep 30, 2026

Copy link
Copy Markdown
Contributor Author

Closing the PR to retrigger the CLA after 1 hour

@Azim04 Azim04 closed this Sep 30, 2026
@Azim04

Azim04 commented Sep 30, 2026

Copy link
Copy Markdown
Contributor Author

I signed the CLA.

@Azim04 Azim04 reopened this Sep 30, 2026
@fluttergithubbot

Copy link
Copy Markdown
Contributor

An existing Git SHA, aed01593ed3154c6339121495275d00e0b90e0d4, was detected, and no actions were taken.

To re-trigger presubmits after closing or re-opeing a PR, or pushing a HEAD commit (i.e. with --force) that already was pushed before, push a blank commit (git commit --allow-empty -m "Trigger Build") or rebase to continue.

@Mairramer Mairramer left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thanks for this PR! The bug fix makes sense, and the approach of decoupling videoCaptureFile from captureFile is clean and addresses the issue well.

I only left two minor comments regarding an outdated error message and a small adjustment to the test cleanup.

There are also several unintended changes in the PR. Please review them and remove any changes that are not related to this fix.

@Mairramer

Copy link
Copy Markdown
Contributor

@Azim04 Please use the Pre-Review Checklist and keep it in the PR rather than deleting it.

Pre-Review Checklist

If you need help, consider asking for advice on the #hackers-new channel on Discord.

Note: The Flutter team is currently trialing the use of Gemini Code Assist for GitHub. Comments from the gemini-code-assist bot should not be taken as authoritative feedback from the Flutter team. If you find its comments useful you can update your code accordingly, but if you are unsure or disagree with the feedback, please feel free to wait for a Flutter team member's review for guidance on which automated comments should be addressed.

Footnotes

  1. Regular contributors who have demonstrated familiarity with the repository guidelines only need to comment if the PR is not auto-exempted by repo tooling. ↩ ↩2

@Azim04
Azim04 force-pushed the camera_android-fix-stop-recording-path branch from bb31bcb to 29a4001 Compare October 1, 2026 10:16
…cording

Separate still-image and video capture file fields so takePicture() cannot
overwrite the path returned by stopVideoRecording().

Fixes flutter/flutter#192927
@Azim04
Azim04 force-pushed the camera_android-fix-stop-recording-path branch from 29a4001 to 94fda02 Compare October 1, 2026 11:07

@Azim04 Azim04 left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Description

When takePicture() is called during an active video recording, stopVideoRecording() could return the JPEG path instead of the MP4 path because a single captureFile field was shared.

This change introduces a dedicated videoCaptureFile for video recording and keeps captureFile for still capture.

Related Issue

Fixes flutter/flutter#192927

Tests

  • Unit tests in CameraTest.java
  • Integration test: stopVideoRecording returns mp4 after takePicture during recording

Pre-Review Checklist

  • I read the Contributor Guide and followed the process outlined there for submitting PRs.
  • I read the AI contribution guidelines and understand my responsibilities, or I am not using AI tools.
  • I read the Tree Hygiene page, which explains my responsibilities.
  • I read and followed the relevant style guides and ran the auto-formatter only where appropriate (no whole-file reformat of unrelated code).
  • I signed the CLA.
  • The title of the PR starts with the name of the package surrounded by square brackets, e.g. [camera_android]
  • I linked to at least one issue that this PR fixes in the description above.
  • I followed the version and CHANGELOG instructions, using semantic versioning and the repository CHANGELOG style (## NEXT entry for this unreleased fix).
  • I updated/added any relevant documentation (doc comments with /// / Javadoc on new fields).
  • I added new tests to check the change I am making.
  • All existing and new tests are passing.

@Azim04
Azim04 requested a review from Mairramer October 1, 2026 11:11
@@ -1,3 +1,7 @@
## NEXT

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This should be ## 0.10.13, since it fixes an existing issue.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@Mairramer
Thanks for the response.
Updated the line in CHANGELOG.md

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

We also need to update this in pubspec.yaml.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Sure, I will update the pubspec.yaml

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@Mairramer
I have bumped pubspec.yaml version from 0.10.12 to 0.12.13
Can you please review it?

@Mairramer Mairramer added the CICD Run CI/CD label Oct 1, 2026
Update changelog to reflect version 0.10.13.
@flutter-dashboard flutter-dashboard Bot removed the CICD Run CI/CD label Oct 1, 2026

@Azim04 Azim04 left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@Mairramer
Thanks for the response.
Updated the line in CHANGELOG.md

@Azim04
Azim04 requested a review from Mairramer October 1, 2026 11:51
@Mairramer Mairramer added the CICD Run CI/CD label Oct 1, 2026
@Azim04

Azim04 commented Oct 12, 2026

Copy link
Copy Markdown
Contributor Author

@Azim04 It still looks like some files aren't formatted correctly. Could you check the format logs again?

I shared the wrong command earlier. The correct one is:

dart run script/tool/bin/flutter_plugin_tools.dart format --packages camera_android

Re-ran:
dart run script/tool/bin/flutter_plugin_tools.dart format --packages camera_android

Formatter updated Camera.java and CameraTest.java; pushed.

@Azim04 Azim04 left a comment •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@Mairramer Thanks — I re-ran:

dart run script/tool/bin/flutter_plugin_tools.dart format --packages camera_android

It updated Camera.java and CameraTest.java. Changes are pushed; please take another look when you have a moment.

@Mairramer Mairramer added the CICD Run CI/CD label Oct 12, 2026
@Mairramer
Mairramer requested a review from mboetger October 12, 2026 16:18
@flutter-dashboard flutter-dashboard Bot removed the CICD Run CI/CD label Oct 13, 2026
@Mairramer Mairramer added the CICD Run CI/CD label Nov 1, 2026
@Mairramer
Mairramer requested review from camsim99 and removed request for mboetger November 1, 2026 20:15
expect(lengths[n], greaterThan(0));
}
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The tests added above seem unrelated to the change. Can those be removed or added in a follow up PR instead?

@Azim04 Azim04 Nov 5, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes, Those tests are unrelated to this fix. I'll remove Control FPS, Control video bitrate, and Control audio bitrate from this PR and keep only stopVideoRecording returns mp4 after takePicture during recording.

@camsim99 camsim99 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Overall looks good! I think we have an opportunity to improve the unit testing though, PTAL!


// Simulate takePicture() overwriting the shared field with a JPEG path
// (this is the bug we fixed by introducing videoCaptureFile).
cameraSpy.captureFile = new File(jpegPath);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Ideally, we call takePicture here instead of making captureFile visible for testing so that the test is reliant on videoCaptureFile existing separate from videoCaptureFile.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done. captureFile is private again, and the test now calls takePicture() after prepareRecording(). stopVideoRecording() still returns the .mp4 path, so the test checks that videoCaptureFile stays separate from the JPEG written by takePicture().

Call takePicture() in the unit test so captureFile can stay private, and remove integration tests that are unrelated to this fix.
@flutter-dashboard flutter-dashboard Bot removed the CICD Run CI/CD label Nov 5, 2026
@Mairramer Mairramer added the CICD Run CI/CD label Nov 5, 2026

@Azim04 Azim04 left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Addressed both review comments:

  • captureFile is private again. The unit test now calls takePicture() after prepareRecording(), and stopVideoRecording() still returns the .mp4 path.
  • Removed the unrelated integration tests (Control FPS, Control video bitrate, and Control audio bitrate). This PR now only adds stopVideoRecording returns mp4 after takePicture during recording.

@flutter-dashboard flutter-dashboard Bot removed the CICD Run CI/CD label Nov 5, 2026
@Azim04
Azim04 requested a review from camsim99 November 5, 2026 12:22
@Mairramer Mairramer added the CICD Run CI/CD label Nov 5, 2026

@camsim99 camsim99 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Changes LGTM, thanks!!

@camsim99 camsim99 added the autosubmit Merge PR when tree becomes green via auto submit App label Nov 10, 2026
@auto-submit
auto-submit Bot merged commit 0f29291 into flutter:main Nov 10, 2026
14 checks passed
opensource-fork-sync Bot pushed a commit to cla7aye15I4nd/opensource-flutter__flutter that referenced this pull request Nov 11, 2026
…er#196381)

flutter/packages@08faf64...653628e

2026-11-11 [email protected] Roll Flutter from
fffd8c2 to b98afb5 (31 revisions) (flutter/packages#13623)
2026-11-11 [email protected] [material_ui] Document how to
programmatically clear DropdownMenu selection (flutter/packages#13266)
2026-11-11 [email protected] [pigeon] Fix basePath resolution when
paths share a string prefix with basePath (flutter/packages#13342)
2026-11-11 [email protected]
[cupertino_ui] Fix CupertinoSheetRoute throwing when a drag ends during
a pending relayout (flutter/packages#13316)
2026-11-11 [email protected] [shared_preferences] Updates Pigeon to
30.0.1 to support multi-engine registration and deregistration.
(flutter/packages#13617)
2026-11-11 [email protected]
[vector_graphics] Catch any throwable in useHtmlRenderObject() and cache
HTML fallback (flutter/packages#13545)
2026-11-11 [email protected] [cupertino_ui]
Include selectionHandleColor in NoDefaultCupertinoThemeData equality
(flutter/packages#13450)
2026-11-11 [email protected] [flutter_svg] Remove failed async loads
from Cache._pending (flutter/packages#13604)
2026-11-11 [email protected] [pigeon] Adds Native Interop FFI codec
serialization for NS types (flutter/packages#13616)
2026-11-10 [email protected] [pigeon] Support multi-engine Native
Interop registration and instance-aware unregistration
(flutter/packages#13576)
2026-11-10 [email protected] [image_picker_ios] Convert the
iOS example app and UI tests to Swift (flutter/packages#13570)
2026-11-10 [email protected]
[cupertino_ui] Localize CupertinoActionSheet semantics label
(flutter/packages#13377)
2026-11-10 [email protected] [camera_android]
Fix stopVideoRecording returning JPEG when takePicture runs during
recording (flutter/packages#13070)
2026-11-10 [email protected] [google_sign_in_android] Rename keep.xml
to google_sign_in_keep.xml (flutter/packages#13475)
2026-11-10 [email protected] [web_benchmarks] Fix benchmark stalling
when only repainting views that are dirty (flutter/packages#13089)
2026-11-10 [email protected] Roll Flutter from
d463821 to fffd8c2 (21 revisions) (flutter/packages#13614)

If this roll has caused a breakage, revert this CL and set the roller
to dry run mode using the controls here:
https://autoroll.skia.org/r/flutter-packages-flutter-autoroll
Please CC [email protected] on the revert to ensure that a
human
is aware of the problem.

To file a bug in Flutter:
https://github.com/flutter/flutter/issues/new/choose

To report a problem with the AutoRoller itself, please file a bug:
https://issues.skia.org/issues/new?component=1389291&template=1850622

Documentation for the AutoRoller is here:
https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

autosubmit Merge PR when tree becomes green via auto submit App CICD Run CI/CD p: camera platform-android

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[camera_android] stopVideoRecording() returns the JPEG path from takePicture() when a picture is taken during recording

4 participants