Our Launcher system application is rarely crashing right after being updated (MY_PACKAGE_REPLACED
), while it is starting this specific activity LoginScannerActivity
with some flags from its own PackageReplacedBroadcastReceiver
receiver.
Crash report:
java.lang.NullPointerException: Attempt to invoke virtual method 'void com.android.server.am.TaskRecord.setIntent(com.android.server.am.ActivityRecord)' on a null object reference at android.os.Parcel.readException(Parcel.java:1690) at android.os.Parcel.readException(Parcel.java:1637) at android.app.ActivityManagerProxy.startActivity(ActivityManagerNative.java:3238) at android.app.Instrumentation.execStartActivity(Instrumentation.java:1518) at android.app.ContextImpl.startActivity(ContextImpl.java:805) at android.app.ContextImpl.startActivity(ContextImpl.java:782) at android.content.ContextWrapper.startActivity(ContextWrapper.java:356) at android.content.ContextWrapper.startActivity(ContextWrapper.java:356) at io.workerbase.app.launcher.activity.user.LogoutHelper.logout(LogoutHelper.kt:54) at io.workerbase.app.launcher.activity.user.LogoutHelper.logoutLauncher(LogoutHelper.kt:41) at io.workerbase.app.launcher.activity.user.LogoutHelper.logoutLauncherAndDM(LogoutHelper.kt:28) at io.workerbase.app.launcher.receiver.PackageReplacedBroadcastReceiver.onReceive(PackageReplacedBroadcastReceiver.kt:23) at android.app.ActivityThread.handleReceiver(ActivityThread.java:3156) at android.app.ActivityThread.-wrap18(ActivityThread.java) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1645) at android.os.Handler.dispatchMessage(Handler.java:110) at android.os.Looper.loop(Looper.java:203) at android.app.ActivityThread.main(ActivityThread.java:6337) at java.lang.reflect.Method.invoke(Method.java) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1084) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:945)java.lang.RuntimeException: Unable to start receiver io.workerbase.app.launcher.receiver.PackageReplacedBroadcastReceiver: java.lang.NullPointerException: Attempt to invoke virtual method 'void com.android.server.am.TaskRecord.setIntent(com.android.server.am.ActivityRecord)' on a null object reference at android.app.ActivityThread.handleReceiver(ActivityThread.java:3163) at android.app.ActivityThread.-wrap18(ActivityThread.java) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1645) at android.os.Handler.dispatchMessage(Handler.java:110) at android.os.Looper.loop(Looper.java:203) at android.app.ActivityThread.main(ActivityThread.java:6337) at java.lang.reflect.Method.invoke(Method.java) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1084) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:945)
The crash happens only on Android 7.1.1 (AOSP) and has never happened on Android 6.0.1 (AOSP).I'm wondering what could be the reason for this crash, the activity intent flags:
Intent(context, LoginScannerActivity::class.java).apply { addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP) addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK)}
which normally works fine when app is used and navigates to this activity when user logs out, or is it something else? I can't reproduce the crash and don't see anything wrong in the code.
Manifest:
<activity android:name="io.workerbase.app.launcher.activity.scan.LoginScannerActivity" android:clearTaskOnLaunch="true" android:screenOrientation="landscape" android:stateNotNeeded="true" android:theme="@style/WatchAppTheme" android:windowSoftInputMode="stateAlwaysHidden" /><receiver android:name=".receiver.PackageReplacedBroadcastReceiver"><intent-filter><action android:name="android.intent.action.MY_PACKAGE_REPLACED" /></intent-filter></receiver>
Receiver:
@KoinApiExtensionclass PackageReplacedBroadcastReceiver : BroadcastReceiver(), KoinComponent { override fun onReceive(context: Context, intent: Intent) { Timber.d("onReceive: ${intent.action}") // when app is updated it must force user logout LogoutHelper.logoutLauncherAndDM(context, configStore = get(), wifiUtil = get()) }}
LogoutHelper:
object LogoutHelper { fun logoutLauncherAndDM(context: Context, configStore: ConfigurationStore, wifiUtil: WifiUtil) { Timber.d("logoutLauncherAndDM") logoutLauncher(context, configStore, wifiUtil) DeviceManagementManager.sendLogoutUserBroadcast(context) } fun logoutLauncher(context: Context, configStore: ConfigurationStore, wifiUtil: WifiUtil) { Timber.d("logoutLauncher") logout(context, configStore, wifiUtil) SkeeperClientService.stop(context) } private fun logout(context: Context, configStore: ConfigurationStore, wifiUtil: WifiUtil) { configStore.clearUserSession().also { Modules.reloadRepositoryModules() } if (wifiUtil.isTargetWifiConnected(configStore)) { context.startActivity(LoginScannerActivity.getStartIntent(context)) } else { context.startActivity(EstablishConnectionActivity.getStartIntent(context)) } }}
The critical line in LogoutHeleper
is
context.startActivity(LoginScannerActivity.getStartIntent(context))
which matches this line in the stack trace:
io.workerbase.app.launcher.activity.user.LogoutHelper.logout(LogoutHelper.kt:54)
And the activity intent that crashes the app when started:
class LoginScannerActivity : WbLauncherBaseActivity() { // rest of the code is omitted due to its size, not related to the crash companion object { @JvmStatic fun getStartIntent(context: Context) = Intent(context, LoginScannerActivity::class.java).apply { addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP) addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK) } }}
Note that this crash also happened a few times when LogoutHelper.logout*
is called from main activity, also on app start. So it's not only crashing if called from the package replaced receiver, but the majority of crashes occurred when called from the receiver.
I would appreciate any help on this as I have never seen crashes mentioning com.android.server.am.TaskRecord.setIntent()
and ActivityManagerNative