简体   繁体   English

如何生成多个apk(使用gradle,libGDX)

[英]how generate multiple apk (using gradle , libGDX)

I try this 我试试这个

I want generate few APK (x86, armeabi-v7a). 我想生成几个APK(x86,armeabi-v7a)。 In order to reduce the size of APK in Google Play 为了减少Google Play中APK的大小

But its doesnt work. 但它不起作用。 Android studia says import com.android.build.OutputFile - Cannot resolve symbol 'OutputFile'. Android studia说导入com.android.build.OutputFile - 无法解析符号'OutputFile'。 And in console i see. 在控制台我看到了。 I try search in google other instructions and tried to do something about it myself, but I'm not good at gradle 我尝试在google其他说明中搜索并尝试自己做一些事情,但我不擅长gradle

Error:Cannot invoke method multiply() on null object

my gradle-file is 我的gradle文件是

// map for the version code

ext.versionCodes = ['armeabi-v7a':1, 'armeabi':2, 'x86':3]

import com.android.build.OutputFile

android.applicationVariants.all { variant ->
    // assign different version code for each output
    variant.outputs.each { output ->
        output.versionCodeOverride =
                project.ext.versionCodes.get(output.getFilter(OutputFile.ABI)) * 1000000 + android.defaultConfig.versionCode
    }
}

android {
    buildToolsVersion "20.0.0"
    compileSdkVersion 20
    sourceSets {
        main {
            manifest.srcFile 'AndroidManifest.xml'
            java.srcDirs = ['src']
            aidl.srcDirs = ['src']
            renderscript.srcDirs = ['src']
            res.srcDirs = ['res']
            assets.srcDirs = ['assets']
        }


        instrumentTest.setRoot('tests')
    }
    defaultConfig {
        versionCode 11
        versionName '1.3'
    }
    productFlavors {
    }

    splits {
        abi {
            enable true
            reset()
            include 'x86', 'armeabi-v7a', 'armeabi'
            universalApk true
        }
    }





}




// needed to add JNI shared libraries to APK when compiling on CLI
tasks.withType(com.android.build.gradle.tasks.PackageApplication) { pkgTask ->
    pkgTask.jniFolders = new HashSet<File>()
    pkgTask.jniFolders.add(new File(projectDir, 'libs'))
}
// called every time gradle gets executed, takes the native dependencies of
// the natives configuration, and extracts them to the proper libs/ folders
// so they get packed with the APK.
task copyAndroidNatives() {
    file("libs/armeabi/").mkdirs();
    file("libs/armeabi-v7a/").mkdirs();
    file("libs/x86/").mkdirs();

    configurations.natives.files.each { jar ->
        def outputDir = null
        if (jar.name.endsWith("natives-armeabi-v7a.jar")) outputDir = file("libs/armeabi-v7a")
        if (jar.name.endsWith("natives-armeabi.jar")) outputDir = file("libs/armeabi")
        if (jar.name.endsWith("natives-x86.jar")) outputDir = file("libs/x86")
        if (outputDir != null) {
            copy {
                from zipTree(jar)
                into outputDir
                include "*.so"
            }
        }
    }
}
task run(type: Exec) {
    def path
    def localProperties = project.file("../local.properties")
    if (localProperties.exists()) {
        Properties properties = new Properties()
        localProperties.withInputStream { instr ->
            properties.load(instr)
        }
        def sdkDir = properties.getProperty('sdk.dir')
        if (sdkDir) {
            path = sdkDir
        } else {
            path = "$System.env.ANDROID_HOME"
        }
    } else {
        path = "$System.env.ANDROID_HOME"
    }

    def adb = path + "/platform-tools/adb"
    commandLine "$adb", 'shell', 'am', 'start', '-n', 'com.mygdx.crazyball.android/com.mygdx.crazyball.android.AndroidLauncher'
}
// sets up the Android Eclipse project, using the old Ant based build.
eclipse {
    // need to specify Java source sets explicitely, SpringSource Gradle Eclipse plugin
    // ignores any nodes added in classpath.file.withXml
    sourceSets {
        main {
            java.srcDirs "src", 'gen'
        }
    }

    jdt {
        sourceCompatibility = 1.6
        targetCompatibility = 1.6
    }

    classpath {
        plusConfigurations += [project.configurations.compile]
        containers 'com.android.ide.eclipse.adt.ANDROID_FRAMEWORK', 'com.android.ide.eclipse.adt.LIBRARIES'
    }

    project {
        name = appName + "-android"
        natures 'com.android.ide.eclipse.adt.AndroidNature'
        buildCommands.clear();
        buildCommand "com.android.ide.eclipse.adt.ResourceManagerBuilder"
        buildCommand "com.android.ide.eclipse.adt.PreCompilerBuilder"
        buildCommand "org.eclipse.jdt.core.javabuilder"
        buildCommand "com.android.ide.eclipse.adt.ApkBuilder"
    }
}
// sets up the Android Idea project, using the old Ant based build.
idea {
    module {
        sourceDirs += file("src");
        scopes = [COMPILE: [plus: [project.configurations.compile]]]

        iml {
            withXml {
                def node = it.asNode()
                def builder = NodeBuilder.newInstance();
                builder.current = node;
                builder.component(name: "FacetManager") {
                    facet(type: "android", name: "Android") {
                        configuration {
                            option(name: "UPDATE_PROPERTY_FILES", value: "true")
                        }
                    }
                }
            }
        }
    }
}
dependencies {
}

