Skip to content

feat(android): support mParticle Android SDK 6#358

Merged
thomson-t merged 9 commits into
mainfrom
thomson-t/mparticle-android-6-upgrade
Jul 24, 2026
Merged

feat(android): support mParticle Android SDK 6#358
thomson-t merged 9 commits into
mainfrom
thomson-t/mparticle-android-6-upgrade

Conversation

@thomson-t

@thomson-t thomson-t commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Summary

Support mParticle Android SDK 6 for the React Native Android bridge and Rokt integrations. The bridge now uses the SDK 6 user attribute and Rokt kit APIs while keeping the existing JavaScript Rokt API surface. Android Rokt native module and view registration is guarded when the Android Rokt kit is not present, and iOS native module loading keeps the existing fail-fast behavior.

The Expo config plugin and sample Android app now use bounded 6.x Android kit dependency ranges. The migration docs describe the Android SDK 6 Rokt requirements for SDK consumers and avoid release-generated changelog or version updates.

Testing Plan

  • yarn build
  • yarn build:plugin
  • yarn test
  • cd android && ./gradlew test lint ktlintCheck
  • trunk check --ci
  • yarn dev:pack
  • cd sample && yarn install --no-lockfile --ignore-scripts (with Node >=22.11.0)
  • cd sample/android && ./gradlew assembleDebug

Update the Android bridge to compile against mParticle Android SDK 6 and the Rokt kit APIs while keeping the existing React Native Rokt JavaScript surface. The Expo config plugin and sample now use bounded 6.x Android kit ranges, and migration docs describe the SDK and build requirements for app developers.
@thomson-t
thomson-t requested a review from a team as a code owner July 22, 2026 21:21
Copilot AI review requested due to automatic review settings July 22, 2026 21:21
@cursor

cursor Bot commented Jul 22, 2026

Copy link
Copy Markdown

PR Summary

High Risk
Major Android SDK bump with Rokt API, threading, and New Architecture event-path changes; apps must upgrade Gradle/compileSdk and matching Maven artifacts.

Overview
Android SDK 6 — Core and Rokt kit dependencies move from 5.x to [6.0.0, 7.0) (library, sample, Expo plugin). Docs call out compileSdk 35+ and AGP 8.6+ when using android-rokt-kit 6.0.0, plus a new MIGRATING.md section for Android 6.

BridgegetUserAttributes switches to TypedUserAttributeListener (SDK 6). MParticlePackage only registers RNMPRokt and RoktLayoutView when com.mparticle.kits.RoktEmbeddedView is on the classpath; JS MParticle.Rokt throws a clear error if the module is missing on Android.

Rokt native — Calls use MParticle.rokt and kit types under com.mparticle.kits, with Rokt SDK types from com.rokt.roktsdk. selectPlacements no longer passes MpRoktEventCallback; load/unload/loading callbacks are driven from the RoktEvent flow. close and Fabric selectPlacements run on the main thread. Embedded layout events use EventDispatcher (New Arch–safe); onLayoutMarginChanged is removed from codegen and RoktLayoutView. Fabric RoktLayoutViewManager adds the codegen delegate.

Reviewed by Cursor Bugbot for commit cc78cff. Bugbot is set up for automated code reviews on this repo. Configure here.

Copilot AI 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.

Pull request overview

Updates the React Native mParticle Android integration to support mParticle Android SDK 6, including the updated Rokt kit APIs, while keeping the existing JavaScript Rokt API surface. It also adjusts dependency ranges and documentation to reflect the new Android SDK/kit requirements, and guards Android Rokt module/view registration when the kit is not present.

Changes:

  • Bump Android core/kit dependency ranges to the supported 6.x line across the library, config plugin, and sample app.
  • Update Android bridge implementation for SDK 6 (Rokt API changes; typed user attribute listener).
  • Gate Android Rokt TurboModule + view manager registration when the Android Rokt kit is not on the classpath; keep iOS behavior unchanged.

Reviewed changes

