我尝试在Google和stackoverflow上搜索这个问题的答案,但我一直无法找到任何有我确切问题的人。每次有人在源代码管理中进行更改时,我都会尝试设置一个持续集成服务器(特别是Bamboo)来更新,构建和导出APK。当我使用我设置的工作时,当我每一步手动操作时,我在本地机器上遇到同样的错误。当我到达构建的dex步骤时会发生错误。到目前为止,我已经使用ant debug
,ant release
,ant clean debug
和ant clean release
获得了相同的输出。整个dex步骤的输出(包括错误)如下:
-dex:
[dex] input: C:\Users\...\Android\bin\classes
[dex] input: C:\Users\...\google-play-services_lib\bin\classes.jar
[dex] input: C:\Program Files (x86)\Android\android-sdk\tools\support\annotations.jar
[dex] input: C:\Users\...\Android\libs\FlurryAgent.jar
[dex] input: C:\Users\...\Android\libs\gcm.jar
[dex] input: C:\Users\...\Android\libs\android-support-v4.jar
[dex] input: C:\Users\...\google-play-services_lib\libs\google-play-services.jar
[dex] Pre-Dexing C:\Users\...\google-play-services_lib\bin\classes.jar -> classes-64c0adfe92ddc950c7ab8c5002ceabf2.jar
[dex] Pre-Dexing C:\Program Files (x86)\Android\android-sdk\tools\support\annotations.jar -> annotations-62bab95d6948a2db17bbc7976160b014.jar
[dex] Pre-Dexing C:\Users\...\Android\libs\FlurryAgent.jar -> FlurryAgent-499d43756a3ce626a64773e6dfd5eaec.jar
[dex] Pre-Dexing C:\Users\...\Android\libs\gcm.jar -> gcm-ae2640f44640eb4fd7b13964b65d2d70.jar
[dex] Pre-Dexing C:\Users\...\Android\libs\android-support-v4.jar -> android-support-v4-fa30b373a3e3ba9f2cf94900a9eb42fe.jar
[dex] Pre-Dexing C:\Users\...\google-play-services_lib\libs\google-play-services.jar -> google-play-services-9efad6e9178399c185fae6c0b6bdc4c6.jar
[dex] Converting compiled files and external libraries into C:\Users\...\Android\bin\classes.dex...
[dx]
[dx] UNEXPECTED TOP-LEVEL EXCEPTION:
[dx] com.android.dx.util.ExceptionWithContext
[dx] at com.android.dx.util.ExceptionWithContext.withContext(ExceptionWithContext.java:46)
[dx] at com.android.dx.dex.cf.CfTranslator.processMethods(CfTranslator.java:344)
[dx] at com.android.dx.dex.cf.CfTranslator.translate0(CfTranslator.java:134)
[dx] at com.android.dx.dex.cf.CfTranslator.translate(CfTranslator.java:87)
[dx] at com.android.dx.command.dexer.Main.processClass(Main.java:487)
[dx] at com.android.dx.command.dexer.Main.processFileBytes(Main.java:459)
[dx] at com.android.dx.command.dexer.Main.access$400(Main.java:67)
[dx] at com.android.dx.command.dexer.Main$1.processFileBytes(Main.java:398)
[dx] at com.android.dx.cf.direct.ClassPathOpener.processOne(ClassPathOpener.java:135)
[dx] at com.android.dx.cf.direct.ClassPathOpener.processDirectory(ClassPathOpener.java:191)
[dx] at com.android.dx.cf.direct.ClassPathOpener.processOne(ClassPathOpener.java:123)
[dx] at com.android.dx.cf.direct.ClassPathOpener.processDirectory(ClassPathOpener.java:191)
[dx] at com.android.dx.cf.direct.ClassPathOpener.processOne(ClassPathOpener.java:123)
[dx] at com.android.dx.cf.direct.ClassPathOpener.processDirectory(ClassPathOpener.java:191)
[dx] at com.android.dx.cf.direct.ClassPathOpener.processOne(ClassPathOpener.java:123)
[dx] at com.android.dx.cf.direct.ClassPathOpener.processDirectory(ClassPathOpener.java:191)
[dx] at com.android.dx.cf.direct.ClassPathOpener.processOne(ClassPathOpener.java:123)
[dx] at com.android.dx.cf.direct.ClassPathOpener.processDirectory(ClassPathOpener.java:191)
[dx] at com.android.dx.cf.direct.ClassPathOpener.processOne(ClassPathOpener.java:123)
[dx] at com.android.dx.cf.direct.ClassPathOpener.process(ClassPathOpener.java:109)
[dx] at com.android.dx.command.dexer.Main.processOne(Main.java:422)
[dx] at com.android.dx.command.dexer.Main.processAllFiles(Main.java:333)
[dx] at com.android.dx.command.dexer.Main.run(Main.java:209)
[dx] at com.android.dx.command.dexer.Main.main(Main.java:174)
[dx] at com.android.dx.command.Main.main(Main.java:91)
[dx] Caused by: java.lang.NullPointerException
[dx] at com.android.dx.cf.code.ConcreteMethod.<init>(ConcreteMethod.java:87)
[dx] at com.android.dx.cf.code.ConcreteMethod.<init>(ConcreteMethod.java:75)
[dx] at com.android.dx.dex.cf.CfTranslator.processMethods(CfTranslator.java:247)
[dx] ... 23 more
[dx] ...while processing <init> (Lcom/.../android/LocationService;)V
[dx] ...while processing com/.../android/LocationService$1.class
[dx]
[dx] 1 error; aborting
对于上下文,我在Windows机器上使用Ant v1.9.2和Android build-tools v18.0.1,我没有以任何方式编辑构建脚本。我在两个目录中使用android update project --path .
为应用程序生成一个,为库生成一个。我还没有尝试将其设置为自动使用正确的密钥库进行签名,尽管我的(有限的)理解不应该是必要的,至少不适用于使用Ant的调试版本。
以前有人见过这个特别的问题吗?这是生成的.class文件的问题吗?构建文件?这是我第一次尝试使用Ant进行构建(我通常只是让Eclipse为我做了所有艰苦的工作),所以我很少继续。任何帮助将不胜感激。
更新:如果有人关注这个问题,我的问题似乎已经解决了。怎么以及为什么,我不知道。我今天早上尝试更新了源代码(我们进行了一些更改),重新 android update project -p .
,尝试ant clean debug
,然后看,它有效。就像ant release
一样,它甚至用我给它的钥匙正确签名。我最好的猜测是,在LocationService类文件中有一些奇怪的东西,尽管它超出了我的范围。
更新2:我在第一次更新中说的任何内容现在都无效。我已经解决了这个问题,但我并没有更接近理解它。这段代码是罪魁祸首:
if (Settings.DEBUG) {
Thread.currentThread().setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread thread, Throwable ex) {
storeDebugNotification(AndroidUncaughtExceptionHandler.getStackTraceString(ex));
}
});
}
这是事情变得奇怪的地方。当Settings.DEBUG
标志为true
时,使用ant可以很好地构建。当它是false
时,它会失败,给我上面显示的错误。当我评论整个事情时,它适用于DEBUG
设置。同样适用于if (Settings.DEBUG)
线及其花括号,但身体保持完整,以及评论身体并单独留下if部分。所以......我在这里不知所措。当DEBUG
为false时,if语句与正文之间的交互,在此特定文件中,会导致问题。另一个奇怪的部分是,我们在应用程序的另一个文件(活动,而这个是服务)中有完全相同的块。
答案 0 :(得分:36)
我在编译项目时遇到了同样的异常。我的代码是:
if (BuildConfig.DEBUG) {
myView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// Do something
}
});
}
由于 BuildConfig.DEBUG 是值为 false 的常量,因此块中的代码会被识别为死代码,并在优化时删除。
CfTranslator(类文件转换器)想要为块内的匿名类创建一个单独的文件( SomeClass $ 1.class ),但由于它已被优化掉了会发生错误。我把花括号外的匿名课程解决了问题:
View.OnClickListener lClickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
// Do something
}
};
if (BuildConfig.DEBUG) {
myView.setOnClickListener(lClickListener);
}
更新:另一种解决此问题的方法(@Ewoks在下面的回答中描述)是:
public boolean isInDeveloperMode() {
return BuildConfig.DEBUG;
}
...
if (isInDeveloperMode()) {
myView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// Do something
}
});
}
答案 1 :(得分:9)
经过几个月的斗争这个确切的问题,我终于找到了适合我的解决方案。可能不是你的情况。确保您所引用的类(可能是设置?也许是AndroidUncaughtExceptionHandler?)都不是私有的。 Gradle无法处理它,也无法在类中找到该方法。只需将其更改为public(或者只是删除标志以保持默认值,如果类是嵌套的),那么你应该好好去。
答案 2 :(得分:2)
@ Albert-Jan提出的其他解决方案是在方法中“包装”该常量。像
这样的东西 public boolean isInDeveloperMode(){
return BuildConfig.DEBUG;
}
在这种情况下,它不会被gradle“解析”为常量,并且在构建期间不会出现问题。
这种方法最着名的“漏洞利用”可能是Android SDK中UserManager类的isUserAGoat()方法。有very popular discussion here关于此方法的可能用途..享受;)
希望这对有类似问题的人有用