Looks like it fails on a try to get ABI for universal APK as there is no filter for it in your versionCodes map. 看起来它试图获得通用 APK的ABI失败,因为你的versionCodes地图中没有过滤器。 You should check the result of output.getFilter(OutputFile.ABI) before applying multiplication in some manner like for example: 你应该以某种方式应用乘法之前检查output.getFilter(OutputFile.ABI)的结果,例如:

android.applicationVariants.all { variant ->
    // assign different version code for each output
    variant.outputs.each { output ->
        def abiFilter = output.getFilter(OutputFile.ABI)
        def abiMultiplier = 0

        if (abiFilter != null) {
            abiMultiplier = project.ext.versionCodes.get(abiFilter)
        }

        output.versionCodeOverride =
            abiMultiplier * 1000000 + android.defaultConfig.versionCode
    }
}

TL;DR: TL; DR:

I just had the same problem, and for me the answer is thankfully simple. 我只是遇到了同样的问题,对我而言,答案很简单。 Instead of using OutputFilter.ABI in the call to output.getFilter , use OutputFilter.FilterType.ABI : 而不是在对output.getFilter的调用中使用OutputFilter.ABI ,而是使用OutputFilter.FilterType.ABI

android.applicationVariants.all { variant ->
  variant.outputs.each { output ->
    def defaultCode = android.defaultConfig.versionCode
    def filter = output.getFilter(OutputFile.FilterType.ABI)
    def abiMultiplier = project.ext.versionCodes.get(filter)

    output.versionCodeOverride = abiMultiplier * 1000000 + defaultCode
  }
}

What broke 什么破了

This is essentially what you have above, but refactored into a few more lines. 这基本上就是你所拥有的,但重构了几行。 The key difference is in the call to output.getFilter . 关键区别在于对output.getFilter的调用。 The examples in the docs say to use OutputFile.ABI - as of more recent tools versions (I'm not sure which), this is wrong. 文档中的示例说使用OutputFile.ABI - 作为更新的工具版本(我不确定哪个),这是错误的。 The correct argument is OutputFile.FilterType.ABI . 正确的参数是OutputFile.FilterType.ABI

The getFilter method is defined on the class ApkVariantOutputImpl . getFilter方法在类ApkVariantOutputImpl上定义。 As you can see in the source code for ApkVariantOutputImpl , it takes a single argument of type OutputFile.FilterType ; 正如您在ApkVariantOutputImpl的源代码中所看到的 ,它接受一个类型为OutputFile.FilterType参数; OutputFile.ABI is a String , and Groovy (despite all the other bits of magic it does) evidently does not convert the constant string into the proper enum, resulting in a null value. OutputFile.ABI是一个String ,而Groovy(尽管它所做的所有其他魔法)显然不会将常量字符串转换为正确的枚举,从而产生一个空值。

Disclaimer 放弃

Just FYI, I had to dig pretty extensively through different versions of the build tools to find the source link - it seems that this has been an area of API instability. 仅供参考,我不得不通过不同版本的构建工具进行广泛挖掘以找到源链接 - 这似乎是API不稳定的一个方面。 This works for me, with the following settings: 这适用于我,具有以下设置:

buildscript {
  dependencies {
    'com.android.tools.build:gradle:1.2.2'
  }
}

android {
  compileSdkVersion 22
  buildToolsVersion "22.0.1"

  // lots of stuff

  splits {
    abi {
      enable true
      reset()
      include 'x86', 'armeabi-v7a', 'mips'
    }
  }
}

If you want to build a universal APK (with all the different ABIs included), you'll need to account for the fact that the universal variant has no ABI filter, ie check the multiplier for null and replace it with something meaningful like zero. 如果你想构建一个通用的APK(包含所有不同的ABI),你需要考虑通用变量没有ABI过滤器这一事实,即检查乘数为null并用零有意义的东西替换它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM