App 在访问 NotificationManager.getNotificationChannels 时因误导性 DeadSystemException 而崩溃

问题描述 投票:0回答:0

目前为多个不同的设备型号和制造商(到目前为止在 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
中,所以我希望有人可能以前遇到过这个并且知道发生了什么,或者至少可以提供一种方法来重现问题,以便提出适当的解决方案。

有谁知道为什么会这样以及如何解决?或者至少如何重现这次崩溃?

android kotlin runtimeexception notificationmanager deadsystemexception
© www.soinside.com 2019 - 2024. All rights reserved.