Skip to content

fix(google): avoid r8 billing reflection - #309

Merged
hyochan merged 1 commit into
mainfrom
fix/google-r8-subscription-replacement
Aug 11, 2026
Merged

hyochan merged 1 commit into
mainfrom
fix/google-r8-subscription-replacement

Conversation

@hyochan

@hyochan hyochan commented Aug 10, 2026 •

Copy link
Copy Markdown
Member

Summary

  • replace reflection-based SubscriptionProductReplacementParams construction with typed Play Billing 9.1 API calls
  • add direct native-builder coverage for every subscription replacement mode
  • remove obsolete class-path reflection tests for this now-statically-linked API

Why

Minified Android release apps could have Billing classes or methods optimized in ways the name-based reflection path could not follow. Using typed calls lets R8 trace and rewrite those references without requiring a package-wide Billing keep rule. The change is isolated to the Play source set; Horizon and Amazon do not compile this code.

Verification

  • :openiap:test
  • Play, Horizon, and Amazon debug Kotlin compilation
  • Play, Horizon, and Amazon release AAR assembly
  • :openiap:lintPlayRelease
  • Kotlin 2.1 Play, Horizon, and Amazon consumer verification
  • bun audit:parity
  • minified Play :Example:assemblePlayRelease with R8; confirmed the merged configuration contains no broad -keep class com.android.billingclient.api.** { *; } workaround

A live Google Play Sandbox replacement purchase was not performed because it requires an active subscription and store-authorized test account. Reporter validation of the resulting snapshot is still recommended for the final store-backed runtime check.

Closes #307

Summary by CodeRabbit

  • Bug Fixes

    • Improved subscription replacement handling by using the supported Google Play Billing conversion, helping replacement requests work reliably with current billing APIs.
    • Removed outdated compatibility logic that could cause errors during subscription changes.
  • Tests

    • Added coverage confirming all supported replacement modes produce the expected billing parameters.

Use typed Play Billing APIs for product-level subscription replacement parameters so R8 can safely optimize release apps.

Replace obsolete reflection-path tests with direct builder coverage.

Closes #307
@coderabbitai

coderabbitai Bot commented Aug 10, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: d1950140-a05f-4bcc-9fc7-c2c5d2c5f388

📥 Commits

Reviewing files that changed from the base of the PR and between 1ede6c5 and 742d075.

📒 Files selected for processing (4)
  • packages/google/openiap/src/play/java/dev/hyo/openiap/OpenIapModule.kt
  • packages/google/openiap/src/play/java/dev/hyo/openiap/SubscriptionReplacementModeAndroidExt.kt
  • packages/google/openiap/src/test/java/dev/hyo/openiap/BillingLibraryClassPathTest.kt
  • packages/google/openiap/src/testPlay/java/dev/hyo/openiap/SubscriptionReplacementModeTest.kt

📝 Walkthrough

Walkthrough

The Android subscription replacement flow now uses typed Billing Library builders instead of reflection. Tests cover native parameter conversion for all replacement modes, and obsolete reflection-based class-path tests are removed.

Changes

Subscription replacement conversion

Layer / File(s) Summary
Native replacement parameter conversion
packages/google/openiap/src/play/java/dev/hyo/openiap/SubscriptionReplacementModeAndroidExt.kt, packages/google/openiap/src/play/java/dev/hyo/openiap/OpenIapModule.kt
The module applies typed Billing Library replacement parameters. The conversion sets the old product ID and native replacement mode.
Conversion test updates
packages/google/openiap/src/testPlay/java/dev/hyo/openiap/SubscriptionReplacementModeTest.kt, packages/google/openiap/src/test/java/dev/hyo/openiap/BillingLibraryClassPathTest.kt
Play tests cover every replacement mode. Obsolete reflection-based class-path tests and their unused helper are removed.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

  • hyodotdev/openiap#52: This PR refines the earlier subscription replacement implementation in OpenIapModule.kt.
  • hyodotdev/openiap#72: Both PRs update replacement-mode mapping from reflection-based handling to native Billing Library APIs.
  • hyodotdev/openiap#96: Both PRs update SubscriptionReplacementModeAndroidExt.kt and its tests.

Suggested labels: ፦ refactor, 🧪 test

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: replacing Billing reflection to avoid R8 failures in Google Play builds.
Linked Issues check ✅ Passed The changes replace reflective Billing calls with typed APIs and add coverage, directly addressing the release-only subscription replacement failure in issue #307.
Out of Scope Changes check ✅ Passed The changes are limited to the Play implementation and related tests, with no unrelated code or platform changes.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/google-r8-subscription-replacement

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@hyochan hyochan added expo-iap expo-iap library 🐛 bug Something isn't working 🤖 android Related to android labels Aug 10, 2026
@hyochan
hyochan merged commit d7d7d2e into main Aug 11, 2026
17 checks passed
@hyochan
hyochan deleted the fix/google-r8-subscription-replacement branch August 11, 2026 00:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🤖 android Related to android 🐛 bug Something isn't working expo-iap expo-iap library

Projects

None yet

Development

Successfully merging this pull request may close these issues.

expo-iap ships no consumer ProGuard rules — subscription replacement fails silently in release builds

1 participant