ExceptionWithContext在尝试使用Ant构建Android应用程序时被抛出



我试过在谷歌和stackoverflow上搜索这个问题的答案,但我找不到任何人有我遇到的确切问题。我正试图建立一个持续集成服务器(特别是Bamboo),以便在每次有人更改源代码管理时更新、构建和导出APK。当我手动完成每一步时,我在本地机器上和使用我设置的作业时,在服务器上都遇到了同样的错误。当我到达构建的dex步骤时,就会发生错误。到目前为止,我已经得到了与ant debugant releaseant clean debugant clean release相同的输出。整个dex步骤的输出,包括错误,如下所示:

-dex:
      [dex] input: C:Users...Androidbinclasses
      [dex] input: C:Users...google-play-services_libbinclasses.jar
      [dex] input: C:Program Files (x86)Androidandroid-sdktoolssupportannotations.jar
      [dex] input: C:Users...AndroidlibsFlurryAgent.jar
      [dex] input: C:Users...Androidlibsgcm.jar
      [dex] input: C:Users...Androidlibsandroid-support-v4.jar
      [dex] input: C:Users...google-play-services_liblibsgoogle-play-services.jar
      [dex] Pre-Dexing C:Users...google-play-services_libbinclasses.jar -> classes-64c0adfe92ddc950c7ab8c5002ceabf2.jar
      [dex] Pre-Dexing C:Program Files (x86)Androidandroid-sdktoolssupportannotations.jar -> annotations-62bab95d6948a2db17bbc7976160b014.jar
      [dex] Pre-Dexing C:Users...AndroidlibsFlurryAgent.jar -> FlurryAgent-499d43756a3ce626a64773e6dfd5eaec.jar
      [dex] Pre-Dexing C:Users...Androidlibsgcm.jar -> gcm-ae2640f44640eb4fd7b13964b65d2d70.jar
      [dex] Pre-Dexing C:Users...Androidlibsandroid-support-v4.jar -> android-support-v4-fa30b373a3e3ba9f2cf94900a9eb42fe.jar
      [dex] Pre-Dexing C:Users...google-play-services_liblibsgoogle-play-services.jar -> google-play-services-9efad6e9178399c185fae6c0b6bdc4c6.jar
      [dex] Converting compiled files and external libraries into C:Users...Androidbinclasses.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 v19.2和Android构建工具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语句和主体之间的交互会引起一些问题。另一个奇怪的部分是,我们在应用程序的另一个文件中有完全相同的if块(一个活动,而这个是一个服务)。

我在编译发布项目时遇到了同样的异常。我的代码是:

if (BuildConfig.DEBUG) {
    myView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            // Do something
        }
    });
}

由于BuildConfig.DEBUG是一个值为false的常量,因此块中的代码被识别为死代码并在优化时删除。

CfTranslator(Classfile Translator)希望为块内的匿名类创建一个单独的文件(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
        }
    });
}

经过几个月的努力,我终于找到了一个适合我的解决方案。请确保您所引用的类(可能是设置?可能是AndroidUnaughtException Handler?)都不是私有的。Gradle无法处理它,并且在类中找不到方法。只需将其更改为public(或者如果类是嵌套的,则只需删除标志以保持默认值),就可以开始了。

除了@Albert Jan提出的其他解决方案是在方法中"包装"该常量。类似的东西

public boolean isInDeveloperMode(){ return BuildConfig.DEBUG; }

在这种情况下,它将不会被gradle"解析"为常量,并且在构建期间不会出现问题。

这种方法最著名的"漏洞"可能是Android SDK中UserManager类的isUserAGoat()方法。关于这种方法的可能用途,这里有非常流行的讨论。。享受;)

希望这对有类似问题的人有用

相关内容

  • 没有找到相关文章

最新更新