目前为多个不同的设备型号和制造商(到目前为止在 Android 8.1.0 和 Android 11 上)获取以下堆栈跟踪,仅在应用程序内部调用中有小的变化:
Fatal Exception: java.lang.RuntimeException: android.os.DeadSystemException
at android.app.NotificationManager.getNotificationChannels(NotificationManager.java:892)
at appinternalcalls(...).getNotificationChannel
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
at kotlinx.coroutines.internal.LimitedDispatcher.run(LimitedDispatcher.kt:42)
at kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:95)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.java:570)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:750)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:677)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:664)
注:因IP关系省略app内部调用
我一直试图理解为什么会发生这种情况,到目前为止我只能得出结论,用于实例化
Context
的 NotificationManager
在这种情况下不知何故是错误的。
问题是我根本无法重现这种情况,也无法想出一种可靠的方法来确保 context
是正确的(通过转换/上下文包装)。
据我所知,该应用程序有 3 个可能的
context
入口点:
BroadcastReceiver
ContentProvider
不幸的是,我已经尽可能多地进行了测试,甚至检查了
BroadcastReceiver
的上下文以在重新启动设备后自动启动应用程序,但仍然没有,一切正常。
该单一方法的源代码记录了以下内容:
/**
* Returns all notification channels belonging to the calling package.
*
* <p>Approved notification delegates (see {@link #canNotifyAsPackage(String)}) can query
* notification channels belonging to packages they are the delegate for. To do so, call this
* method from a context created for that package (see
* {@link Context#createPackageContext(String, int)}).</p>
*/
public List<NotificationChannel> getNotificationChannels() {
INotificationManager service = getService();
try {
return service.getNotificationChannels(mContext.getOpPackageName(),
mContext.getPackageName(), mContext.getUserId()).getList();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
当跟随
rethrowFromSystemServer
导致这个:
/**
* Rethrow this exception when we know it came from the system server. This
* gives us an opportunity to throw a nice clean
* {@link DeadSystemRuntimeException} signal to avoid spamming logs with
* misleading stack traces.
* <p>
* Apps making calls into the system server may end up persisting internal
* state or making security decisions based on the perceived success or
* failure of a call, or any default values returned. For this reason, we
* want to strongly throw when there was trouble with the transaction.
*
* @throws RuntimeException
*/
@NonNull
public RuntimeException rethrowFromSystemServer() {
if (this instanceof DeadObjectException) {
throw new DeadSystemRuntimeException();
} else {
throw new RuntimeException(this);
}
}
这是让我以某种方式相信的唯一线索,在某种未知的情况下,该应用程序正在以非其自身的上下文启动,从而导致提到的
DeadSystemException
崩溃,这让我有一段时间相信这意味着该设备已经崩溃并正在重新启动,直到我注意到它总是发生,并且只发生在访问完全相同的方法而不是其他方法时。
我找不到任何关于为什么会发生这种情况的明确解释,也找不到明确的解决方法,除了将它包围在
try...catch
中,所以我希望有人可能以前遇到过这个并且知道发生了什么,或者至少可以提供一种方法来重现问题,以便提出适当的解决方案。
有谁知道为什么会这样以及如何解决?或者至少如何重现这次崩溃?