在 Android SDK 的方法 updateLocaleListFromAppContext 中获取 NullPointerException

Getting NullPointerException in Android SDK's method updateLocaleListFromAppContext

提问人:Richie 提问时间:6/17/2019 最后编辑:NoHarmDanRichie 更新时间:10/16/2023 访问量:3518

问:

我在 PlayStore 上上传了一个应用程序,但从java.lang.NullPointerExceptionandroid.app.ActivityThread.updateLocaleListFromAppContext

我尝试在网上搜索很多,以检查此错误可能来自哪里。我本身并没有专门针对代码中的任何内容使用此方法调用。

java.lang.NullPointerException: 
  at android.app.ActivityThread.updateLocaleListFromAppContext (ActivityThread.java:5892)
  at android.app.ActivityThread.handleBindApplication (ActivityThread.java:6127)
  at android.app.ActivityThread.access$1200 (ActivityThread.java:240)
  at android.app.ActivityThread$H.handleMessage (ActivityThread.java:1797)
  at android.os.Handler.dispatchMessage (Handler.java:106)
  at android.os.Looper.loop (Looper.java:214)
  at android.app.ActivityThread.main (ActivityThread.java:7076)
  at java.lang.reflect.Method.invoke (Method.java)
  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:494)
  at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:965)

如果有人知道解决方案或我可以从哪里开始寻求解决此问题,请提供帮助。

澄清一下,这不是如何避免常见的 NullPointerException 的问题,这不会发生在开发人员代码中,而是发生在 Android API 本身的一侧,问题在于如何避免它,因为它无法直接解决。问题仍然存在。

Android 谷歌播放

评论

1赞 Piyush 6/17/2019
在崩溃日志中,您可以找到 java 类和行号
1赞 VinothKumar Subramani 7/18/2019
我发现了一些 xda 开发人员网站 forum.xda-developers.com/...
4赞 3c71 9/9/2019
2 年后,我也在 Android 9 上看到了这个问题,遗憾的是没有迹象表明其根本原因。在寻找解决方案方面有任何进展吗?
9赞 saberrider 9/16/2019
同样在这里。对我来说,这个问题在 1 周前开始突然出现。无法检测到它来自哪里。它只发生在 OnePlus 设备上。
1赞 Richie 11/8/2019
我在运行 Android 9 的三星 J 系列设备上严重收到此错误。

答:

1赞 Furkan Yurdakul 8/20/2023 #1

在检查问题评论以及发生此问题的设备时,它似乎特定于设备子集,例如 OnePlus 设备和三星 J 系列。共同点是它们是 Android 9 设备。我已经检查了 Android 9 的源代码(这里是第 5750 行的方法调用,这里是第 5520 行的方法本身),我可以说这段代码与配置更改无关。虽然链路的行号并不完全相同,但它们在距离上是相关的(例如,5750 - 5520 = 280 来自源代码,6127 - 5892 = 285 来自堆栈跟踪)。非常接近但不精确),所以我假设框架正在调用该部分。该方法在首次启动时调用,并且配置更改仅在重新创建活动时发生,应用的配置不会更改。至少,给定的方法不会再次调用。ActivityThread.handleBindApplication

我还可以说该方法已成功调用,并且代码在方法内部崩溃,而不是在开始时崩溃。updateLocaleListFromAppContext

以下是代码的相关部分:

/**
 * The LocaleList set for the app's resources may have been shuffled so that the preferred
 * Locale is at position 0. We must find the index of this preferred Locale in the
 * original LocaleList.
 */
private void updateLocaleListFromAppContext(Context context, LocaleList newLocaleList) {
    final Locale bestLocale = context.getResources().getConfiguration().getLocales().get(0);
    final int newLocaleListSize = newLocaleList.size();
    for (int i = 0; i < newLocaleListSize; i++) {
        if (bestLocale.equals(newLocaleList.get(i))) {
            LocaleList.setDefault(newLocaleList, i);
            return;
        }
    }

    // The app may have overridden the LocaleList with its own Locale
    // (not present in the available list). Push the chosen Locale
    // to the front of the list.
    LocaleList.setDefault(new LocaleList(bestLocale, newLocaleList));
}

现在,有几件事需要考虑,

  • 这是从 AOSP(开源项目)中获取的,设备制造商通常会修改这些核心类。设备内部的方法可能已被修改,但可能性很小。
  • Google Play 管理中心有时可以删减有关堆栈跟踪的信息。
  • 如果堆栈跟踪是精确的,则此方法只能在 和 调用时崩溃。这样做的原因是:当生成堆栈跟踪时,它们的异常始终包含最后一个代码,而其他行将留下另一个堆栈跟踪。newLocaleList.size()bestLocale.equals(newLocaleList.get(i))
  • 另一种可能性是:由于 for 循环和 的用法,变量的大小可能在代码迭代时发生了变化,从而导致 在 处崩溃。不过,这个可能性更大,因为假设数据完整,该方法在崩溃时是可见的。newLocaleListSizenewLocaleListnewLocaleList.get(i)get(i)

根据信息,最有可能的罪魁祸首是变量和方法。在进一步检查源代码后,将创建传递的变量,该变量通过处理程序向下传递,并且其信息在 中更新。该方法使用 Android 的 PackageManager 调用特定信息更新,用于查询有关 APK / 加载的应用程序的信息,例如其信息、清单数据、元数据、活动等......bestLocalenewLocaleListnewLocaleListAppBindDatahandleBindApplication

此信息通常使用 IPC(或 AIDL)从系统传递到应用程序,并且该信息有时会损坏,从而导致此错误。因此,变量可能为 null。newLocaleList

由于这是系统中的问题,为了避免它,我只能建议几件事:

  • 如果可能,请分析设备本身,并查看应用是否在调试版本中崩溃。
  • 确保您的字符串已完全转换为所有语言,并且您不依赖默认语言(也称为具有所有字符串但特定配置没有它们的主要语言,除非它们在文件中标记)translatable=falsestrings.xml
  • 如果使用了类似的报告,请检查 Firebase Crashlytics 中是否存在(它可能不存在,因为应用在正确创建应用之前就崩溃了,但 Firebase 服务有时仍然可以上传。它还可以包含有关堆栈跟踪的详细信息。
  • 检查崩溃是否发生在 Android 9 模拟器(官方模拟器 Genymotion 模拟器)中
  • 您还可以使用三星测试实验室的在线三星设备(尽管时间很短),并查看是否可以观察到崩溃。您可能会获得完整的堆栈跟踪,并且可以为您指明正确的方向。

这些是我的发现,希望它们在某种程度上有用。