【问题标题】:Building Cordovo Android app fails - Dex cannot parse version 52 byte code error message构建 Cordovo Android 应用程序失败 - Dex 无法解析版本 52 字节代码错误消息
【发布时间】:2020-01-05 16:02:58
【问题描述】:

我正在尝试构建一个 Cordova Android 应用程序,当我尝试使用调用 cordova build 命令的自定义脚本进行构建时,我收到以下错误 - 知道这可能是什么吗?

Dex: Error converting bytecode to dex:
Cause: Dex cannot parse version 52 byte code.
This is caused by library dependencies that have been compiled using Java 8 or above.
If you are using the 'java' gradle plugin in a library submodule add
targetCompatibility = '1.7'
sourceCompatibility = '1.7'
to that submodule's build.gradle file.
    UNEXPECTED TOP-LEVEL EXCEPTION:
java.lang.RuntimeException: Exception parsing classes
        at com.android.dx.command.dexer.Main.processClass(Main.java:775)
        at com.android.dx.command.dexer.Main.processFileBytes(Main.java:741)
        at com.android.dx.command.dexer.Main.access$1200(Main.java:88)
        at com.android.dx.command.dexer.Main$FileBytesConsumer.processFileBytes(Main.java:1683)
        at com.android.dx.cf.direct.ClassPathOpener.processArchive(ClassPathOpener.java:284)
        at com.android.dx.cf.direct.ClassPathOpener.processOne(ClassPathOpener.java:166)
        at com.android.dx.cf.direct.ClassPathOpener.process(ClassPathOpener.java:144)
        at com.android.dx.command.dexer.Main.processOne(Main.java:695)
        at com.android.dx.command.dexer.Main.processAllFiles(Main.java:592)
        at com.android.dx.command.dexer.Main.runMultiDex(Main.java:376)
        at com.android.dx.command.dexer.Main.run(Main.java:290)
        at com.android.builder.internal.compiler.DexWrapper.run(DexWrapper.java:54)
        at com.android.builder.core.DexByteCodeConverter.lambda$dexInProcess$0(DexByteCodeConverter.java:173)
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at java.lang.Thread.run(Thread.java:748)
Caused by: com.android.dx.cf.iface.ParseException: bad class file magic (cafebabe) or version (0034.0000)
        at com.android.dx.cf.direct.DirectClassFile.parse0(DirectClassFile.java:476)
        at com.android.dx.cf.direct.DirectClassFile.parse(DirectClassFile.java:406)
        at com.android.dx.cf.direct.DirectClassFile.parseToInterfacesIfNecessary(DirectClassFile.java:388)
        at com.android.dx.cf.direct.DirectClassFile.getMagic(DirectClassFile.java:251)
        at com.android.dx.command.dexer.Main.parseClass(Main.java:787)
        at com.android.dx.command.dexer.Main.access$1600(Main.java:88)
        at com.android.dx.command.dexer.Main$ClassParserTask.call(Main.java:1722)
        at com.android.dx.command.dexer.Main.processClass(Main.java:773)
        ... 16 more

1 error; aborting

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':transformClassesWithDexForRelease'.
> com.android.build.api.transform.TransformException: java.lang.RuntimeException: java.lang.RuntimeException: com.android.ide.common.process.ProcessException: java.util.concurrent.ExecutionException: com.android.ide.common.process.ProcessException: Return code 1 for dex process

// 构建 gradle 文件

apply plugin: 'com.android.application'

buildscript {
    repositories {
        mavenCentral()
        jcenter()
    }

    // Switch the Android Gradle plugin version requirement depending on the
    // installed version of Gradle. This dependency is documented at
    // http://tools.android.com/tech-docs/new-build-system/version-compatibility
    // and https://issues.apache.org/jira/browse/CB-8143
    dependencies {
        classpath 'com.android.tools.build:gradle:2.2.3'
    }
}

// Allow plugins to declare Maven dependencies via build-extras.gradle.
allprojects {
    repositories {
        mavenCentral();
        jcenter()
    }
}

task wrapper(type: Wrapper) {
    gradleVersion = '2.14.1'
}

// Configuration properties. Set these via environment variables, build-extras.gradle, or gradle.properties.
// Refer to: http://www.gradle.org/docs/current/userguide/tutorial_this_and_that.html
ext {
    apply from: 'CordovaLib/cordova.gradle'
    // The value for android.compileSdkVersion.
    if (!project.hasProperty('cdvCompileSdkVersion')) {
        cdvCompileSdkVersion = null;
    }
    // The value for android.buildToolsVersion.
    if (!project.hasProperty('cdvBuildToolsVersion')) {
        cdvBuildToolsVersion = null;
    }
    // Sets the versionCode to the given value.
    if (!project.hasProperty('cdvVersionCode')) {
        cdvVersionCode = null
    }
    // Sets the minSdkVersion to the given value.
    if (!project.hasProperty('cdvMinSdkVersion')) {
        cdvMinSdkVersion = null
    }
    // Whether to build architecture-specific APKs.
    if (!project.hasProperty('cdvBuildMultipleApks')) {
        cdvBuildMultipleApks = null
    }
    // .properties files to use for release signing.
    if (!project.hasProperty('cdvReleaseSigningPropertiesFile')) {
        cdvReleaseSigningPropertiesFile = null
    }
    // .properties files to use for debug signing.
    if (!project.hasProperty('cdvDebugSigningPropertiesFile')) {
        cdvDebugSigningPropertiesFile = null
    }
    // Set by build.js script.
    if (!project.hasProperty('cdvBuildArch')) {
        cdvBuildArch = null
    }

    // Plugin gradle extensions can append to this to have code run at the end.
    cdvPluginPostBuildExtras = []
}

// PLUGIN GRADLE EXTENSIONS START
// PLUGIN GRADLE EXTENSIONS END

def hasBuildExtras = file('build-extras.gradle').exists()
if (hasBuildExtras) {
    apply from: 'build-extras.gradle'
}

// Set property defaults after extension .gradle files.
if (ext.cdvCompileSdkVersion == null) {
    ext.cdvCompileSdkVersion = privateHelpers.getProjectTarget()
}
if (ext.cdvBuildToolsVersion == null) {
    ext.cdvBuildToolsVersion = privateHelpers.findLatestInstalledBuildTools()
}
if (ext.cdvDebugSigningPropertiesFile == null && file('debug-signing.properties').exists()) {
    ext.cdvDebugSigningPropertiesFile = 'debug-signing.properties'
}
if (ext.cdvReleaseSigningPropertiesFile == null && file('release-signing.properties').exists()) {
    ext.cdvReleaseSigningPropertiesFile = 'release-signing.properties'
}

// Cast to appropriate types.
ext.cdvBuildMultipleApks = cdvBuildMultipleApks == null ? false : cdvBuildMultipleApks.toBoolean();
ext.cdvMinSdkVersion = cdvMinSdkVersion == null ? null : Integer.parseInt('' + cdvMinSdkVersion)
ext.cdvVersionCode = cdvVersionCode == null ? null : Integer.parseInt('' + cdvVersionCode)

def computeBuildTargetName(debugBuild) {
    def ret = 'assemble'
    if (cdvBuildMultipleApks && cdvBuildArch) {
        def arch = cdvBuildArch == 'arm' ? 'armv7' : cdvBuildArch
        ret += '' + arch.toUpperCase().charAt(0) + arch.substring(1);
    }
    return ret + (debugBuild ? 'Debug' : 'Release')
}

// Make cdvBuild a task that depends on the debug/arch-sepecific task.
task cdvBuildDebug
cdvBuildDebug.dependsOn {
    return computeBuildTargetName(true)
}

task cdvBuildRelease
cdvBuildRelease.dependsOn {
    return computeBuildTargetName(false)
}

task cdvPrintProps << {
    println('cdvCompileSdkVersion=' + cdvCompileSdkVersion)
    println('cdvBuildToolsVersion=' + cdvBuildToolsVersion)
    println('cdvVersionCode=' + cdvVersionCode)
    println('cdvMinSdkVersion=' + cdvMinSdkVersion)
    println('cdvBuildMultipleApks=' + cdvBuildMultipleApks)
    println('cdvReleaseSigningPropertiesFile=' + cdvReleaseSigningPropertiesFile)
    println('cdvDebugSigningPropertiesFile=' + cdvDebugSigningPropertiesFile)
    println('cdvBuildArch=' + cdvBuildArch)
    println('computedVersionCode=' + android.defaultConfig.versionCode)
    android.productFlavors.each { flavor ->
        println('computed' + flavor.name.capitalize() + 'VersionCode=' + flavor.versionCode)
    }
}

