这个问题就像一个逻辑谜题。你被警告了。
我正在开发一个集成到其他应用程序的库。一个人抱怨说他们只看到了一些用户的崩溃:
java.lang.NoClassDefFoundError: com.somecompany.subpackage.SomeAsyncTaskSubclass
at com.somecompany.subpackage.ClassA.instantiateInstanceOfSomeAsyncTaskSubclass(ClassA.java:105)
at
com.somecompany.subpackage.Blah.loadsomedata(MyController.java:180)
at com.somecompany.subpackage.Blah.loadsomemoredata(MyController.java:164)
at com.somecompany.subpackage.SomeView.loadsomemoredata(SomeView.java:213)
com.other.blah.Blah.preloadstuff(Blah.java:118)
at
com.other.blah.Controller.loadSomething(Controller.java:100)
at
com.other.blah.Controller.preloadSomething(Controller.java:144)
at org.cocos2dx.lib.Cocos2dxRenderer.nativeRender(Native Method)
at org.cocos2dx.lib.Cocos2dxRenderer.onDrawFrame(Cocos2dxRenderer.java:94)
at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1332)
at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1116)
发生崩溃的代码行位于:
public class ClassA {
public void instantiateInstanceOfSomeAsyncTaskSubclass(){
SomeAsyncTaskSubclass crashHere = new SomeAsyncTaskSubclass(); //<--- this is where it crashes
}
}
并且在同一个包中,有......
class SomeAsyncTaskSubclass extends AsyncTask<String, Void, SomeCustomObject> {
// some code here...
}
以下是我被告知或我知道的事情:
此崩溃只发生在某些用户身上。 (但是基于Google Play崩溃报告。那么是不准确?还是生成的样本太慢?)
即使使用签名版本,开发人员也无法在内部重现此错误。 (我已经检查了签名的构建并对其进行了dedexed以查看该类存在于src中,所以我相信他)
但当应用程序在Play商店上线,并且人们下载了他的新版本时,他突然看到一些人的崩溃报告,据信主要是设备2.3.x,虽然这是未经证实的)
他声称他更新为“api 17”。当人们这么说时,他们是否意味着建立目标17?或者人们是指更新到ADT 17?因为我知道ADT搞砸了lib / libs文件夹问题。
他好像正在使用eclipse。
他通过c handler.post()
这怎么可能?
我很困惑为什么只有一些用户看到NoClassDefFoundError
?这是一个巨大的谷歌游戏崩溃报告问题?比如,所有用户都看到了它,但谷歌播放说只有部分用户看到了这个问题? (我还没有与开发人员确认,但我相当肯定他通过从Play商店下载实时版本进行测试,他没有看到任何错误,并且这段代码是公平运行的。)
据我所知,NoClassDefFoundError
只有当类通过三个类加载器之一存在时,但是在运行时,没有一个类加载器可以找到特定的类。
这是一个问题吗?我读过proguard只在发布时运行。
这是一个AsyncTask问题吗?我已经读过AsyncTasks必须首次在UI线程上实例化。虽然,我不确定为什么会导致NoClassDefFoundError
。
有什么想法吗?
答案 0 :(得分:1)
可能有多种原因导致您的应用中出现 //Get the correct screen size even if the device has a hideable navigation bar (e.g. the Samsung Galaxy S8)
View decorView = getWindow().getDecorView(); //if you use this in a fragment, use getActivity before getWindow()
Rect r = new Rect();
decorView.getWindowVisibleDisplayFrame(r);
int screenHeight = r.bottom; // =2220 on S8 with hidden NavBar and =2076 with enabled NavBar
int screenWidth = r.right; // =1080 on S8
,例如:
NoClassDefFoundError
,您可以关注此官方Android资源https://developer.android.com/studio/build/multidex#mdex-gradle MultiDEX
是不够的,您需要在主DEX文件中声明一些类。基本上你只需要将缺少的类添加到文件中,因此它们会在应用程序启动时加载,如Dean Wild指出的那样。这是因为有时构建工具可能会在计算要添加的类时遇到麻烦。官方文件:https://developer.android.com/studio/build/multidex#keep MultiDEX
类以使用某些自定义代码对其进行扩展,那么您可能必须从Application
类继承,而不是从MultiDexApplication
类继承。Application
或MonitoringInstrumentation
工具,则不会招致AndroidJUnitRunner
,但您可能会得到它们。如果是这种情况,那么只需在NoClassDefFoundError
方法中添加以下代码: onCreate()
方法内容:
onCreate()
答案 1 :(得分:0)
针对SDK ICS或更高版本构建您的项目。
他们已经在ICS +中自动加载了AsyncTask。这就是问题所在。
答案 2 :(得分:0)
启用multidex会导致我出现此问题。我需要multidex,因为我包括整个Google Play服务库。通过仅包含我需要的组件(在我的情况下为GCM),我能够禁用multidex并防止出现此问题。
我知道这不是一个真正的修复,但我认为如果可能的话,我应该避免使用multidex。