multiplatform-settings icon indicating copy to clipboard operation
multiplatform-settings copied to clipboard

[Android] Nullpointer exception while creating Settings instance

Open ismkhanh opened this issue 2 years ago • 11 comments

We are receiving crash while creating instance of Settings on Android. Looks its not able to get context from androidx-startup ? version: 0.8

Caused by java.lang.NullPointerException
       at com.russhwolf.settings.NoArgKt.Settings(NoArgKt.java:33)

ismkhanh avatar Sep 21 '22 11:09 ismkhanh

Seems weird, but that doesn't really give me enough information to understand what's going on. Since 0.8 is pretty old, can you try it on a newer version such as 1.0.0-alpha01?

russhwolf avatar Sep 24 '22 17:09 russhwolf

@russhwolf regarding the issue raised, i have a kmm app that i try to test with robolectric from android module (android/src/test). I wanna test the Main Activity but even the simplest test like assertNotNull(activity) crashes with the same error. I have upgraded to latest version 1.0.0-alpha01.

And the stack trace below

java.lang.NullPointerException at com.russhwolf.settings.NoArgKt.Settings(NoArg.kt:32) at com.calendrop.app.service.SettingsRepository$Companion$instance$2.invoke(SettingsRepository.kt:11) at com.calendrop.app.service.SettingsRepository$Companion$instance$2.invoke(SettingsRepository.kt:10) at kotlin.SynchronizedLazyImpl.getValue(LazyJVM.kt:74) at com.calendrop.app.service.SettingsRepository$Companion.getInstance(SettingsRepository.kt:10) at com.calendrop.common.ui.viewmodel.LanguageSettings.(LanguageSettings.kt:27) at com.calendrop.common.ui.viewmodel.LanguageSettings$Companion.getInstance(LanguageSettings.kt:21) at com.calendrop.common.ui.utils.GetResourcesKt.SetStoredLanguage(GetResources.kt:49) at com.calendrop.common.ui.utils.GetResourcesKt.SetupApplicationLanguage(GetResources.kt:44) at com.calendrop.common.ui.SplashScreenUINewKt.SplashScreenContentNew(SplashScreenUINew.kt:25) at com.calendrop.common.ui.utils.RootUIKt$SplashContentNew$1.invoke(RootUI.kt:50) at com.calendrop.common.ui.utils.RootUIKt$SplashContentNew$1.invoke(RootUI.kt:48) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:116) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34) at com.arkivanov.decompose.extensions.compose.jetbrains.stack.ChildrenKt$Children$1$1.invoke(Children.kt:31) at com.arkivanov.decompose.extensions.compose.jetbrains.stack.ChildrenKt$Children$1$1.invoke(Children.kt:30) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:107) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34) at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:228) at androidx.compose.runtime.saveable.SaveableStateHolderImpl.SaveableStateProvider(SaveableStateHolder.kt:84) at com.arkivanov.decompose.extensions.compose.jetbrains.stack.ChildrenKt$Children$1.invoke(Children.kt:30) at com.arkivanov.decompose.extensions.compose.jetbrains.stack.ChildrenKt$Children$1.invoke(Children.kt:29) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:116) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34) at com.arkivanov.decompose.extensions.compose.jetbrains.stack.animation.DefaultStackAnimation$invoke$1$1$2.invoke(DefaultStackAnimation.kt:55) at com.arkivanov.decompose.extensions.compose.jetbrains.stack.animation.DefaultStackAnimation$invoke$1$1$2.invoke(DefaultStackAnimation.kt:53) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:116) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34) at com.arkivanov.decompose.extensions.compose.jetbrains.stack.animation.ComposableSingletons$FadeKt$lambda-1$1.invoke(Fade.kt:17) at com.arkivanov.decompose.extensions.compose.jetbrains.stack.animation.ComposableSingletons$FadeKt$lambda-1$1.invoke(Fade.kt:16) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:149) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34) at com.arkivanov.decompose.extensions.compose.jetbrains.stack.animation.DefaultStackAnimator.invoke(DefaultStackAnimator.kt:43) at com.arkivanov.decompose.extensions.compose.jetbrains.stack.animation.DefaultStackAnimation.invoke(DefaultStackAnimation.kt:42) at com.arkivanov.decompose.extensions.compose.jetbrains.stack.ChildrenKt.Children(Children.kt:29) at com.arkivanov.decompose.extensions.compose.jetbrains.stack.ChildrenKt.Children(Children.kt:46) at com.calendrop.common.ui.utils.RootUIKt.SplashContentNew(RootUI.kt:45) at com.calendrop.android.MainActivity$onCreate$1$1.invoke(MainActivity.kt:33) at com.calendrop.android.MainActivity$onCreate$1$1.invoke(MainActivity.kt:32) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:107) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34) at com.calendrop.app.theme.AppThemeKt$AppTheme$1.invoke(AppTheme.kt:40) at com.calendrop.app.theme.AppThemeKt$AppTheme$1.invoke(AppTheme.kt:39) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:107) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34) at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:228) at com.calendrop.app.theme.AppThemeKt.AppTheme(AppTheme.kt:33) at com.calendrop.android.MainActivity$onCreate$1.invoke(MainActivity.kt:32) at com.calendrop.android.MainActivity$onCreate$1.invoke(MainActivity.kt:27) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:107) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34) at androidx.compose.ui.platform.ComposeView.Content(ComposeView.android.kt:404) at androidx.compose.ui.platform.AbstractComposeView$ensureCompositionCreated$1.invoke(ComposeView.android.kt:250) at androidx.compose.ui.platform.AbstractComposeView$ensureCompositionCreated$1.invoke(ComposeView.android.kt:249) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:107) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34) at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:228) at androidx.compose.ui.platform.CompositionLocalsKt.ProvideCommonCompositionLocals(CompositionLocals.kt:177) at androidx.compose.ui.platform.AndroidCompositionLocals_androidKt$ProvideAndroidCompositionLocals$3.invoke(AndroidCompositionLocals.android.kt:123) at androidx.compose.ui.platform.AndroidCompositionLocals_androidKt$ProvideAndroidCompositionLocals$3.invoke(AndroidCompositionLocals.android.kt:122) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:107) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34) at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:228) at androidx.compose.ui.platform.AndroidCompositionLocals_androidKt.ProvideAndroidCompositionLocals(AndroidCompositionLocals.android.kt:114) at androidx.compose.ui.platform.WrappedComposition$setContent$1$1$3.invoke(Wrapper.android.kt:157) at androidx.compose.ui.platform.WrappedComposition$setContent$1$1$3.invoke(Wrapper.android.kt:156) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:107) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34) at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:228) at androidx.compose.ui.platform.WrappedComposition$setContent$1$1.invoke(Wrapper.android.kt:156) at androidx.compose.ui.platform.WrappedComposition$setContent$1$1.invoke(Wrapper.android.kt:140) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:107) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34) at androidx.compose.runtime.ActualJvm_jvmKt.invokeComposable(ActualJvm.jvm.kt:78) at androidx.compose.runtime.ComposerImpl$doCompose$2$5.invoke(Composer.kt:3248) at androidx.compose.runtime.ComposerImpl$doCompose$2$5.invoke(Composer.kt:3238) at androidx.compose.runtime.SnapshotStateKt__DerivedStateKt.observeDerivedStateRecalculations(DerivedState.kt:341) at androidx.compose.runtime.SnapshotStateKt.observeDerivedStateRecalculations(Unknown Source) at androidx.compose.runtime.ComposerImpl.doCompose(Composer.kt:3238) at androidx.compose.runtime.ComposerImpl.composeContent$runtime_release(Composer.kt:3173) at androidx.compose.runtime.CompositionImpl.composeContent(Composition.kt:587) at androidx.compose.runtime.Recomposer.composeInitial$runtime_release(Recomposer.kt:950) at androidx.compose.runtime.CompositionImpl.setContent(Composition.kt:519) at androidx.compose.ui.platform.WrappedComposition$setContent$1.invoke(Wrapper.android.kt:140) at androidx.compose.ui.platform.WrappedComposition$setContent$1.invoke(Wrapper.android.kt:131) at androidx.compose.ui.platform.AndroidComposeView.setOnViewTreeOwnersAvailable(AndroidComposeView.android.kt:1060) at androidx.compose.ui.platform.WrappedComposition.setContent(Wrapper.android.kt:131) at androidx.compose.ui.platform.WrappedComposition.onStateChanged(Wrapper.android.kt:182) at androidx.lifecycle.LifecycleRegistry$ObserverWithState.dispatchEvent(LifecycleRegistry.java:360) at androidx.lifecycle.LifecycleRegistry.addObserver(LifecycleRegistry.java:202) at androidx.compose.ui.platform.WrappedComposition$setContent$1.invoke(Wrapper.android.kt:138) at androidx.compose.ui.platform.WrappedComposition$setContent$1.invoke(Wrapper.android.kt:131) at androidx.compose.ui.platform.AndroidComposeView.onAttachedToWindow(AndroidComposeView.android.kt:1147) at android.view.View.dispatchAttachedToWindow(View.java:20753) at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3490) at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3497) at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3497) at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3497) at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3497) at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3497) at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3497) at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2613) at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:2126) at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:8649) at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1037) at android.view.Choreographer.doCallbacks(Choreographer.java:845) at android.view.Choreographer.doFrame(Choreographer.java:780) at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1022) at android.os.Handler.handleCallback(Handler.java:938) at android.os.Handler.dispatchMessage(Handler.java:99) at org.robolectric.shadows.ShadowPausedLooper$IdlingRunnable.run(ShadowPausedLooper.java:368) at org.robolectric.shadows.ShadowPausedLooper.executeOnLooper(ShadowPausedLooper.java:402) at org.robolectric.shadows.ShadowPausedLooper.idle(ShadowPausedLooper.java:93) at org.robolectric.shadows.ShadowPausedLooper.idleIfPaused(ShadowPausedLooper.java:164) at org.robolectric.android.controller.ActivityController.visible(ActivityController.java:208) at org.robolectric.android.controller.ActivityController.setup(ActivityController.java:319) at com.calendrop.android.TestApplication.setUp(TestApplication.kt:47) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56) at org.junit.internal.runners.statements.RunBefores.invokeMethod(RunBefores.java:33) at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:24) at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27) at org.junit.rules.ExternalResource$1.evaluate(ExternalResource.java:54) at androidx.compose.ui.test.junit4.AndroidComposeTestRule$apply$1$evaluate$1.invoke(AndroidComposeTestRule.android.kt:148) at androidx.compose.ui.test.junit4.AndroidComposeTestRule$apply$1$evaluate$1.invoke(AndroidComposeTestRule.android.kt:147) at androidx.compose.ui.test.AndroidComposeUiTestEnvironment$AndroidComposeUiTestImpl.withDisposableContent(ComposeUiTest.android.kt:476) at androidx.compose.ui.test.AndroidComposeUiTestEnvironment$runTest$1$1$1$1$1$1$1.invoke(ComposeUiTest.android.kt:294) at androidx.compose.ui.test.AndroidComposeUiTestEnvironment.withTextInputService(ComposeUiTest.android.kt:360) at androidx.compose.ui.test.AndroidComposeUiTestEnvironment.access$withTextInputService(ComposeUiTest.android.kt:217) at androidx.compose.ui.test.AndroidComposeUiTestEnvironment$runTest$1$1$1$1$1$1.invoke(ComposeUiTest.android.kt:293) at androidx.compose.ui.test.AndroidComposeUiTestEnvironment.withComposeIdlingResource(ComposeUiTest.android.kt:347) at androidx.compose.ui.test.AndroidComposeUiTestEnvironment.access$withComposeIdlingResource(ComposeUiTest.android.kt:217) at androidx.compose.ui.test.AndroidComposeUiTestEnvironment$runTest$1$1$1$1$1.invoke(ComposeUiTest.android.kt:292) at androidx.compose.ui.test.AndroidComposeUiTestEnvironment.withWindowRecomposer(ComposeUiTest.android.kt:321) at androidx.compose.ui.test.AndroidComposeUiTestEnvironment.access$withWindowRecomposer(ComposeUiTest.android.kt:217) at androidx.compose.ui.test.AndroidComposeUiTestEnvironment$runTest$1$1$1$1.invoke(ComposeUiTest.android.kt:291) at androidx.compose.ui.test.AndroidComposeUiTestEnvironment.withTestCoroutines(ComposeUiTest.android.kt:334) at androidx.compose.ui.test.AndroidComposeUiTestEnvironment.access$withTestCoroutines(ComposeUiTest.android.kt:217) at androidx.compose.ui.test.AndroidComposeUiTestEnvironment$runTest$1$1$1.invoke(ComposeUiTest.android.kt:290) at androidx.compose.ui.test.junit4.IdlingStrategy.withStrategy(IdlingStrategy.android.kt:52) at androidx.compose.ui.test.AndroidComposeUiTestEnvironment$runTest$1$1.invoke(ComposeUiTest.android.kt:289) at androidx.compose.ui.test.junit4.IdlingResourceRegistry.withRegistry(IdlingResourceRegistry.jvm.kt:157) at androidx.compose.ui.test.AndroidComposeUiTestEnvironment$runTest$1.invoke(ComposeUiTest.android.kt:288) at androidx.compose.ui.test.junit4.ComposeRootRegistry.withRegistry(ComposeRootRegistry.android.kt:146) at androidx.compose.ui.test.AndroidComposeUiTestEnvironment.runTest(ComposeUiTest.android.kt:287) at androidx.compose.ui.test.junit4.AndroidComposeTestRule$apply$1.evaluate(AndroidComposeTestRule.android.kt:147) at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306) at org.robolectric.RobolectricTestRunner$HelperTestRunner$1.evaluate(RobolectricTestRunner.java:591) at org.robolectric.internal.SandboxTestRunner$2.lambda$evaluate$0(SandboxTestRunner.java:274) at org.robolectric.internal.bytecode.Sandbox.lambda$runOnMainThread$0(Sandbox.java:88) at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) at java.base/java.lang.Thread.run(Thread.java:829)

