question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Does Koin work with Android BroadcastReceiver in the manifest?

See original GitHub issue

Describe the bug I have an Android app which uses Koin and which uses Robolectric for some unit tests. All unit tests that use Robolectric fail with the stack below. This appears to be because I have a BroadcastReceiver declared in the manifest <receiver android:name="MyBroadcastReceiver"/> And MyBroadcastReceiver implements KoinComponent and uses by inject.

It appears that because the BroadcastReceiver is declared in the manifest it gets created BEFORE my App.onCreate (which is where I start Koin). When I remove the BroadcastReceiver from the manifest the tests pass.

Am I doing something wrong? Possibly this is a Robolectric bug instead? I am migrating an app from Dagger to Koin and these unit test previously worked fine with Dagger.

java.lang.IllegalStateException: KoinApplication has not been started

	at org.koin.core.context.GlobalContext.get(GlobalContext.kt:37)
	at org.koin.core.KoinComponent$DefaultImpls.getKoin(KoinComponent.kt:32)
	at com.metaswitch.max.util.MyBroadcastReceiver.getKoin(MyBroadcastReceiver.kt:52)
	at com.metaswitch.max.util.MyBroadcastReceiver.<init>(MyBroadcastReceiver.kt:143)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
	at org.robolectric.util.ReflectionHelpers.callConstructor(ReflectionHelpers.java:379)
	at org.robolectric.internal.bytecode.ShadowImpl.newInstanceOf(ShadowImpl.java:18)
	at org.robolectric.shadow.api.Shadow.newInstanceOf(Shadow.java:35)
	at org.robolectric.android.internal.AndroidEnvironment.registerBroadcastReceivers(AndroidEnvironment.java:491)
	at org.robolectric.android.internal.AndroidEnvironment.installAndCreateApplication(AndroidEnvironment.java:242)
	at org.robolectric.android.internal.AndroidEnvironment.setUpApplicationState(AndroidEnvironment.java:149)
	at org.robolectric.RobolectricTestRunner.beforeTest(RobolectricTestRunner.java:298)
	at org.robolectric.internal.SandboxTestRunner$2.lambda$evaluate$0(SandboxTestRunner.java:247)
	at org.robolectric.internal.bytecode.Sandbox.lambda$runOnMainThread$0(Sandbox.java:89)
	at java.util.concurrent.FutureTask.run$$$capture(FutureTask.java:266)
	at java.util.concurrent.FutureTask.run(FutureTask.java)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)

To Reproduce See above.

Expected behavior Unit test to pass.

Koin project used and used version (please complete the following information): “org.koin:koin-androidx-viewmodel:2.0.1” “org.koin:koin-test:2.0.1”

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Comments:9 (4 by maintainers)

github_iconTop GitHub Comments

10reactions
NickButcher1commented, Jul 3, 2019

I think I see how to workaround this.

Split my BroadcastReceiver into two classes:

  • An actual BroadcastReceiver.
  • A Helper class that has the Koin injection and does all the work.
class MyBroadcastReceiver {
    private val myhelper: MyHelper by lazy { MyHelper() }

    override fun onReceive(context: Context, intent: Intent) {
        myhelper.onReceive(context, Intent)
    }
}

class MyHelper : KoinComponent {
    private val foo: Foo by inject()

    fun onReceive(context: Context, intent: Intent) {
        // Do the work here that used to be in the BroadcastReceiver.
    }

Now MyHelper isn’t created until Koin has been initialised in App.onCreate.

0reactions
nienienieniecommented, Sep 14, 2022

check for #237

Read more comments on GitHub >

github_iconTop Results From Across the Web

Broadcasts overview | Android Developers
Apps can receive broadcasts in two ways: through manifest-declared receivers and context-registered receivers. Manifest-declared receivers. If you declare a ...
Read more >
android - how can i use broadcast receiver in my application
1 Answer 1 ... From the documentation: Note: If your app targets API level 26 or higher, you cannot use the manifest to...
Read more >
Android BroadcastReceiver Example Tutorial | DigitalOcean
Today we'll discuss and implement Android BroadcastReceiver that is a very important component of Android Framework.
Read more >
Android: Broadcast Receiver - Topcoder
Statically (manifest-declared) - This receiver can be registered via the AndroidManifest.xml file. Dynamically (context-registered) - This ...
Read more >
Declaring BroadcastReceivers in the manifest is deprecated
As per the provided link in the teacher's notes, https://developer.android.com/training/monitoring-device-state/connectivity-monitoring.html# ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found