android {
    sourceSets {
        main {
            manifest.srcFile 'AndroidManifest.xml'
            java.srcDirs = ['src']
            resources.srcDirs = ['src']
            aidl.srcDirs = ['src']
            renderscript.srcDirs = ['src']
            res.srcDirs = ['res']
            assets.srcDirs = ['assets']
            jniLibs.srcDirs = ['libs']
        }
    }

    defaultConfig {
        versionCode cdvVersionCode ?: new BigInteger("" + privateHelpers.extractIntFromManifest("versionCode"))
        applicationId privateHelpers.extractStringFromManifest("package")

        minSdkVersion 21
        targetSdkVersion 26
        multiDexEnabled true

        if (cdvMinSdkVersion != null) {
            minSdkVersion cdvMinSdkVersion
        }
    }

    lintOptions {
      abortOnError false;
    }

    compileSdkVersion cdvCompileSdkVersion
    buildToolsVersion cdvBuildToolsVersion

    if (Boolean.valueOf(cdvBuildMultipleApks)) {
        productFlavors {
            armv7 {
                versionCode defaultConfig.versionCode*10 + 2
                ndk {
                    abiFilters "armeabi-v7a", ""
                }
            }
            x86 {
                versionCode defaultConfig.versionCode*10 + 4
                ndk {
                    abiFilters "x86", ""
                }
            }
            all {
                ndk {
                    abiFilters "all", ""
                }
            }
        }
    }
    /*

    ELSE NOTHING! DON'T MESS WITH THE VERSION CODE IF YOU DON'T HAVE TO!

    else if (!cdvVersionCode) {
      def minSdkVersion = cdvMinSdkVersion ?: privateHelpers.extractIntFromManifest("minSdkVersion")
      // Vary versionCode by the two most common API levels:
      // 14 is ICS, which is the lowest API level for many apps.
      // 20 is Lollipop, which is the lowest API level for the updatable system webview.
      if (minSdkVersion >= 20) {
        defaultConfig.versionCode += 9
      } else if (minSdkVersion >= 14) {
        defaultConfig.versionCode += 8
      }
    }
    */

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_6
        targetCompatibility JavaVersion.VERSION_1_6
    }

    if (cdvReleaseSigningPropertiesFile) {
        signingConfigs {
            release {
                // These must be set or Gradle will complain (even if they are overridden).
                keyAlias = ""
                keyPassword = "__unset" // And these must be set to non-empty in order to have the signing step added to the task graph.
                storeFile = null
                storePassword = "__unset"
            }
        }
        buildTypes {
            release {
                signingConfig signingConfigs.release
            }
        }
        addSigningProps(cdvReleaseSigningPropertiesFile, signingConfigs.release)
    }
    if (cdvDebugSigningPropertiesFile) {
        addSigningProps(cdvDebugSigningPropertiesFile, signingConfigs.debug)
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: '*.jar')
    // SUB-PROJECT DEPENDENCIES START
    debugCompile(project(path: "CordovaLib", configuration: "debug"))
    releaseCompile(project(path: "CordovaLib", configuration: "release"))
    compile "net.gotev:uploadservice:3.2.3"
    compile "net.gotev:uploadservice-okhttp:3.2.3"
    compile "com.sromku:simple-storage:1.2.0"
    compile "com.android.support:support-v4:24.1.1+"
    // SUB-PROJECT DEPENDENCIES END
}

def promptForReleaseKeyPassword() {
    if (!cdvReleaseSigningPropertiesFile) {
        return;
    }
    if ('__unset'.equals(android.signingConfigs.release.storePassword)) {
        android.signingConfigs.release.storePassword = privateHelpers.promptForPassword('Enter key store password: ')
    }
    if ('__unset'.equals(android.signingConfigs.release.keyPassword)) {
        android.signingConfigs.release.keyPassword = privateHelpers.promptForPassword('Enter key password: ');
    }
}

gradle.taskGraph.whenReady { taskGraph ->
    taskGraph.getAllTasks().each() { task ->
        if (task.name == 'validateReleaseSigning' || task.name == 'validateSigningRelease') {
            promptForReleaseKeyPassword()
        }
    }
}

def addSigningProps(propsFilePath, signingConfig) {
    def propsFile = file(propsFilePath)
    def props = new Properties()
    propsFile.withReader { reader ->
        props.load(reader)
    }

    def storeFile = new File(props.get('key.store') ?: privateHelpers.ensureValueExists(propsFilePath, props, 'storeFile'))
    if (!storeFile.isAbsolute()) {
        storeFile = RelativePath.parse(true, storeFile.toString()).getFile(propsFile.getParentFile())
    }
    if (!storeFile.exists()) {
        throw new FileNotFoundException('Keystore file does not exist: ' + storeFile.getAbsolutePath())
    }
    signingConfig.keyAlias = props.get('key.alias') ?: privateHelpers.ensureValueExists(propsFilePath, props, 'keyAlias')
    signingConfig.keyPassword = props.get('keyPassword', props.get('key.alias.password', signingConfig.keyPassword))
    signingConfig.storeFile = storeFile
    signingConfig.storePassword = props.get('storePassword', props.get('key.store.password', signingConfig.storePassword))
    def storeType = props.get('storeType', props.get('key.store.type', ''))
    if (!storeType) {
        def filename = storeFile.getName().toLowerCase();
        if (filename.endsWith('.p12') || filename.endsWith('.pfx')) {
            storeType = 'pkcs12'
        } else {
            storeType = signingConfig.storeType // "jks"
        }
    }
    signingConfig.storeType = storeType
}

for (def func : cdvPluginPostBuildExtras) {
    func()
}

// This can be defined within build-extras.gradle as:
//     ext.postBuildExtras = { ... code here ... }
if (hasProperty('postBuildExtras')) {
    postBuildExtras()
}

我在 Windows 10 Pro 上使用以下内容:-

javac -version
javac 1.8.0_221

javaw -version
java version "1.8.0_221"
Java(TM) SE Runtime Environment (build 1.8.0_221-b11)
Java HotSpot(TM) 64-Bit Server VM (build 25.221-b11, mixed mode)
NodeJS : v10.13.0
npm    : 6.7.0

Gradle 是截至 2019 年 2 月 9 日的最新版本,即 gradle-5.6.1

【问题讨论】:

  • 您的意思是“cordova build”在从终端调用时成功,但从自定义脚本调用时失败?
  • @GuillaumeAdam 当我运行cordova build 时,它也会出现同样的问题:(
  • 尝试删除 .gradle 文件夹(或简单地将其重命名为 .gradle.old)并再次运行该命令。这个技巧有时真的很管用。
  • 这可能是java版本。您使用的是 1.6 和 1.7。将其更新到 1.8,清理项目并重建它。
  • 我以前见过这个(很多次)。将所有内容更新为最新版本。如果您的明智将是您的第一个任务,而无需询问我们。

标签: android cordova android-studio gradle build.gradle


【解决方案1】:

上面写着:

ParseException: bad class file magic (cafebabe) or version (0034.0000)

0x0034 是版本 52 字节代码,这意味着某些类是用 JDK 8 编译的,dex 的那个版本无法理解。它甚至明确要求源/目标兼容模式:

Dex: Error converting bytecode to dex:
Cause: Dex cannot parse version 52 byte code.

This is caused by library dependencies that have been compiled using Java 8 or above.

If you are using the 'java' gradle plugin in a library submodule add
targetCompatibility = '1.7'
sourceCompatibility = '1.7'
to that submodule's build.gradle file.

所以有两种选择:

a) 遵循建议并编辑 compileOptions(这不仅适用于 java 插件):

android {
    compileOptions {
        // sourceCompatibility JavaVersion.VERSION_1_6
        // targetCompatibility JavaVersion.VERSION_1_6
        sourceCompatibility JavaVersion.VERSION_1_7
        targetCompatibility JavaVersion.VERSION_1_7
    }
}

b) 使用 JDK 8 构建。

您实际上是在使用相当旧的版本进行构建:

dependencies {
    classpath "com.android.tools.build:gradle:2.2.3"
}

task wrapper(type: Wrapper) {
    gradleVersion = "2.14.1"
}

目前的版本是:

dependencies {
    classpath "com.android.tools.build:gradle:3.5.0"
}

task wrapper(type: Wrapper) {
    gradleVersion = "5.4.1"
}

当我阅读版本 2.2.3 时,我会假设 Android Studio 的版本同样旧。更新到 Android Studio 3.5.0 并安装嵌入式 JRE 8。那个 Android Studio 可能仍然有一个嵌入式 JRE 7(不管路径上的 JDK 声称是什么,因为全局 JDK 和嵌入式 JRE 是两个不同的安装)。 Gradle 也是如此,因为它可能使用版本 2.14.1 的本地包装器,而不是版本 5.6.1 的全局安装。可以通过 org.gradle.java.home 告诉 Gradle 使用特定的 JDK,但 IDE 通常可能太旧了。您至少需要 Android Studio 3.0.0 才能获得 Java 8 支持。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-04
    • 2016-08-29
    • 1970-01-01
    • 2016-09-11
    • 2018-06-21
    相关资源
    最近更新 更多