Skip to content

Commit 283f790

Browse files
committed
Refactor example app UI and improve context handling
Redesigned the example app with new Section, Field, and ToggleRow components for a more organized and modern UI, updated styles for a light theme, and improved the display of security capabilities and stored items. On Android, ReactContextHolder now tracks FragmentActivity more robustly and manages lifecycle listeners to ensure correct activity references for biometric prompts. Removed unnecessary FragmentActivity check in BiometricAuthenticator.
1 parent 3c81c68 commit 283f790

3 files changed

Lines changed: 537 additions & 249 deletions

File tree

android/src/main/java/com/sensitiveinfo/internal/auth/BiometricAuthenticator.kt

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -172,9 +172,6 @@ internal class BiometricAuthenticator {
172172
private fun currentFragmentActivity(): FragmentActivity {
173173
val activity = ReactContextHolder.currentActivity()
174174
?: throw IllegalStateException("Unable to show authentication prompt: no active React activity.")
175-
if (activity !is FragmentActivity) {
176-
throw IllegalStateException("Current activity does not support FragmentManager required for biometric prompts.")
177-
}
178175
return activity
179176
}
180177

android/src/main/java/com/sensitiveinfo/internal/util/ReactContextHolder.kt

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ package com.sensitiveinfo.internal.util
22

33
import android.app.Activity
44
import com.facebook.react.bridge.ReactApplicationContext
5+
import com.facebook.react.bridge.LifecycleEventListener
6+
import androidx.fragment.app.FragmentActivity
57
import java.lang.ref.WeakReference
68
import java.util.concurrent.atomic.AtomicReference
79

@@ -16,23 +18,59 @@ import java.util.concurrent.atomic.AtomicReference
1618
internal object ReactContextHolder {
1719
// Keep only a weak reference so the React instance can be GC'd after teardown.
1820
private val contextRef = AtomicReference<WeakReference<ReactApplicationContext>?>(null)
21+
private val activityRef = AtomicReference<WeakReference<FragmentActivity>?>(null)
22+
private val lifecycleListener = object : LifecycleEventListener {
23+
override fun onHostResume() {
24+
captureActivity(contextRef.get()?.get()?.currentActivity)
25+
}
26+
27+
override fun onHostPause() {
28+
// No-op. We keep the last resumed activity to support prompts during pauses triggered by UI overlays.
29+
}
30+
31+
override fun onHostDestroy() {
32+
clearActivity()
33+
}
34+
}
1935

2036
fun install(context: ReactApplicationContext) {
2137
val current = contextRef.get()?.get()
2238
if (current === context) {
2339
return
2440
}
41+
current?.removeLifecycleEventListener(lifecycleListener)
42+
context.addLifecycleEventListener(lifecycleListener)
2543
contextRef.set(WeakReference(context))
44+
captureActivity(context.currentActivity)
2645
}
2746

2847
fun clear() {
29-
contextRef.set(null)
48+
contextRef.getAndSet(null)?.get()?.removeLifecycleEventListener(lifecycleListener)
49+
clearActivity()
3050
}
3151

3252
fun requireContext(): ReactApplicationContext {
3353
return contextRef.get()?.get()
3454
?: throw IllegalStateException("ReactApplicationContext not yet available for SensitiveInfo.")
3555
}
3656

37-
fun currentActivity(): Activity? = contextRef.get()?.get()?.currentActivity
57+
fun currentActivity(): FragmentActivity? {
58+
val active = activityRef.get()?.get()
59+
if (active != null && !active.isFinishing && !active.isDestroyed) {
60+
return active
61+
}
62+
63+
val contextActivity = contextRef.get()?.get()?.currentActivity as? FragmentActivity
64+
captureActivity(contextActivity)
65+
return contextActivity
66+
}
67+
68+
private fun captureActivity(activity: Activity?) {
69+
val fragmentActivity = activity as? FragmentActivity ?: return
70+
activityRef.set(WeakReference(fragmentActivity))
71+
}
72+
73+
private fun clearActivity() {
74+
activityRef.getAndSet(null)?.clear()
75+
}
3876
}

0 commit comments

Comments
 (0)