1

I want to create a Splash screen and show it as long as the authentication state of the user gets determined. I have a global singleton called AuthStateController which holds my state and some extra functions.
But because the installSplashScreen function is outside of a composable I can't use Koin to inject the AuthStateController class to get access to my loading state.

Below is my MainActivity with all my Koin modules. And the installSplashScreen function.

class MainActivity : ComponentActivity() {
    // not allowed because outside of Composable
    private val authStateController: AuthStateController by inject()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        startKoin {
            androidLogger(if (BuildConfig.DEBUG) Level.ERROR else Level.NONE)
            androidContext(this@MainActivity)
            modules(listOf(appModule, networkModule, viewModelModule, interactorsModule))
        }

        installSplashScreen().apply {
            setKeepVisibleCondition {
                // need AuthStateController instance to determine loading state
                authStateController.state.value.isLoading
            }
        }

        setContent {
                M3Theme {
                    SetupNavGraph()
                }
            }
        }
    }
}

This is the Koin module that provides my AuthStateController class:

val appModule = module {
    single { AuthStateController(get()) }
}

And this is my AuthStateController class which holds my state and some extra functions:

class AuthStateController(
    private val getMeInterceptor: GetMeInterceptor
) {
    val state: MutableState<AuthState> = mutableStateOf(AuthState())

    fun fetchMe() {
        val me = getMeInterceptor.execute().collect(CoroutineScope(Dispatchers.IO)) { dataState ->
            dataState.data?.let {
                state.value =
                    state.value.copy(profile = it, isAuthenticated = true, isLoading = false)
            }
        }
    }

    init {
        val token = settings.getString(Constants.AUTH_TOKEN)
        if (token.isNotBlank()) {
            fetchMe()
            state.value = state.value.copy(authToken = token)
        }
    }
}

How can I get access to the singleton created with Koin inside the MainActivity and use it inside the installSplashScreen function?

Edit

Android Manifest:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="com.example.sessions_clean.android">

    <uses-permission android:name="android.permission.INTERNET" />
    
    <application
        // app crashes when adding line below
        android:name=".MainApplication"
        android:allowBackup="false"
        android:supportsRtl="true"
        android:theme="@style/Theme.App.Starting"
        android:usesCleartextTraffic="true">
        <activity
            android:name=".MainActivity"
            android:exported="true"
            android:theme="@style/Theme.App.Starting">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>

When I add android:name to the already existing application tag the App crashes instantly.

But when I create a new application tag for the new MainApplication I get errors in the IDE like Attribute android:allowBackup is not allowed here

JonasLevin
  • 1,592
  • 1
  • 20
  • 50
  • Can you startKoin inside Application (instead of MainActivity)? – Linh Jan 11 '22 at 00:13
  • 1
    What do you mean by Application? I could start it inside `setContent` but that wouldn't make a difference – JonasLevin Jan 11 '22 at 11:17
  • 2
    something like https://insert-koin.io/docs/reference/koin-android/start/ – Linh Jan 11 '22 at 12:13
  • That looks good, so I created a new class wich extends `Application`. Do I need to reference it as a new activity inside the `AndroidManifest`? – JonasLevin Jan 11 '22 at 13:16

1 Answers1

1

I think you can startKoin inside the Application

MainApplication.kt

class MainApplication : Application() {

    override fun onCreate() {
        super.onCreate()

        startKoin {
            ...
        }
        
    }
}

AndroidManifest.xml

<manifest ...>

    <application
        android:name=".MainApplication"
        ...>
        ...
    </application>

</manifest>
Linh
  • 57,942
  • 23
  • 262
  • 279
  • 1
    I have changed my question to include my `AndroidManifest`. My app crashes instanly when I add `anroid:name` to the application tag. – JonasLevin Jan 11 '22 at 14:20
  • @JonasLevin I'm not sure, never face this issue before. https://stackoverflow.com/questions/31683788/android-manifest-attribute-not-allowed-here follow this answer here, it look like a IDE error. please try to invalidate cache and restart Android Studio to see if this problem still happened – Linh Jan 11 '22 at 14:50