Skip to content

Keep ActivityResultContract class names in R8 builds - #59700

Draft
tomekzaw wants to merge 2 commits into
react:mainfrom
tomekzaw:fix-activity-result-contract-names
Draft

tomekzaw wants to merge 2 commits into
react:mainfrom
tomekzaw:fix-activity-result-contract-names

Conversation

@tomekzaw

Copy link
Copy Markdown
Contributor

Summary:

ReactActivityResultCaller keys each launcher by "<owner class>:<contract class>". With R8 enabled, it can merge different contract classes into one class (horizontal class merging), so they end up with the same name. For example, in a minified RNTester build, ActivityResultContracts.RequestPermission, PickVisualMedia and GetContent were all merged into a class named e2. Registering a second contract from the same owner then throws IllegalStateException: A launcher is already registered for key '…:e2'. That's why SampleTurboModule fails to initialize in a minified RNTester.

This adds a consumer R8 rule that keeps the names of ActivityResultContract subclasses, which stops R8 from merging or renaming them. Unused contracts can still be removed. It also keeps the keys stable between builds, which the docs ask for. The docs now mention the rule.

Changelog:

[INTERNAL] [FIXED] - Keep ActivityResultContract class names in R8 builds so that activity result launcher keys don't collide

Test Plan:

Minified release RNTester: ./gradlew :packages:rn-tester:android:app:assembleRelease -PreactNativeArchitectures=arm64-v8a, with enableProguardInReleaseBuilds = true.

  • R8 mapping:
    • main: ActivityResultContracts$GetContent -> e2, a merged class with an $r8$classId field.
    • This PR: every contract keeps its own name, for example ActivityResultContracts$RequestPermission -> ActivityResultContracts$RequestPermission.
  • On a Galaxy A16 (Android 16), from a Playground screen that calls SampleTurboModule:
    • main: Exception in HostObject::get for prop 'SampleTurboModule': java.lang.IllegalStateException: A launcher is already registered for key 'com.facebook.fbreact.specs.SampleTurboModule:e2'
    • This PR: the module initializes, and getObject, getArray and getConstants return the expected values.

🤖 Generated with Claude Code

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Oct 30, 2026
@facebook-github-tools facebook-github-tools Bot added p: Software Mansion Partner: Software Mansion Partner labels Oct 30, 2026
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. p: Software Mansion Partner: Software Mansion Partner

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant