Android 4.4 KitKat随机崩溃

时间:2013-12-06 17:07:21

标签: android dalvik android-4.4-kitkat

编辑:在进行投票和暗示之前,请理解我无法重现此错误。这种情况经常发生在我无法访问的某些设备上,但在固件重置后却没有!

我最近在为客户开发的应用中发现了随机崩溃。 该应用程序在3年后现在有大约100,000个活跃用户。

我们已经看到Nexus 4和5的崩溃,两者都是Android 4.4 KitKat。

我们无法在我们自己的运行4.4的Nexus 4和5上重现它。

我们通过我们的支持获得了客户。他告诉我们,在调用新活动时,每次都在同一个地方发生崩溃。他经营的是Dalvik,而不是ART。重置固件后,应用程序运行正常,无法再次重现!

我出于法律原因无法发布源或布局,但是有这个堆栈跟踪:

java.lang.RuntimeException: Unable to start activity ComponentInfo{xx.xxx.xxxxx.xxx.xxxxxx.prod/xx.xxx.xxxxx.xxx.PaymentsActivity}: java.lang.NullPointerException
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2176)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2226)
at android.app.ActivityThread.access$700(ActivityThread.java:135)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1397)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4998)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:777)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:593)
at de.robv.android.xposed.XposedBridge.main(XposedBridge.java:126)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.NullPointerException
at android.view.View.sendAccessibilityEventUncheckedInternal(View.java:4938)
at android.view.View.sendAccessibilityEventUnchecked(View.java:4919)
at android.view.View$SendViewStateChangedAccessibilityEvent.run(View.java:19433)
at android.view.View$SendViewStateChangedAccessibilityEvent.runOrPost(View.java:19465)
at android.view.View.notifyViewAccessibilityStateChangedIfNeeded(View.java:7265)
at android.view.View.setFlags(View.java:8990)
at android.view.View.setVisibility(View.java:6020)
at android.view.LayoutInflater.parseInclude(LayoutInflater.java:859)
at de.robv.android.xposed.XposedBridge.invokeOriginalMethodNative(Native Method)
at de.robv.android.xposed.XposedBridge.handleHookedMethod(XposedBridge.java:547)
at android.view.LayoutInflater.parseInclude(Native Method)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:745)
at android.view.LayoutInflater.inflate(LayoutInflater.java:492)
at de.robv.android.xposed.XposedBridge.invokeOriginalMethodNative(Native Method)
at de.robv.android.xposed.XposedBridge.handleHookedMethod(XposedBridge.java:547)
at android.view.LayoutInflater.inflate(Native Method)
at android.view.LayoutInflater.inflate(LayoutInflater.java:397)
at android.view.LayoutInflater.inflate(LayoutInflater.java:353)
at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:290)
at android.app.Activity.setContentView(Activity.java:1928)
at xx.xxx.xxxxx.xxx.StandardActivity.setContentView(StandardActivity.java:289)
at xx.xxx.xxxxx.xxx.PaymentsActivity.onCreate(PaymentsActivity.java:61)
at android.app.Activity.performCreate(Activity.java:5243)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2140)
... 12 more

编辑:没有xposed的第二个堆栈跟踪

java.lang.RuntimeException: Unable to start activity ComponentInfo{xx.xxx.xxxxx.xxx.xxxxx.prod/xx.xxx.xxxxx.xxx.PaymentsActivity}: java.lang.NullPointerException
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2176)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2226)
at android.app.ActivityThread.access$700(ActivityThread.java:135)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1397)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4998)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:777)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:593)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.NullPointerException
at android.view.View.sendAccessibilityEventUncheckedInternal(View.java:4938)
at android.view.View.sendAccessibilityEventUnchecked(View.java:4919)
at android.view.View$SendViewStateChangedAccessibilityEvent.run(View.java:19433)
at android.view.View$SendViewStateChangedAccessibilityEvent.runOrPost(View.java:19465)
at android.view.View.notifyViewAccessibilityStateChangedIfNeeded(View.java:7265)
at android.view.View.setFlags(View.java:8990)
at android.view.View.setVisibility(View.java:6020)
at android.view.LayoutInflater.parseInclude(LayoutInflater.java:859)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:745)
at android.view.LayoutInflater.inflate(LayoutInflater.java:492)
at android.view.LayoutInflater.inflate(LayoutInflater.java:397)
at android.view.LayoutInflater.inflate(LayoutInflater.java:353)
at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:290)
at android.app.Activity.setContentView(Activity.java:1928)
at xx.xxx.xxxxx.xxx.StandardActivity.setContentView(StandardActivity.java:289)
at xx.xxx.xxxxx.xxx.PaymentsActivity.onCreate(PaymentsActivity.java:61)
at android.app.Activity.performCreate(Activity.java:5243)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2140)
... 11 more

