提问人:Richie 提问时间:6/17/2019 最后编辑:NoHarmDanRichie 更新时间:10/16/2023 访问量:3518
在 Android SDK 的方法 updateLocaleListFromAppContext 中获取 NullPointerException
Getting NullPointerException in Android SDK's method updateLocaleListFromAppContext
问:
我在 PlayStore 上上传了一个应用程序,但从java.lang.NullPointerException
android.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 本身的一侧,问题在于如何避免它,因为它无法直接解决。问题仍然存在。
答:
在检查问题评论以及发生此问题的设备时,它似乎特定于设备子集,例如 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 循环和 的用法,变量的大小可能在代码迭代时发生了变化,从而导致 在 处崩溃。不过,这个可能性更大,因为假设数据完整,该方法在崩溃时是可见的。
newLocaleListSize
newLocaleList
newLocaleList.get(i)
get(i)
根据信息,最有可能的罪魁祸首是变量和方法。在进一步检查源代码后,将创建传递的变量,该变量通过处理程序向下传递,并且其信息在 中更新。该方法使用 Android 的 PackageManager 调用特定信息更新,用于查询有关 APK / 加载的应用程序的信息,例如其信息、清单数据、元数据、活动等......bestLocale
newLocaleList
newLocaleList
AppBindData
handleBindApplication
此信息通常使用 IPC(或 AIDL)从系统传递到应用程序,并且该信息有时会损坏,从而导致此错误。因此,变量可能为 null。newLocaleList
由于这是系统中的问题,为了避免它,我只能建议几件事:
- 如果可能,请分析设备本身,并查看应用是否在调试版本中崩溃。
- 确保您的字符串已完全转换为所有语言,并且您不依赖默认语言(也称为具有所有字符串但特定配置没有它们的主要语言,除非它们在文件中标记)
translatable=false
strings.xml
- 如果使用了类似的报告,请检查 Firebase Crashlytics 中是否存在(它可能不存在,因为应用在正确创建应用之前就崩溃了,但 Firebase 服务有时仍然可以上传。它还可以包含有关堆栈跟踪的详细信息。
- 检查崩溃是否发生在 Android 9 模拟器(官方模拟器和 Genymotion 模拟器)中
- 您还可以使用三星测试实验室的在线三星设备(尽管时间很短),并查看是否可以观察到崩溃。您可能会获得完整的堆栈跟踪,并且可以为您指明正确的方向。
这些是我的发现,希望它们在某种程度上有用。
评论