DimitrisKatsamagos avatar Sep 29 '22 08:09 DimitrisKatsamagos

I don't think androidx.startup gets initialized in a Robolectric test. There's not really much Multiplatform Settings can do there.

I could think about adding an API where you could inject your test Context the way the library does in its tests. But if you're going to use something like that, you might as well just inject the Settings instance instead and avoid calling the no-arg constructor from your tests in the first place.

russhwolf avatar Oct 01 '22 18:10 russhwolf

I have the same issue, and I've tried the new 1.0.0-RC version but unsuccessfully.

viktor-savchik-idf avatar Oct 04 '22 19:10 viktor-savchik-idf

Same here, the merged manifest seems ok, the androidx.startup.InitializationProvider and com.russhwolf.settings.SettingsInitializer is there, but it appears the SettingsInitializer isn't receiving the context. I'm using 1.0.0

FATAL EXCEPTION: main
Process: com.stone.tapsdk:TLniWnlh6DxccKfljv7c, PID: 25927
java.lang.RuntimeException: Unable to create application com.example.app.DemoApplication: java.lang.NullPointerException
	at android.app.ActivityThread.handleBindApplication(ActivityThread.java:7000)
	at android.app.ActivityThread.access$1500(ActivityThread.java:258)
	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1983)
	at android.os.Handler.dispatchMessage(Handler.java:106)
	at android.os.Looper.loop(Looper.java:236)
	at android.app.ActivityThread.main(ActivityThread.java:8061)
	at java.lang.reflect.Method.invoke(Native Method)
	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:656)
	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:967)
