fix(expo): seed Clerk activity ref on cold-start to fix MissingActivity (MOBILE-485)#8485
fix(expo): seed Clerk activity ref on cold-start to fix MissingActivity (MOBILE-485)#8485chriscanin wants to merge 1 commit intomainfrom
Conversation
…ty (MOBILE-485)
clerk-android tracks the current foreground Activity via
ActivityLifecycleCallbacks registered inside Clerk.initialize(). In a
React Native app, MainActivity has already passed onResume() by the time
<ClerkProvider> mounts and configure() runs, so the callbacks miss the
initial Activity. Without seeding, the first Credential Manager call
(Google sign-in, passkeys) fails with MissingActivity until the user
backgrounds and foregrounds the app.
Adopt the new public Clerk.attachActivity() API from clerk-android 1.0.16
to seed the Activity reference at two reliable points: in
ClerkExpoModule.configure() right after Clerk.initialize() (using
React's currentActivity), and in ClerkAuthNativeView's findActivity()
result. The second hook is the empirically-reliable backstop — at cold
start, getCurrentActivity() may return null before React's host-resume
sync, but ClerkAuthNativeView is constructed when AuthView mounts, by
which point the Activity is unambiguously available.
Bumps clerk-android-{api,ui} to 1.0.16. Adds an explicit clerk-android-api
dep to override telemetry's transitive pin on the previous release —
without this the version constraint loses the conflict and consumers end
up on the older artifact (which lacks attachActivity).
🦋 Changeset detectedLatest commit: 5aecdf2 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
@clerk/astro
@clerk/backend
@clerk/chrome-extension
@clerk/clerk-js
@clerk/dev-cli
@clerk/expo
@clerk/expo-passkeys
@clerk/express
@clerk/fastify
@clerk/hono
@clerk/localizations
@clerk/nextjs
@clerk/nuxt
@clerk/react
@clerk/react-router
@clerk/shared
@clerk/tanstack-react-start
@clerk/testing
@clerk/ui
@clerk/upgrade
@clerk/vue
commit: |
📝 WalkthroughWalkthroughThis pull request addresses MissingActivity errors during cold-start sign-in flows by ensuring the Android Activity is registered with the Clerk SDK before credential operations. The changes include: (1) updating Android dependency versions from 1.0.13 to 1.0.16 and adding the clerk-android-api dependency; (2) invoking Clerk.attachActivity() at SDK initialization in ClerkExpoModule and during view initialization in ClerkAuthExpoView; and (3) documenting the patch in a changeset. No public API signatures are modified, and the fix is transparent on rebuild. Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. 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. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
packages/expo/android/src/main/java/expo/modules/clerk/ClerkExpoModule.kt (1)
72-162: ⚡ Quick winNo automated tests cover the cold-start fix
No tests are added or modified in this PR. Per project guidelines, test coverage is expected for changed paths. At minimum, a unit test mocking
Clerk.isInitialized,getCurrentActivity(), and verifyingClerk.attachActivity()is called (or gracefully skipped when null) in bothconfigure()and theClerkAuthNativeViewconstructor would prevent regressions.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/expo/android/src/main/java/expo/modules/clerk/ClerkExpoModule.kt` around lines 72 - 162, The PR lacks tests for the cold-start activity attach logic: add unit tests that mock Clerk.isInitialized, getCurrentActivity(), and Clerk.attachActivity() to cover the new behavior in configure() and the ClerkAuthNativeView constructor; specifically, create tests that (1) simulate cold start when Clerk.isInitialized is false and getCurrentActivity() returns a non-null Activity and assert Clerk.attachActivity(activity) is invoked, (2) simulate cold start with getCurrentActivity() returning null and assert no attachActivity call is made (graceful skip), and (3) cover the already-initialized path where configure() updates the bearer token (mock Clerk.updateDeviceToken and Clerk.sessionFlow) to ensure session wait logic runs without attaching activity. Ensure tests stub/restore Clerk.isInitialized, Clerk.initializationError, Clerk.sessionFlow, getCurrentActivity(), and Clerk.attachActivity() so they deterministically exercise both branches.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@packages/expo/android/src/main/java/expo/modules/clerk/ClerkExpoModule.kt`:
- Around line 72-162: The PR lacks tests for the cold-start activity attach
logic: add unit tests that mock Clerk.isInitialized, getCurrentActivity(), and
Clerk.attachActivity() to cover the new behavior in configure() and the
ClerkAuthNativeView constructor; specifically, create tests that (1) simulate
cold start when Clerk.isInitialized is false and getCurrentActivity() returns a
non-null Activity and assert Clerk.attachActivity(activity) is invoked, (2)
simulate cold start with getCurrentActivity() returning null and assert no
attachActivity call is made (graceful skip), and (3) cover the
already-initialized path where configure() updates the bearer token (mock
Clerk.updateDeviceToken and Clerk.sessionFlow) to ensure session wait logic runs
without attaching activity. Ensure tests stub/restore Clerk.isInitialized,
Clerk.initializationError, Clerk.sessionFlow, getCurrentActivity(), and
Clerk.attachActivity() so they deterministically exercise both branches.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository YAML (base), Organization UI (inherited)
Review profile: CHILL
Plan: Pro
Run ID: 97a113e5-4d3a-424b-86f0-729ba5c023a0
📒 Files selected for processing (4)
.changeset/expo-mobile-485-cold-start-activity.mdpackages/expo/android/build.gradlepackages/expo/android/src/main/java/expo/modules/clerk/ClerkAuthExpoView.ktpackages/expo/android/src/main/java/expo/modules/clerk/ClerkExpoModule.kt
Summary
Fixes MOBILE-485.
Customer-reported bug (T-57530, M2X Group, Business tier): on
@clerk/expo@3.2.x, the first tap on "Sign in with Google" in<AuthView />after a cold launch silently fails. Logcat shows:The workaround was to background and foreground the app once before signing in.
Root cause
clerk-androidtracks the current foregroundActivityviaActivityLifecycleCallbacksregistered insideClerk.initialize(). The callbacks only fire on subsequentonActivityCreated/Started/Resumedevents — they don't observe the host Activity's current state at the momentinitialize()runs.In React Native,
MainActivityhas already passedonResume()by the time<ClerkProvider />mounts andconfigure()runs, so when we callClerk.initialize(), the just-registered callbacks miss the initial Activity.Clerk.currentActivitystays null until the next OS-driven resume cycle — which is why backgrounding and re-foregrounding the app "fixes" it.Fix
The proper fix lives in
clerk-android: it now exposes a publicClerk.attachActivity(activity)API in 1.0.16 for hosts that pass an Application-typed Context toinitialize()but have a current Activity available.This PR adopts that API at two reliable points:
ClerkExpoModule.configure()— right afterClerk.initialize(), callsClerk.attachActivity(getCurrentActivity()). May be a no-op on cold start if React's host-resume sync hasn't fired yet, but covers the warm-init case.ClerkAuthNativeViewconstructor — callsClerk.attachActivity()with the Activity returned byfindActivity(context). This is the empirically-reliable backstop: by the time the AuthView is being constructed, the host Activity is unambiguously available.Bumps
clerk-android-{api,ui}to1.0.16. Also adds an explicitclerk-android-apidep — without it, telemetry's transitive pin on the prior release wins the version conflict and consumers end up on the older artifact (which doesn't haveattachActivity).Test plan
@clerk/expo@3.2.7against a Pixel 9 Pro emulator (Android 16). Cold-launch viapm clear+ deep-link, tap Google as first action —E/ClerkLog: Clerk error: Google sign-in cannot start: Credential Manager requires an active Activity context.in logcat, silent failure on JS, stuck on AuthView.@clerk/expoagainst this branch (consumingclerk-android1.0.16 via local Maven), reran the same reproduction:I/CredentialManager: starting executeGetCredential→[GetGoogleIdOperation] Operation succeeded→ Google account picker opens, sign-in completes, lands on the Welcome screen.MissingActivityin logcat.pm clearand force-stop — could not reproduce the error.Gating
This PR depends on clerk/clerk-android#614 shipping as
1.0.16. The build will fail at theclerk_expo:compileDebugKotlinstep until that release is published to Maven Central.