Copilot reviewed 16 out of 16 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
sample/README.md Updates sample app guidance for Android SDK 6 Rokt dependencies/requirements.
sample/android/app/build.gradle Bumps sample Android dependencies to mParticle 6.x ranges.
README.md Updates public docs for Android Rokt requirements with SDK 6.
plugin/src/withMParticleAndroid.ts Updates Expo config plugin kit injection to 6.x bounded ranges.
MIGRATING.md Adds migration notes for Android SDK 6 / Rokt requirements.
js/rokt/rokt.ts Makes Android Rokt module resolution conditional and throws when unavailable.
ExpoTestApp/README.md Updates Expo test app docs/examples for Android SDK 6 Rokt requirements and dependency range.
android/src/oldarch/java/com/mparticle/react/rokt/RoktLayoutViewManager.kt Updates Rokt embedded view import for SDK 6 kit package.
android/src/oldarch/java/com/mparticle/react/rokt/MPRoktModule.kt Updates old-arch Rokt module to SDK 6 rokt API usage.
android/src/newarch/java/com/mparticle/react/rokt/RoktLayoutViewManager.kt Updates new-arch view manager to SDK 6 kit package import and formatting.
android/src/newarch/java/com/mparticle/react/rokt/MPRoktModule.kt Updates new-arch Rokt module to SDK 6 rokt API usage.
android/src/main/java/com/mparticle/react/rokt/RoktLayoutViewManagerImpl.kt Updates imports for SDK 6 kit callback types and removes obsolete callback handling.
android/src/main/java/com/mparticle/react/rokt/MPRoktModuleImpl.kt Reworks event/callback bridging to SDK 6 Rokt events and config types.
android/src/main/java/com/mparticle/react/MParticlePackage.kt Guards Android Rokt module and view registration when kit is absent.
android/src/main/java/com/mparticle/react/MParticleModule.kt Migrates user attribute retrieval to SDK 6 typed attribute listener.
android/build.gradle Moves library core dependency to 6.x range and adds compileOnly Rokt kit + test deps.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread sample/README.md Outdated
Comment thread js/rokt/rokt.ts Outdated
Comment thread js/rokt/rokt.ts Outdated
Comment thread js/rokt/rokt.ts Outdated
Comment thread android/src/main/java/com/mparticle/react/MParticlePackage.kt Outdated
thomson-t and others added 3 commits July 23, 2026 10:59
…TEventEmitter