在setContentView()中设置的布局包含框架,否则它非常标准且简单。

非常感谢任何输入: - )

2 个答案:

答案 0 :(得分:12)

我也遇到了一些我正在维护的代码问题。通过在辅助功能选项中启用TalkBack,我能够始终如一地复制错误。

首先,这是来自View.java的方法,其中使用了导致崩溃的空引用,来自Android的KitKat版本:

void sendAccessibilityEventUncheckedInternal(AccessibilityEvent event) {
    if (!isShown()) {
        return;
    }
    onInitializeAccessibilityEvent(event);
    // Only a subset of accessibility events populates text content.
    if ((event.getEventType() & POPULATING_ACCESSIBILITY_EVENT_TYPES) != 0) {
        dispatchPopulateAccessibilityEvent(event);
    }
    // In the beginning we called #isShown(), so we know that getParent() is not null.
    getParent().requestSendAccessibilityEvent(this, event);
}

对我来说,根本原因是一个自定义的View,它已经覆盖了View.isShown(),如下所示:

public boolean isShown(){
  return someCondition;
}

这意味着sendAccessibilityEventUncheckedInternal会在继续执行之前运行if(!isShown())检查,即使View有一个null父项,也会导致崩溃。

我原本以为这是一个并发问题,因为我假设isShown()检查确保父级不为null,并且在执行sendAccessibilityEventUncheckedInternal期间对View的父级的引用已被更改。错!

如果您发现类似的问题,特别是在您没有编写的代码中,您可以通过包含超类的isShown()的结果来轻松防止此崩溃(假设您正在更改View的直接子类中的代码):

public boolean isShown(){
  return super.isShown() && someCondition;
}

答案 1 :(得分:2)

我的用户遇到了同样的问题,而且似乎是由一个或多个辅助功能选项打开引起的。我的一些用户正在使用Pebble智能手表,它安装了一个辅助功能选项 - 所以它不仅仅是TalkBack等。

诊断

https://github.com/android/platform_frameworks_base/blob/kitkat-mr1-release/core/java/android/view/View.java#L9006

处查看KitKat View#setFlags()方法的这一点
if (accessibilityEnabled) {
  ...
  notifyViewAccessibilityStateChangedIfNeeded(
                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
}

如果在将视图附加到视图层次结构(即没有父级)之前执行,则会向您发送以NullPointerException 结尾的兔子洞,因为在我https://github.com/android/platform_frameworks_base/blob/kitkat-mr1-release/core/java/android/view/View.java#L4952View#sendAccessibilityEventUncheckedInternal() {/ 1}}:

getParent().requestSendAccessibilityEvent(this, event);

我的解决方法(看起来它不适合你)

对于我的应用,我正在以编程方式创建View子类,并在构造函数中调用View#setOnClickListener()。相反,我现在从

调用View#setOnClickListener()
@Override
protected void onAttachedToWindow() {
    super.onAttachedToWindow();
    /* Due to a bug in how Android 4.4 handles accessibility options,
     * we can't set the onClick listener until this View has a parent or we will
     * get an NPE. */
    setOnClickListener(this);
}

它的工作原理是因为ViewView#onAttachedToWindow()被调用时会有一个父级。

您的堆栈跟踪更有问题。您通过XML布局上的属性进入兔子洞。我没有想出你的想法。一个想法是,这必须只发生在应用程序启动时 - 否则几乎所有的XML布局通知都会触发崩溃,因为有很多路径会引导您完成View#setFlags()。在我的应用程序中,这一点似乎是唯一的崩溃,它发生在应用程序启动时。这不是一个令人愉快的想法,但一种可能性是重新订购事情以便稍后夸大这一观点。