Skip to content

[camera_android_camerax] Add explicit concurrent-futures dependency - #12359

Closed
dhc-tech wants to merge 4 commits into
flutter:mainfrom
dhc-tech:fix/camerax-concurrent-futures-dependency
Closed

[camera_android_camerax] Add explicit concurrent-futures dependency#12359
dhc-tech wants to merge 4 commits into
flutter:mainfrom
dhc-tech:fix/camerax-concurrent-futures-dependency

Conversation

@dhc-tech

@dhc-tech dhc-tech commented Aug 4, 2026

Copy link
Copy Markdown

camera_android_camerax's Gradle module does not explicitly declare a dependency on androidx.concurrent:concurrent-futures. Verified via androidx.camera:camera-core:1.6.1's own Gradle module metadata (.module file): camera-core declares androidx.concurrent:concurrent-futures only on its runtime variant (releaseVariantReleaseRuntimePublication), not its api/compile variant (releaseVariantReleaseApiPublication). So when a consumer compiles against camera-core, Gradle correctly does not put concurrent-futures on the compile classpath — that's not a resolution bug, it's what camera-core's own metadata declares.

However, camera-core's compiled SurfaceRequest.class carries a compile-time-retained jspecify @NonNull type annotation on a member typed androidx.concurrent.futures.CallbackToFutureAdapter. javac needs that class on the compile classpath to fully process the annotation metadata during compilation — even though no camera_android_camerax (or camera-core) source calls it directly. This is a mismatch in camera-core's own packaging (a type needed at compile time for annotation processing, but declared runtime-only), which the Flutter team can't fix upstream since camera-core is owned by the AndroidX/Jetpack team. Declaring the dependency explicitly in camera_android_camerax works around it.

Confirmed 100% reproducible on a completely stock, uncustomized flutter create app on current stable (3.44.8, default AGP 9.0.1, compileSdk 37):

flutter create camera_repro
cd camera_repro
flutter pub add camera
flutter build apk --debug

fails every time with:

error: Cannot attach type annotations @org.jspecify.annotations.NonNull to
SurfaceRequest.mSurfaceRecreationCompleter: class file for
androidx.concurrent.futures.CallbackToFutureAdapter not found

Minimal repro repo (steps + README with root cause): https://github.com/dhc-tech/camera-android-camerax-build-repro

List which issues are fixed by this PR:

