Created
January 10, 2023 10:10
-
-
Save hoc081098/6e1856172f883ce53c859729ef699e4b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@HiltAndroidApp | |
class MyApp : Application(), ImageLoaderFactory { | |
@Inject | |
internal lateinit var activityTracker: TopResumedActivityTracker | |
override fun onCreate() { | |
super.onCreate() | |
registerActivityLifecycleCallbacks(activityTracker) | |
} | |
} | |
class RealAuthRepository @Inject constructor( | |
private val activityTracker: TopResumedActivityTracker, | |
) : AuthRepository { | |
fun signIn() { | |
val activity = activityTracker.topResumedActivity ?: return | |
// start other activity for signing in ... (via browser / chrome custom tab intent, eg. Auth0) | |
} | |
} | |
@Singleton | |
class TopResumedActivityTracker @Inject constructor( | |
appCoroutineScope: AppCoroutineScope, | |
) : Application.ActivityLifecycleCallbacks { | |
@Retention(value = AnnotationRetention.BINARY) | |
@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.TYPEALIAS, AnnotationTarget.PROPERTY) | |
@RequiresOptIn(level = RequiresOptIn.Level.ERROR) | |
annotation class Experimental | |
/** | |
* Keep the top resumed activity and its identity hashcode. | |
*/ | |
private val _topResumedActivityStateFlow = MutableStateFlow<Pair<Activity, Int>?>(null) | |
init { | |
if (BuildConfig.DEBUG) { | |
_topResumedActivityStateFlow | |
.onEach { Timber.d("[topResumedActivityStateFlow] $it") } | |
.launchIn(appCoroutineScope) | |
} | |
} | |
@get:AnyThread | |
val topResumedActivity: Activity? | |
get() = _topResumedActivityStateFlow.value?.first | |
@Experimental | |
val topResumedActivityStateFlow: StateFlow<Activity?> = | |
_topResumedActivityStateFlow | |
.asStateFlow() | |
.map { it?.first } | |
.stateIn( | |
scope = appCoroutineScope, | |
started = SharingStarted.Eagerly, | |
initialValue = null | |
) | |
@Suppress("NOTHING_TO_INLINE") | |
private inline fun clearTopResumedActivity(activity: Activity) { | |
Timber.d("[clearMainActivity] activity=$activity, ref=${_topResumedActivityStateFlow.value}") | |
_topResumedActivityStateFlow.update { old -> | |
old?.let { | |
if (System.identityHashCode(activity) == it.second) { | |
null | |
} else { | |
it | |
} | |
} | |
} | |
} | |
override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) = Unit | |
override fun onActivityStarted(activity: Activity) = Unit | |
override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) = Unit | |
override fun onActivityResumed(activity: Activity) { | |
Timber.d("[onActivityResumed] activity=$activity, ref=${_topResumedActivityStateFlow.value}") | |
_topResumedActivityStateFlow.update { it ?: (activity to System.identityHashCode(activity)) } | |
} | |
override fun onActivityPaused(activity: Activity) = clearTopResumedActivity(activity) | |
override fun onActivityStopped(activity: Activity) = clearTopResumedActivity(activity) | |
override fun onActivityDestroyed(activity: Activity) = clearTopResumedActivity(activity) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment