2015-03-18 15 views
5

I try this, wie mehrere apk generieren (mit gradle, Libgdx)

möchte ich einige APK (x86, armeabi-V7A) erzeugen. Um

Aber seine nicht funktioniert spielt die Größe der APK in Google zu reduzieren. Android studia sagt import com.android.build.OutputFile - Kann das Symbol 'OutputFile' nicht auflösen. Und in der Konsole sehe ich. Ich versuche, in google anderen Anweisungen suchen und versuchte mich, etwas dagegen zu tun, aber ich bin nicht gut in gradle

Error:Cannot invoke method multiply() on null object

meine gradle-Datei ist

// 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 { 
} 

Antwort

2

TL; DR:

Ich hatte gerade das gleiche Problem, und für mich ist die Antwort glücklicherweise einfach. Stattdessen OutputFilter.ABI-output.getFilter im Aufruf der Verwendung Verwendung 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 
    } 
} 

Was brach

Dies ist im Wesentlichen, was Sie oben, aber in ein paar Zeilen Refactoring. Der Hauptunterschied ist in dem Anruf output.getFilter. Die Beispiele in den Dokumenten sagen OutputFile.ABI - wie von neueren Tools Versionen (ich bin mir nicht sicher, welche), das ist falsch. Das korrekte Argument ist OutputFile.FilterType.ABI.

Die Methode getFilter ist in der Klasse ApkVariantOutputImpl definiert. Wie Sie in the source code for ApkVariantOutputImpl sehen können, benötigt es ein einzelnes Argument vom Typ OutputFile.FilterType; OutputFile.ABI ist ein String, und Groovy (trotz all der anderen Bits der Magie, die es tut) wandelt die konstante Zeichenkette offensichtlich nicht in die richtige enum um, was zu einem Nullwert führt.

Haftungsausschluss

Gerade FYI, ich hatte ziemlich viel durch verschiedene Versionen der Build-Tool zu graben, um den Quell-Link zu finden - es scheint, dass dies ein Bereich von API Instabilität ist. Dies funktioniert für mich, mit den folgenden Einstellungen:

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' 
    } 
    } 
} 

Wenn Sie einen Universal-APK bauen wollen (mit all den verschiedenen ABIs enthalten), müssen Sie für die Tatsache berücksichtigen, dass die Universal-Variante kein ABI hat filter, dh überprüfe den Multiplikator auf Null und ersetze ihn durch etwas Bedeutungsvolles wie Null.

2

Sieht aus wie es auf einem Versuch fehlschlägt ABI für universal APK zu bekommen, da es keine Filter für sie in Ihrer versionCodes Karte ist. Sie sollten das Ergebnis von output.getFilter(OutputFile.ABI) überprüfen, bevor Sie die Multiplikation in irgendeiner Weise anwenden, wie zum Beispiel:

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 
    } 
} 
Verwandte Themen