Fixes flutter/flutter#190505

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. This PR was prepared with AI assistance (Claude Code); I reviewed the diagnosis and the diff, reproduced the failure myself on a clean project, and verified the root cause against camera-core's published Gradle module metadata before submitting.
  • I read the Tree Hygiene page, which explains my responsibilities.
  • I read and followed the relevant style guides and ran the auto-formatter.
  • I signed the CLA.
  • The title of the PR starts with the name of the package surrounded by square brackets, e.g. [camera_android_camerax]
  • 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 (bumped to 0.7.4+5, rebased to avoid colliding with the real 0.7.4+4 release).
  • I updated/added any relevant documentation (doc comments with ///). N/A — no public API surface changed, only a build-file dependency.
  • I added new tests to check the change I am making: ConcurrentFuturesDependencyTest.java asserts CallbackToFutureAdapter resolves on the classpath, so it fails if the dependency is ever dropped again.
  • All existing and new tests are passing.

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

@flutter-dashboard

Copy link
Copy Markdown

It looks like this pull request may not have tests. Please make sure to add tests or get an explicit test exemption before merging.

If you are not sure if you need tests, consider this rule of thumb: the purpose of a test is to make sure someone doesn't accidentally revert the fix. Ask yourself, is there anything in your PR that you feel it is important we not accidentally revert back to how it was before your fix?

Reviewers: Read the Tree Hygiene page and make sure this patch meets those guidelines before LGTMing. If you believe this PR qualifies for a test exemption, contact "@test-exemption-reviewer" in the #hackers channel in Discord (don't just cc them here, they won't see it!). The test exemption team is a small volunteer group, so all reviewers should feel empowered to ask for tests, without delegating that responsibility entirely to the test exemption group.

@google-cla

google-cla Bot commented Aug 4, 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 adds an explicit dependency on androidx.concurrent:concurrent-futures to resolve compilation errors where CallbackToFutureAdapter annotations cannot be resolved. It also updates the package version to 0.7.4+4 and documents the change in the changelog. Feedback suggests using the stable version 1.2.0 of the dependency instead of 1.3.0 to prevent potential dependency resolution errors.

Comment thread packages/camera/camera_android_camerax/android/build.gradle.kts Outdated
@dhc-tech

dhc-tech commented Aug 4, 2026

Copy link
Copy Markdown
Author

Fixes flutter/flutter#190505

@dhc-tech

dhc-tech commented Aug 4, 2026

Copy link
Copy Markdown
Author

/gemini review

@flutter-dashboard: a regression test has been added in 7efa210 (ConcurrentFuturesDependencyTest.java) that asserts androidx.concurrent.futures.CallbackToFutureAdapter resolves on the classpath, so this fix cannot be silently reverted without a test failure.

@gemini-code-assist: please re-review with the latest commit — the concurrent-futures version is pinned to the stable 1.2.0 per earlier feedback, and a test now covers the fix.

@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 adds an explicit dependency on androidx.concurrent:concurrent-futures:1.2.0 in android/build.gradle.kts to resolve a compilation issue where CallbackToFutureAdapter was not found. It also introduces a regression test, ConcurrentFuturesDependencyTest, to verify that the class remains on the classpath, and updates the version to 0.7.4+4 in pubspec.yaml and CHANGELOG.md. There are no review comments, and I have no feedback to provide.

@digvijaysinh-cloudemy digvijaysinh-cloudemy left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Hi team, I encountered the exact same Gradle transform error on my setup after updating plugins. I can confirm that the changes in this PR fixed the issue for me as well.

Could someone please review and merge this when possible? Thanks! @justinmc PTAL

@stuartmorgan-g

Copy link
Copy Markdown
Collaborator

@digvijaysinh-cloudemy Please do not ping people like that. We have a documented process for routing PRs to appropriate reviewers, and it does not involve immediately pinging random Flutter team members who don't even work on the relevant package to individually ask them for review.

@stuartmorgan-g

stuartmorgan-g commented Aug 4, 2026

Copy link
Copy Markdown
Collaborator

Thank you for your contribution! Because of the volume of PRs we receive, we require that new contributors use our checklist to guide them through critical steps in creating a Flutter PR. This PR's description is not using our standard checklist, so it is being marked as a Draft.

Please edit the PR description to add the correct checklist, then ensure that you have completed all of the steps. Once you've done that, please mark the PR as ready for review.

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

Also, as previously discussed, it's not clear why this PR would be necessary, and neither the PR description nor the issue actually explain that; that's going to be a necessary first step for this being reviewable. It says:

camera_android_camerax's Gradle module does not explicitly declare a
dependency on androidx.concurrent:concurrent-futures, relying on it being
pulled in transitively via androidx.camera:camera-core.

but no explanation is given for why you believe it is a bug that the plugin does not declare a direct dependency on a library that the plugin does not appear to directly use. If you believe camera_android_camerax plugin code is directly relying on this library, please provide a link to the specific relevant code in the PR description.

camera-core's compiled classes carry jspecify @nonnull type annotations
on members that reference androidx.concurrent.futures.CallbackToFutureAdapter.
Since camera_android_camerax never declared that dependency directly, it
compiled fine as long as it was pulled in transitively — but under recent
AGP/Gradle resolution behavior it may not be, causing:

  error: Cannot attach type annotations @org.jspecify.annotations.NonNull to
  SurfaceRequest.mSurfaceRecreationCompleter: class file for
  androidx.concurrent.futures.CallbackToFutureAdapter not found

Declaring the dependency explicitly fixes compileDebugJavaWithJavac.
@dhc-tech

dhc-tech commented Aug 5, 2026

Copy link
Copy Markdown
Author

Rebased onto current main (version is now 0.7.4+5 to avoid colliding with the real 0.7.4+4 that landed in the meantime) and added a minimal, verified reproduction:

/gemini review

@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 adds an explicit dependency on androidx.concurrent:concurrent-futures:1.2.0 in build.gradle.kts to resolve compilation issues with CallbackToFutureAdapter annotations, along with a regression test to verify its presence on the classpath. Feedback suggests referencing CallbackToFutureAdapter.class statically in the test instead of using reflection (Class.forName) to ensure compile-time safety.

Comment on lines +30 to +39
try {
Class.forName("androidx.concurrent.futures.CallbackToFutureAdapter");
} catch (ClassNotFoundException e) {
fail(
"androidx.concurrent.futures.CallbackToFutureAdapter is not on the classpath. "
+ "This means the explicit androidx.concurrent:concurrent-futures dependency in "
+ "android/build.gradle.kts was removed or is no longer being resolved, which will "
+ "cause compileDebugJavaWithJavac to fail for consumers of this plugin. "
+ "See https://github.com/flutter/flutter/issues/190505.");
}

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.

medium

Using reflection (Class.forName) to check for the presence of a class on the classpath defers the check to runtime. Referencing the class statically (e.g., androidx.concurrent.futures.CallbackToFutureAdapter.class) provides compile-time safety. If the dependency is accidentally removed, the build will fail during compilation, which is more robust and standard in Java than a runtime test failure.

    org.junit.Assert.assertNotNull(androidx.concurrent.futures.CallbackToFutureAdapter.class);

@dhc-tech
dhc-tech marked this pull request as ready for review August 5, 2026 04:29

@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 adds an explicit androidx.concurrent:concurrent-futures:1.2.0 dependency to the camera_android_camerax package's Android build configuration to resolve a compilation failure where CallbackToFutureAdapter is not found. It also introduces a regression test ConcurrentFuturesDependencyTest to verify the presence of this class on the classpath, and bumps the package version to 0.7.4+4 in pubspec.yaml and CHANGELOG.md. There are no review comments, and I have no feedback to provide.

Referencing CallbackToFutureAdapter.class directly means the test target
fails to compile (rather than a runtime ClassNotFoundException) if the
concurrent-futures dependency is ever removed, which is a stronger and
more immediate signal.
@dhc-tech
dhc-tech force-pushed the fix/camerax-concurrent-futures-dependency branch from 7efa210 to 53a7455 Compare August 5, 2026 04:34
@dhc-tech

dhc-tech commented Aug 5, 2026

Copy link
Copy Markdown
Author

Closing in favor of a clean recreation with the same fix and all review feedback applied: #12373

@dhc-tech dhc-tech closed this Aug 5, 2026
@dhc-tech
dhc-tech deleted the fix/camerax-concurrent-futures-dependency branch August 6, 2026 18:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[camera_android_camerax] Build failure: class file for androidx.concurrent.futures.CallbackToFutureAdapter not found during Java compilation

3 participants