Skip to content

Commit 3b74d9a

Browse files
authored
fix(expo): seed Clerk activity ref on cold-start to fix MissingActivity (MOBILE-485) (#8485)
1 parent 3ffbe1f commit 3b74d9a

4 files changed

Lines changed: 37 additions & 3 deletions

File tree

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
"@clerk/expo": patch
3+
---
4+
5+
Fix `MissingActivity` error on cold-start Google sign-in / passkey flows. Previously, the first tap on "Sign in with Google" in `<AuthView />` failed with `Clerk error: Google sign-in cannot start: Credential Manager requires an active Activity context.` — the workaround was to background and foreground the app once before signing in.
6+
7+
The Android bridge now calls `Clerk.attachActivity()` (added in clerk-android 1.0.16) at SDK initialization and on AuthView/UserProfile mount, so the current Activity is registered with the underlying SDK before any Credential Manager call. No app-side changes required; the fix is transparent on rebuild.

packages/expo/android/build.gradle

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ ext {
1818
credentialsVersion = "1.3.0"
1919
googleIdVersion = "1.1.1"
2020
kotlinxCoroutinesVersion = "1.7.3"
21-
clerkAndroidApiVersion = "1.0.13"
22-
clerkAndroidUiVersion = "1.0.13"
21+
clerkAndroidApiVersion = "1.0.16"
22+
clerkAndroidUiVersion = "1.0.16"
2323
composeVersion = "1.7.0"
2424
activityComposeVersion = "1.9.0"
2525
lifecycleVersion = "2.8.0"
@@ -117,6 +117,16 @@ dependencies {
117117
exclude group: 'com.squareup.okhttp3', module: 'okhttp'
118118
exclude group: 'com.squareup.okhttp3', module: 'okhttp-urlconnection'
119119
}
120+
// clerk-android-telemetry has a transitive dep on the last released
121+
// clerk-android-api. Pinning the api explicitly here keeps consumers
122+
// compiling against the same version we ship the UI from.
123+
implementation("com.clerk:clerk-android-api:$clerkAndroidApiVersion") {
124+
exclude group: 'org.jetbrains.kotlin', module: 'kotlin-stdlib'
125+
exclude group: 'org.jetbrains.kotlin', module: 'kotlin-stdlib-jdk7'
126+
exclude group: 'org.jetbrains.kotlin', module: 'kotlin-stdlib-jdk8'
127+
exclude group: 'com.squareup.okhttp3', module: 'okhttp'
128+
exclude group: 'com.squareup.okhttp3', module: 'okhttp-urlconnection'
129+
}
120130

121131
// Jetpack Compose for wrapping Clerk views
122132
implementation "androidx.compose.ui:ui:$composeVersion"

packages/expo/android/src/main/java/expo/modules/clerk/ClerkAuthExpoView.kt

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,14 @@ class ClerkAuthNativeView(context: Context) : FrameLayout(context) {
4444
var mode: String = "signInOrUp"
4545
var isDismissable: Boolean = true
4646

47-
private val activity: ComponentActivity? = findActivity(context)
47+
private val activity: ComponentActivity? = findActivity(context).also {
48+
// At cold start, ClerkExpoModule.configure() may run before React's
49+
// host-resume sync — meaning getCurrentActivity() returns null there.
50+
// This view's construction is a reliable second hook: we know the Activity
51+
// is available (we just walked the context to find it) and we're about to
52+
// render Google sign-in / passkey buttons that need it.
53+
if (it != null) Clerk.attachActivity(it)
54+
}
4855

4956
// Per-view ViewModelStoreOwner so the AuthView's ViewModels (including its
5057
// navigation state) are scoped to THIS view instance, not the activity.

packages/expo/android/src/main/java/expo/modules/clerk/ClerkExpoModule.kt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,16 @@ class ClerkExpoModule(reactContext: ReactApplicationContext) :
8585
}
8686

8787
Clerk.initialize(reactApplicationContext, pubKey)
88+
// clerk-android registers ActivityLifecycleCallbacks during
89+
// initialize(), but in React Native MainActivity has already passed
90+
// onResume() by the time <ClerkProvider> mounts and we reach this
91+
// line, so the callbacks miss the initial activity. Without seeding,
92+
// the first Credential Manager call (Google sign-in / passkeys)
93+
// fails with MissingActivity until the user backgrounds and
94+
// foregrounds the app. getCurrentActivity() can be null here on
95+
// cold start before React's host-resume sync — AuthView and
96+
// UserProfile also call attachActivity() on mount as a backstop.
97+
getCurrentActivity()?.let { Clerk.attachActivity(it) }
8898
// Theme loading is centralized here. ClerkViewFactory.configure()
8999
// and ClerkUserProfileActivity.onCreate() only call Clerk.initialize()
90100
// when Clerk is not yet initialized, so by the time they run

0 commit comments

Comments
 (0)