Java Play Store崩溃报告:android.view.view$DeclaredOnClickListener.onClick上的IllegalStateException

Java Play Store崩溃报告:android.view.view$DeclaredOnClickListener.onClick上的IllegalStateException,java,android,google-play,illegalstateexception,Java,Android,Google Play,Illegalstateexception,我的一个应用程序收到了一些关于IllegalStateException的崩溃报告。堆栈跟踪显示它来自android.view.view$DeclaredOnClickListener.onClick(视图)。我在测试或日常使用中从未遇到过这个错误(我每天在运行安卓6.0.1的三星Note4上使用我自己)。老实说,我不知道从哪里开始查找,因为堆栈跟踪似乎甚至没有引用我自己的任何代码,只是平台代码。我错过了什么?此版本确实使用支持库,但不使用片段,这是其他解决此错误的方法所引用的 下面我粘贴了一个

我的一个应用程序收到了一些关于IllegalStateException的崩溃报告。堆栈跟踪显示它来自android.view.view$DeclaredOnClickListener.onClick(视图)。我在测试或日常使用中从未遇到过这个错误(我每天在运行安卓6.0.1的三星Note4上使用我自己)。老实说,我不知道从哪里开始查找,因为堆栈跟踪似乎甚至没有引用我自己的任何代码,只是平台代码。我错过了什么?此版本确实使用支持库,但不使用片段,这是其他解决此错误的方法所引用的

下面我粘贴了一个堆栈痕迹。这是来自运行Android 6.0的Moto G Turbo

java.lang.IllegalStateException: 
  at android.view.View$DeclaredOnClickListener.onClick(View.java:4455)
  at android.view.View.performClick(View.java:5201)
  at android.view.View$PerformClick.run(View.java:21163)
  at android.os.Handler.handleCallback(Handler.java:746)
  at android.os.Handler.dispatchMessage(Handler.java:95)
  at android.os.Looper.loop(Looper.java:148)
  at android.app.ActivityThread.main(ActivityThread.java:5443)
  at java.lang.reflect.Method.invoke(Native Method:0)
  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:728)
  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)
Caused by: java.lang.reflect.InvocationTargetException: 
  at java.lang.reflect.Method.invoke(Native Method:0)
  at android.view.View$DeclaredOnClickListener.onClick(View.java:4450)

很抱歉给出了这么长的答案,但我认为解释如何深入Android框架来调试这个问题很有用

引发此异常的代码可在此处访问:

反射及其在单击侦听器中的使用

基本上,它所做的是使用反射调用基于字符串的方法。此方法由应用程序开发人员定义,用于响应单击的按钮。这通常是这样做的,因为您可以通过XML指定onClickListener方法,例如,您可以说invoke“goDoWhatever”,而不是通常的“onClick”。反射采用此方法的字符串表示形式,并尝试对该名称的指定类调用方法

当所需的方法不存在时会发生反射错误,例如,如果名称错误、方法是私有的或参数不同

注意,在这种情况下有两种不同的异常,一种是非公共方法,另一种是无法执行它。我不知道为什么堆栈跟踪没有与IllegalStateException关联的消息,但制造商可以根据需要修改此代码

我怀疑您有一个名称正确的方法,因为如果名称错误,resolve method函数会抛出不同的错误:

4463        @NonNull
4464        private Method resolveMethod(@Nullable Context context, @NonNull String name) {
4465            while (context != null) {
4466                try {
4467                    if (!context.isRestricted()) {
4468                        return context.getClass().getMethod(mMethodName, View.class);
4469                    }
                ...
4485            throw new IllegalStateException("Could not find method " + mMethodName
4486                    + "(View) in a parent or ancestor Context for android:onClick "
4487                    + "attribute defined on view " + mHostView.getClass() + idText);
4488        }
4489    }
这就给我们留下了两种可能性,我可以想到:它找到的方法有错误的签名,或者它找到的方法是静态/私有的

我将如何调试它:

我猜您在xml的某个地方指定了一个单击侦听器(在xml文件中查找“android:onClick=”。然后在应用程序中搜索所有同名的方法,并确保它们以单个视图作为参数(确保您也在文件中导入了“android.View.View”,因为导入错误的视图可能会导致这种情况)。还要确保它们不是静态的。可能也值得查找私有的东西,因为这也可能会导致问题,但根据堆栈跟踪,这种情况似乎不太可能发生

为什么这个问题很难重现:

如果您注意到android框架中的方法“resolveMethod”只返回相同名称的第一个方法,那么java拥有一个类是有效的:

class Foo{
    void bar(String s){}
    void bar(View s){}
方法签名由一个名称(如“bar”)和一个参数列表组成(在本例中,是一个包含一项“视图”的列表,还是一个包含一项“字符串”的列表)

此Android框架代码可能会找到“void bar(String s)”而不是“void bar(View s)”。这可能会导致难以重现的错误,因为反射查找方法的顺序是不确定的()。因此,您可能很难复制它,因为特定设备可能会以某种方式决定性地对其进行迭代,但不一定与其他设备/实现的方式相同


我希望这能有所帮助!请告诉我结果如何,我是一名研究生,正在研究软件缺陷,比如这类缺陷,因此详细信息对我非常有用。

我最近收到了两个程序中的一个程序的类似错误报告,这些崩溃发生在Android 6.0.1和7.1上。受影响的应用程序已经在商店中或者几个月,但这种现象对我来说是全新的,并且在几天内重复出现,从统计角度来看,这是不可能的

然而,FrearTheCron的解释非常有用,但最终并不令人满意。首先,“非法州例外”应该出现在第4455行,但第4455行处理“非法州例外”,而第一个在第4458行处理。这是一个矛盾,我没有任何解释。也许这是Java虚拟机中的一个错误

此外,我在我的应用程序中检查了所有“android:onClick”条目和回调,所有这些条目和回调都有相当独特的名称,因此没有相同名称和不同参数的变体

这些检查让我认为问题不是由应用程序中的编码错误引起的,而是由安卓的不当行为引起的

但这是怎么发生的,又是怎么避免的呢?我的一个应用程序使用了两个活动,而另一个应用程序只使用了一个,但有片段。只有两个活动的应用程序受到影响。我的理论是,安卓会与视图和活动混淆,可能是由一些奇怪的暂停/停止/销毁/创建/启动/恢复活动触发的ty状态更改模式,并尝试将视图与错误的活动关联。例如,my UM Player的视图显示相册的曲目,系统检测到对曲目的单击,但此单击会发送到另一个活动,该活动显示设备上的相册,无法处理单击曲目回调。结果如下所述在坠机报告中

因此,我将改变我的应用程序,使这两个活动对每个“android::onClick”都有回调,并忽略发送到错误处理程序的调用


也许这会有帮助。如果在黑暗中再亮一点,我们将不胜感激。

我在play store中遇到了一个相同的错误。肯定没有足够的信息来快速指出问题。担心CRO
class Foo{
    void bar(String s){}
    void bar(View s){}