Caused by: java.lang.NullPointerException
	at com.russhwolf.settings.NoArgKt.Settings(NoArg.kt:32)
	at co.stone.commons.InitiatorTransactionKeyHandler.<init>(InitiatorTransactionKeyHandler.kt:9)
	at com.example.lib.TapPciMpp.<init>(TapPciMpp.kt:41)
	at com.example.lib.TapSdk.selectLib(TapSdk.kt:20)
	at com.example.lib.TapSdk.initialize(TapSdk.kt:27)
	at com.example.app.DemoApplication.onCreate(DemoApplication.kt:9)
	at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1193)

filpgame avatar Mar 13 '23 18:03 filpgame

Again, I don't expect this to work from a Robolectric test because I don't think Robolectric correctly initializes ContentProviders like androidx.startup uses. If you need to test code that talks to your Settings object, pass in a MapSettings instead of calling the no-arg constructor.

russhwolf avatar Mar 13 '23 23:03 russhwolf

I had the same issue in my app with multiple processes, so I fixed it with an explicit call of the library initializer in my Application class implementation:

AppInitializer.getInstance(getApplicationContext()).initializeComponent(SettingsInitializer.class);

Ustimov avatar Jun 14 '23 05:06 Ustimov

Oh that's interesting. SettingsInitializer is marked internal, so that only works from Java code, but maybe the right solution here is to just make it public.

russhwolf avatar Jun 18 '23 16:06 russhwolf

I plan to make SettingsInitializer public in version 1.2.0 so that you have more flexibility to handle this in tests.

russhwolf avatar Jan 11 '24 18:01 russhwolf