Cómo generar múltiples apk (utilizando gradle, libGDX)
Lo intento
Quiero generar pocos APK (x86, armeabi-v7a). Para reducir el tamaño de APK en Google Play
- Box2d Comprobar Collision / Overlaping en cualquier momento
- Android NullPointerException en $ Proxy0.equals
- ¿Cómo hacer que la clase AndroidApplication de LibGDX admita Fragmentos de Android?
- Tween.registerAccessor NoClassDefFoundError
- Fondo animado con Libgdx
Pero no funciona. Android studia dice import com.android.build.OutputFile – No se puede resolver el símbolo 'OutputFile'. Y en la consola que veo. Intento buscar en google otras instrucciones y traté de hacer algo al respecto yo mismo, pero no soy bueno en gradle
Error:Cannot invoke method multiply() on null object
Mi gradle-archivo es
// 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 { }
- Libgdx SpriteBatch render a la textura
- ¿Cómo obtener una "pantalla de carga" con libgdx?
- Libgdx y Leadbolt
- Proyecto LibGDX escrito en Scala, en Android, con IntelliJ
- El registro de LibGDX no aparece en logcat
- LibGDX 0.9.9 - Aplicar cubemap en el entorno
- LibGDX - Shader trabajando en el escritorio pero no en Android
- Cómo dibujar la clase Button en libgdx
TL, DR:
Acabo de tener el mismo problema, y para mí la respuesta es afortunadamente simple. En lugar de utilizar OutputFilter.ABI
en la llamada a output.getFilter
, utilice 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 } }
Lo que se rompió
Esto es esencialmente lo que tienes arriba, pero refactorizado en unas pocas líneas más. La diferencia clave está en la llamada a output.getFilter
. Los ejemplos en los documentos dicen utilizar OutputFile.ABI
– como de versiones de herramientas más recientes (no estoy seguro de cuál), esto es incorrecto. El argumento correcto es OutputFile.FilterType.ABI
.
El método getFilter
se define en la clase ApkVariantOutputImpl
. Como se puede ver en el código fuente de ApkVariantOutputImpl , se necesita un único argumento de tipo OutputFile.FilterType
; OutputFile.ABI
es una String
, y Groovy (a pesar de todos los otros bits de magia que hace) evidentemente no convertir la cadena constante en el enum adecuado, resultando en un valor nulo.
Renuncia
Sólo FYI, tuve que cavar bastante extensivamente a través de diferentes versiones de las herramientas de construcción para encontrar el enlace de origen – parece que este ha sido un área de inestabilidad API. Esto funciona para mí, con las siguientes configuraciones:
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' } } }
Si desea construir un APK universal (con todas las diferentes ABI incluidas), tendrá que tener en cuenta el hecho de que la variante universal no tiene filtro ABI, es decir, comprobar el multiplicador de nulo y reemplazarlo por algo significativo como cero.
Parece que falla en un intento de obtener ABI para APK universal ya que no hay filtro para ello en su mapa de versionCodes
. Debe comprobar el resultado de output.getFilter(OutputFile.ABI)
antes de aplicar la multiplicación de alguna manera como por ejemplo:
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 } }
- Comunicación distinta de Android Library Project a App utilizando
- "ResultIndex es -1, el polígono debe ser inválido!" Adter addView ()