The Rokt embedded layout view manager emitted its height-changed event through
`context.getJSModule(RCTEventEmitter).receiveEvent(...)`. Under the New
Architecture bridgeless runtime (default on RN >= 0.76, the wrapper's floor)
this logs an `IllegalArgumentException` SoftException on every height change
and stops working entirely once the Fabric interop layer is disabled — which
would drop the height event and leave embedded placements mis-sized.

Replace it with `UIManagerHelper.getEventDispatcherForReactTag` + an `Event`
subclass overriding `getEventData()`. This is the RN-recommended path and works
on both Paper and Fabric across all supported RN versions, from a single
`main/` implementation (no arch/version branching).

Also remove the dead margin path (`changeMargin`, `EVENT_MARGIN_CHANGED`,
`onLayoutMarginChanged`, `MarginChangedEvent`): mParticle Android SDK 6's
`RoktLayoutDimensionCallBack` only exposes `onHeightChanged`, so nothing ever
fired the margin event. iOS never emitted it either (height flows via the
separate RoktEventManager emitter), so dropping it from the shared codegen
spec is safe on both platforms.

Verified: sample app builds, embedded placement renders to interactive at the
correct height with no SoftException in logcat.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Under the New Architecture, `RoktLayoutViewManager` implements the
codegen-generated `RoktNativeLayoutManagerInterface` but never returned a
delegate from `getDelegate()`. On every view creation Fabric calls
`getOrCreateViewManagerDelegate()`, the base ViewManager returns null and logs
`ReactNoCrashSoftException: ViewManager using codegen must override getDelegate
method (name: RoktNativeLayout)`, and the `placeholderName` prop is not routed
through the generated delegate.

Instantiate `RoktNativeLayoutManagerDelegate` and return it from
`getDelegate()`. The delegate's `setProperty` now owns prop dispatch, so the
redundant `@ReactProp` annotation is removed. Explicit generic type arguments
are supplied because Kotlin cannot infer the delegate's intersection-bounded
type parameter.

newarch source set only; the Paper `ViewGroupManager` path uses no codegen
delegate and is unaffected.

Verified: sample app builds, embedded placement renders to interactive with no
getDelegate SoftException.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Under the New Architecture, `MPRoktModule.selectPlacements` invoked the SDK's
`rokt.selectPlacements(...)` on the TurboModule thread. mParticle Android SDK
6's `RoktKit.selectPlacements` clears prior placeholder content with
`ViewGroup.removeAllViews()`, which detaches the now Compose-based Rokt widget
and triggers `LifecycleRegistry.removeObserver` — hard-enforced to the main
thread. Showing an embedded placement then another placement crashed with
`IllegalStateException: Method removeObserver must be called on the main thread`.

The bug was latent before SDK 6 (the old View-based widget tolerated the
off-thread detach); the Compose migration turned it into a deterministic crash.

Resolve placeholder views and call the SDK together inside a single
`UiThreadUtil.runOnUiThread {}`, dropping the CountDownLatch (which also removed
a blocking cross-thread wait on the module thread). Guard `close()` the same
way, since `rokt.close()` detaches overlay Compose views. This matches the
oldarch path (`UIManager.addUIBlock`) and iOS (uiManager methodQueue), both of
which already dispatch on the main thread and were unaffected.

Verified: embedded → overlay no longer crashes and both render to interactive;
ROKT CLOSE dismisses the overlay (PlacementClosed) with no exception.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Comment thread android/src/main/java/com/mparticle/react/MParticleModule.kt
… managers

Join single-expression bodies onto their signatures (getEventData,
createViewInstance) and wrap the multi-parameter setPlaceholderName signature,
matching the repo's existing Kotlin style and clearing the
standard:function-signature violations from ktlintMainSourceSetCheck.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

@cursor cursor Bot 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.

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

There are 2 total unresolved issues (including 1 from previous review).

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 9204e57. Configure here.

Comment thread android/src/main/java/com/mparticle/react/rokt/MPRoktModuleImpl.kt
thomson-t and others added 4 commits July 23, 2026 14:05
These three methods are typed to return a Promise but called getMPRokt()
synchronously, so a missing-native-module error threw synchronously instead of
rejecting the returned Promise — inconsistent with the type signature and with
the sibling methods (selectPlacements, selectShoppableAds, purchaseFinalized),
which are already async. A caller using `.catch()` would miss the error.

Mark them async so the getMPRokt() throw surfaces as a rejected Promise. Return
types are unchanged, so this is non-breaking; native promise resolution is
unaffected. Addresses copilot PR review comments on js/rokt/rokt.ts.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
isRoktKitAvailable() ran a reflective Class.forName on each of its four call
sites during module and view-manager registration at startup. The kit's
presence on the classpath is fixed for the app's lifetime, so convert it to a
`by lazy` val that performs the reflection once. Addresses copilot PR review
comment on MParticlePackage.kt.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
State that both com.mparticle:android-core and android-rokt-kit are pinned to
[6.0.0, 7.0) (removes the ambiguity flagged in review) and drop the Android
CNAME mention. Addresses copilot PR review comment on sample/README.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Rewrap the Android dependency paragraph so a line no longer begins with "36."
(which prettier/markdown would treat as an ordered-list item), satisfying the
trunk prettier check.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@thomson-t
thomson-t merged commit 6e881eb into main Jul 24, 2026
11 checks passed
@thomson-t
thomson-t deleted the thomson-t/mparticle-android-6-upgrade branch July 24, 2026 15:10
@rokt-releases rokt-releases Bot mentioned this pull request Jul 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants