Open fanwgwg opened 2 months ago
Hello @fanwgwg, thank you for the report. Could you share more of the stack trace regarding the crash? I have tested your code but was unable to reproduce the exception. Part of the initialization has been moved to the background; however, you can still successfully call methods like getUser() immediately after initWithContext(). The system allows components like User to be initialized even if the background initialization is not yet complete. In this case, the system will simply use the component that was initialized by your call.
I do notice that this error can occur in certain multi-threading environments that are not specifically covered in our documentation. If you could provide more details, including how you are calling OneSignal API methods and the stack trace when the crash occurs, I can assist in identifying the root cause of the issue.
Here's the stacktrace:
Caused by java.lang.Exception: Must call 'initWithContext' before use
at com.onesignal.internal.OneSignalImp.getUser(OneSignalImp.kt:123)
at com.onesignal.OneSignal.getUser(OneSignal.kt:46)
at com.xxxxx.appsettings.AppSettingsViewModel.refreshNotificationStatus(AppSettingsViewModel.java:82)
at com.xxxxx.appsettings.AppSettingsViewModel.init(AppSettingsViewModel.java:191)
at com.xxxxx.appsettings.AppSettingsViewModel.<init>(AppSettingsViewModel.java:61)
at com.xxxxx.appsettings.AppSettingsViewModel_Factory.newInstance(AppSettingsViewModel_Factory.java:83)
at com.xxxxx.DaggerNoteApplication_HiltComponents_SingletonC$ViewModelCImpl$SwitchingProvider.get(DaggerNoteApplication_HiltComponents_SingletonC.java:3154)
at dagger.hilt.android.internal.lifecycle.HiltViewModelFactory$2.createViewModel(HiltViewModelFactory.java:132)
at dagger.hilt.android.internal.lifecycle.HiltViewModelFactory$2.create(HiltViewModelFactory.java:103)
at dagger.hilt.android.internal.lifecycle.HiltViewModelFactory.create(HiltViewModelFactory.java:170)
at androidx.lifecycle.ViewModelProvider$Factory.create(ViewModelProvider.android.kt:158)
at androidx.lifecycle.viewmodel.ViewModelProviderImpl_androidKt.createViewModel(ViewModelProviderImpl_android.kt:34)
at androidx.lifecycle.viewmodel.ViewModelProviderImpl.getViewModel$lifecycle_viewmodel_release(ViewModelProviderImpl.java:65)
at androidx.lifecycle.viewmodel.ViewModelProviderImpl.getViewModel$lifecycle_viewmodel_release$default(ViewModelProviderImpl.java:47)
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:91)
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:109)
The code setup is that: AppSettingsActivity
@AndroidEntryPoint
public class AppSettingsActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
OneSignal.initWithContext(context, CredentialUtils.getOneSignalId());
AppSettingsViewModel appSettingsViewModel =
new ViewModelProvider(this).get(AppSettingsViewModel.class);
}
}
AppSettingsViewModel
@Inject
AppSettingsViewModel() {
init()
}
private void init() {
refreshNotificationStatus();
}
private void refreshNotificationStatus() {
boolean isOptIn = OneSignal.getUser().getPushSubscription().getOptedIn();
}
@fanwgwg Are you still able to reproduce the exception if you call 'OneSignal.getUser().getPushSubscription().getOptedIn();' immediately after 'OneSignal.initWithContext()'? It seems that your ViewModelProvider might be initialized earlier than AppSettingsActivity.onCreate(), depending on how your injection works.
Does this exception occur every time, most of the time, or only occasionally when you run the app?
I'm not able to reproduce it, I'm only seeing it from Crashlytics. Based on the stacktrace, I do believe that AppSettingsActivity.onCreate() is already called before OneSignal.getUser()
is called.
Sharing the complete stacktrace here as I only pasted the ones related to the viewmodel in my previous reply. This is the exact stacktrace on Crashlytics, except that I've removed our package id.
You'll a line of com.xxxxx.appsettings.AppSettingsActivity.onCreate (AppSettingsActivity.java)
inside the stacktrace.
com.onesignal.internal.OneSignalImp.getUser (OneSignalImp.kt:123)
com.onesignal.OneSignal.getUser (OneSignal.kt:46)
com.xxxxx.appsettings.AppSettingsViewModel.refreshNotificationStatus (AppSettingsViewModel.java:82)
com.xxxxx.appsettings.AppSettingsViewModel.init (AppSettingsViewModel.java:191)
com.xxxxx.appsettings.AppSettingsViewModel.<init> (AppSettingsViewModel.java:61)
com.xxxxx.appsettings.AppSettingsViewModel_Factory.newInstance (AppSettingsViewModel_Factory.java:83)
com.xxxxx.DaggerNoteApplication_HiltComponents_SingletonC$ViewModelCImpl$SwitchingProvider.get (DaggerNoteApplication_HiltComponents_SingletonC.java:3154)
dagger.hilt.android.internal.lifecycle.HiltViewModelFactory$2.createViewModel (HiltViewModelFactory.java:132)
dagger.hilt.android.internal.lifecycle.HiltViewModelFactory$2.create (HiltViewModelFactory.java:103)
dagger.hilt.android.internal.lifecycle.HiltViewModelFactory.create (HiltViewModelFactory.java:170)
androidx.lifecycle.ViewModelProvider$Factory.create (ViewModelProvider.android.kt:158)
androidx.lifecycle.viewmodel.ViewModelProviderImpl_androidKt.createViewModel (ViewModelProviderImpl_android.kt:34)
androidx.lifecycle.viewmodel.ViewModelProviderImpl.getViewModel$lifecycle_viewmodel_release (ViewModelProviderImpl.java:65)
androidx.lifecycle.viewmodel.ViewModelProviderImpl.getViewModel$lifecycle_viewmodel_release$default (ViewModelProviderImpl.java:47)
androidx.lifecycle.ViewModelProvider.get (ViewModelProvider.java:91)
androidx.lifecycle.ViewModelProvider.get (ViewModelProvider.java:109)
com.xxxxx.appsettings.AppSettingsFragment.onCreate (AppSettingsFragment.java:58)
androidx.fragment.app.Fragment.performCreate (Fragment.java:3099)
androidx.fragment.app.FragmentStateManager.create (FragmentStateManager.java:524)
androidx.fragment.app.FragmentStateManager.moveToExpectedState (FragmentStateManager.java:282)
androidx.fragment.app.FragmentStore.moveToExpectedState (FragmentStore.java:114)
androidx.fragment.app.FragmentManager.moveToState (FragmentManager.java:1675)
androidx.fragment.app.FragmentManager.dispatchStateChange (FragmentManager.java:3269)
androidx.fragment.app.FragmentManager.dispatchCreate (FragmentManager.java:3176)
androidx.fragment.app.Fragment.restoreChildFragmentState (Fragment.java:1994)
androidx.fragment.app.Fragment.onCreate (Fragment.java:1972)
androidx.navigation.fragment.NavHostFragment.onCreate (NavHostFragment.kt:163)
androidx.fragment.app.Fragment.performCreate (Fragment.java:3099)
androidx.fragment.app.FragmentStateManager.create (FragmentStateManager.java:524)
androidx.fragment.app.FragmentStateManager.moveToExpectedState (FragmentStateManager.java:282)
androidx.fragment.app.FragmentStore.moveToExpectedState (FragmentStore.java:114)
androidx.fragment.app.FragmentManager.moveToState (FragmentManager.java:1675)
androidx.fragment.app.FragmentManager.dispatchStateChange (FragmentManager.java:3269)
androidx.fragment.app.FragmentManager.dispatchCreate (FragmentManager.java:3176)
androidx.fragment.app.FragmentController.dispatchCreate (FragmentController.java:252)
androidx.fragment.app.FragmentActivity.onCreate (FragmentActivity.java:219)
com.xxxxx.appsettings.Hilt_AppSettingsActivity.onCreate (Hilt_AppSettingsActivity.java)
com.xxxxx.appsettings.AppSettingsActivity.onCreate (AppSettingsActivity.java)
android.app.Activity.performCreate (Activity.java:8657)
android.app.Activity.performCreate (Activity.java:8636)
android.app.Instrumentation.callActivityOnCreate (Instrumentation.java:1417)
android.app.ActivityThread.performLaunchActivity (ActivityThread.java:4165)
android.app.ActivityThread.handleLaunchActivity (ActivityThread.java:4340)
android.app.servertransaction.LaunchActivityItem.execute (LaunchActivityItem.java:101)
android.app.servertransaction.TransactionExecutor.executeCallbacks (TransactionExecutor.java:135)
android.app.servertransaction.TransactionExecutor.execute (TransactionExecutor.java:95)
android.app.ActivityThread$H.handleMessage (ActivityThread.java:2584)
android.os.Handler.dispatchMessage (Handler.java:106)
android.os.Looper.loopOnce (Looper.java:226)
android.os.Looper.loop (Looper.java:313)
android.app.ActivityThread.main (ActivityThread.java:8810)
java.lang.reflect.Method.invoke (Method.java)
com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:604)
com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1067)
@fanwgwg Is your CredentialUtils.getOneSignalId() retrieving the OneSignalId from your server, causing it to return null at times? I believe this exception can be reproduced if the OneSignalId you passed in is null. I suggest checking if OneSignalId is null before calling initWithContext.
If that’s the case, we can certainly work on making the error message clearer and more precise.
If your OneSignalId is local or guaranteed to be non-null, I would suggest a temporary workaround: use try-catch around isOptedIn while we continue investigating based on your feedback.
What happened?
In my code, I've consistently encountered crashes when using OneSignal APIs after calling OneSignal.initWithContext, specifically receiving the error: java.lang.Exception: Must call 'initWithContext' before use.
I believe this is related to the recent changes in PR #2151, which moved initialization to a background thread. However, there seems to be no clear guidance from OneSignal on how to determine when the SDK has completed initialization and when it's safe to call other APIs.
Relying on developers to wait for an arbitrary period, such as 2 seconds, before invoking OneSignal APIs is not a viable or professional coding practice—this is not something we see in other SDKs. If the initialization is now asynchronous, then the rest of the APIs should also be asynchronous. For instance, APIs could return a result only after initialization has completed.
Overall, I feel the quality of the SDK urgently needs improvement, especially given the frequent crashes introduced since the 5.0 release. Addressing these issues with more robust handling of the initialization process is crucial.
Steps to reproduce?
What did you expect to happen?
The code should not crash
OneSignal Android SDK version
com.onesignal:OneSignal:5.1.21
Android version
14
Specific Android models
No response
Relevant log output
No response
Code of Conduct