androidandroid-activityandroid-application-class

Activity created before Application.onCreate called?


We use a subclassed Application object, like this:

class MyApp : Application() {
    init {
        instance = this
    }

    ...

    companion object {
        lateinit var instance: MyApp
            private set
    }
}

...which should get initialized before any other components of the app are launched (Activities, Services, etc). And for 99.99% of our users, everything works correctly.

However, there's a crash that we see for just a few users, that looks like this:

Exception java.lang.RuntimeException:
  at android.app.ActivityThread.performLaunchActivity (ActivityThread.java:4051)
  at android.app.ActivityThread.handleLaunchActivity (ActivityThread.java:4325)
  at android.app.servertransaction.LaunchActivityItem.execute (LaunchActivityItem.java:101)
  at android.app.servertransaction.TransactionExecutor.executeCallbacks (TransactionExecutor.java:135)
  at android.app.servertransaction.TransactionExecutor.execute (TransactionExecutor.java:95)
  at android.app.ActivityThread$H.handleMessage (ActivityThread.java:2574)
  at android.os.Handler.dispatchMessage (Handler.java:106)
  at android.os.Looper.loopOnce (Looper.java:226)
  at android.os.Looper.loop (Looper.java:313)
  at android.app.ActivityThread.main (ActivityThread.java:8757)
  at java.lang.reflect.Method.invoke
  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:571)
  at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1067)
Caused by kotlin.UninitializedPropertyAccessException: lateinit property instance has not been initialized
  at mypackage.MyApp$Companion.getInstance (MyApp.kt:312)
  at mypackage.MyActivity.<init> (MyActivity.kt:72)
  at java.lang.Class.newInstance
  at android.app.AppComponentFactory.instantiateActivity (AppComponentFactory.java:95)
  at androidx.core.app.CoreComponentFactory.instantiateActivity (CoreComponentFactory.java:45)
  at android.app.Instrumentation.newActivity (Instrumentation.java:1328)
  at android.app.ActivityThread.performLaunchActivity (ActivityThread.java:4038)

Note in the stack trace that MyActivity attempts to access MyApp.instance, but apparently it hasn't been initialized! This would imply that the Activity is getting launched before the Application class was instantiated (?)

What could be going on?


Solution

  • I've been investigating this issue as well

    From the following bug report, it may be an OS bug related to backup where your Application subclass is not launched: https://issuetracker.google.com/u/0/issues/160946170

    It may be caused by a Service or BroadcastReceiver starting your app while it is in backup (restricted) mode, causing a crash, and triggering an OS bug which leaves it in restricted mode and causes your subclassed Application to not get used in subsequent calls. Restarting the device seems to clear things. Or you could implement a workaround such as the follows:

    class BaseClass
    ...
        @CallSuper
        override fun onCreate(savedInstanceState: Bundle?) {
            ...
    
            if (application !is MyApp) {
                // app is in restricted mode, kill it
                Handler().post { exitProcess(0) }
    
                finish()
                return
            }