Skip to content

test(sample): add opt-in deferred-init edge-case example (Android)#341

Merged
nickolas-dimitrakas merged 4 commits into
mainfrom
nickolas-dimitrakas/sample-deferred-init-example
Jun 19, 2026
Merged

test(sample): add opt-in deferred-init edge-case example (Android)#341
nickolas-dimitrakas merged 4 commits into
mainfrom
nickolas-dimitrakas/sample-deferred-init-example

Conversation

@nickolas-dimitrakas

Copy link
Copy Markdown
Contributor

What

Adds a small, disabled-by-default example to the sample app that reproduces the Android deferred-initialisation edge case: starting mParticle from a native module at first-frame paint instead of MainApplication.onCreate().

Why

A partner deferring MParticle.start() (to shave init cost off startup) saw flaky Rokt overlay placements on Android but not iOS. Root cause: the Rokt Android SDK (≤ v5) caches the current Activity only on onActivityResumed, via an observer registered during Rokt.init() (which mParticle calls from RoktKit.onKitCreate()). When init runs after the host Activity has already resumed — exactly what deferred init does — that resume is missed, so overlay/bottom-sheet placements can't display until the next resume (the "press home and reopen" workaround). iOS resolves the presenter lazily at execute time, so it's unaffected.

Fixed upstream in the Rokt Android SDK: ROKT/sdk-android-source #1062 / #1063 (v5 backport #1082). This example is kept around as an easy way to re-trigger the scenario and confirm the fix / catch regressions.

How it works

  • DeferredInitModule (native) starts mParticle when JS calls it at first-frame paint (requestAnimationFrame in index.js).
  • ActivityTracker mirrors Rokt's Activity-capture: an EAGER instance registered at process start vs a DEFERRED instance registered at init time. With the example on, EAGER captures MainActivity while DEFERRED stays null — the race, visible via adb logcat -s DeferredInitRepro.

Default behaviour unchanged

DeferredInitModule.DEFERRED_INIT_EXAMPLE defaults to false, so the sample uses the standard eager init in MainApplication.onCreate(). Flip it to true to reproduce. See sample/README.md → "Deferred-init edge case (Android)".

Validation

  • :app:compileDebugKotlin passes (default flag off).
  • Earlier, with the flag on, the race + the background/foreground recovery were reproduced on an emulator (logcat captured).

Adds a self-contained, disabled-by-default example that reproduces the
Android late-initialisation Activity-capture race: starting mParticle from a
native module at first-frame paint instead of Application.onCreate().

The Rokt SDK (<= v5) caches the current Activity only on onActivityResumed
(registered during Rokt.init() via RoktKit.onKitCreate()), so deferring init
past the host Activity's resume leaves overlay placements unable to display
until the next resume. iOS is unaffected. Fixed upstream in the Rokt Android
SDK (ROKT/sdk-android-source #1062, #1063; v5 backport #1082).

Default sample behaviour is unchanged (standard eager init). Flip
DeferredInitModule.DEFERRED_INIT_EXAMPLE to true to reproduce; the EAGER vs
DEFERRED ActivityTracker logs (adb logcat -s DeferredInitRepro) make the race
observable. Kept around as an easy regression/verification fixture.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings June 19, 2026 17:34
@nickolas-dimitrakas nickolas-dimitrakas requested a review from a team as a code owner June 19, 2026 17:34
@cursor

cursor Bot commented Jun 19, 2026

Copy link
Copy Markdown

PR Summary

Low Risk
Sample-only, flag defaults false so production-style eager init is unchanged; no SDK or auth changes.

Overview
Adds a disabled-by-default Android sample path that starts mParticle after first-frame paint (via a new DeferredInit native module) instead of in Application.onCreate(), to reproduce the late-init Activity capture race that broke Rokt overlay/bottom-sheet placements when init missed onActivityResumed.

ActivityTracker contrasts EAGER (lifecycle registered at process start) vs DEFERRED (registered at init time) with adb logcat -s DeferredInitRepro. MainApplication branches on DEFERRED_INIT_EXAMPLE; index.js calls DeferredInit.startMParticle() from requestAnimationFrame on Android only (no-op when the flag is off). README documents how to enable the repro and notes that early JS mParticle calls are no-ops until init completes when deferred mode is on.

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

Comment thread sample/index.js Outdated

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

Adds an opt-in (disabled-by-default) repro path in the sample app to demonstrate the Android deferred-initialization / missed-onActivityResumed race that affects Rokt overlay placements when MParticle.start() happens after the host Activity is already resumed.

Changes:

  • Document the deferred-init edge case and repro steps in the sample README.
  • Trigger a first-frame requestAnimationFrame call in JS to start mParticle via a native module (for the repro).
  • Add Android sample native code (DeferredInitModule, DeferredInitPackage, ActivityTracker) and wire it into MainApplication.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
sample/README.md Adds documentation and steps to enable/reproduce the Android deferred-init race.
sample/index.js Adds first-frame JS hook to invoke the Android deferred-init native module.
sample/android/app/src/main/java/com/mparticlesample/MainApplication.kt Adds the package + conditional eager-vs-deferred init path.
sample/android/app/src/main/java/com/mparticlesample/DeferredInitPackage.kt Registers the Android native module via a ReactPackage.
sample/android/app/src/main/java/com/mparticlesample/DeferredInitModule.kt Implements the deferred-start entry point called from JS.
sample/android/app/src/main/java/com/mparticlesample/ActivityTracker.kt Adds a lifecycle tracker to mirror Rokt’s Activity capture behavior.

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

Comment thread sample/index.js Outdated
Comment thread sample/android/app/src/main/java/com/mparticlesample/DeferredInitModule.kt Outdated
@nickolas-dimitrakas nickolas-dimitrakas self-assigned this Jun 19, 2026
nickolas-dimitrakas and others added 2 commits June 19, 2026 13:52
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…empotent

Addresses review feedback:
- index.js: only run the first-frame DeferredInit call on Android, so iOS no
  longer logs a spurious 'module not available' warning every launch.
- DeferredInitModule: short-circuit startMParticle() when MParticle is already
  started, so repeat JS calls (Fast Refresh / remounts) don't double-register
  lifecycle callbacks or re-start the SDK.

Co-Authored-By: Claude Opus 4.8 <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.

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 52e1059. Configure here.

Comment thread sample/index.js
Documents the expected secondary deferred-init hazard flagged in review: with
DEFERRED_INIT_EXAMPLE on, mParticle JS calls made before first-frame start are
no-ops until the SDK starts. Default (eager) behaviour is unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@nickolas-dimitrakas nickolas-dimitrakas merged commit c5f6350 into main Jun 19, 2026
11 checks passed
@nickolas-dimitrakas nickolas-dimitrakas deleted the nickolas-dimitrakas/sample-deferred-init-example branch June 19, 2026 18:43
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.

3 participants