2013-07-04 3 views
25

ho due sapori del mio progetto:Come sostituire una stringa per un buildvariant con gradle in Android Studio?

flavor1 -> packagename: com.example.flavor1 
flavor2 -> packagename: com.example.flavor2 

ora voglio costruire un buildvariant di flavor1 e flavor2. L'unica differenza di buildvariant è un altro nome pacchetto.

Il mio progetto utilizza MapFragments e ha un solo manifest - quindi inserisco il nome di autorizzazione di MAPS_RECEIVE nei miei file di risorse stringa dei rispettivi sapori.

La domanda è: come posso sostituire una risorsa stringa di un buildvariant?

ho provato l'approccio seguente (described in this post):

buildTypes{ 
    flavor1Rev{ 
     packageName 'com.example.rev.flavor1' 
     filter(org.apache.tools.ant.filters.ReplaceTokens, tokens: ['package_permission' : 'com.example.rev.flavor1.permission.MAPS_RECEIVE']) 
    } 
} 

Ma usando questo ho ottenuto questo errore:

Could not find method filter() for arguments [{tokens={package_permission=com.example.rev.flavor1.permission.MAPS_RECEIVE}}, BuildTypeDsl_D ecorated{name=ReplaceTokens, debuggable=false, jniDebugBuild=false, renderscript DebugBuild=false, renderscriptOptimLevel=3, packageNameSuffix=null, versionNameS uffix=null, runProguard=false, zipAlign=true, signingConfig=null}] on BuildTypeD sl_Decorated{name=buderusFinal, debuggable=false, jniDebugBuild=false, renderscr iptDebugBuild=false, renderscriptOptimLevel=3, packageNameSuffix=null, versionNa meSuffix=null, runProguard=false, zipAlign=true, signingConfig=null}.

Devo definire un proprio compito per il metodo del filtro?

EDIT [2013_07_09]:

stringa in src/flavor1/res:

<string name="package_permission">package_permission</string> 

Codice in build.gradle per sostituire la stringa:

buildTypes{ 
    flavor1Rev{ 
     copy{ 
      from('src/res/'){ 
       include '**/*.xml' 
       filter{String line -> line.replaceAll(package_permission, 'com.example.rev.flavor1.permission.MAPS_RECEIVE')} 
      } 
      into '$buildDir/res' 
     } 
    } 
} 
+0

Ehi, ho cercato un'altra soluzione. Ma non funziona. Sebbene la compilazione abbia successo, ma la stringa non viene sostituita. Qualcuno può darmi un suggerimento cosa c'è di sbagliato con il mio compito di copia? – owe

+2

E la nuova Fusione Manifest? può funzionare per te? http://tools.android.com/tech-docs/new-build-system/user-guide/manifest-merger – OriolJ

risposta

35

Ho risolto il problema da solo, ecco la soluzione "passo dopo passo" - forse aiuterà altri neofiti a gradle :)

  • Copy Task in generale:

    copy{ 
        from("pathToMyFolder"){ 
         include "my.file" 
        } 
        // you have to use a new path for youre modified file 
        into("pathToFolderWhereToCopyMyNewFile") 
    } 
    
  • Sostituire una linea in generale:

    copy { 
        ... 
        filter{ 
         String line -> line.replaceAll("<complete line of regular expression>", 
                 "<complete line of modified expression>") 
        } 
    } 
    
  • Penso che il problema più grande è stato quello di ottenere il giusto cammino, perché ho dovuto fare questo dinamicamente (this link was very helpful for me). Ho risolto il mio problema sostituendo le righe speciali nel file manifest e non nel file String.

  • L'esempio seguente mostra come sostituire il -tag "meta-dati" nel manifesto di utilizzare sei google-maps-api-chiave (nel mio caso ci sono diversi sapori che utilizzano chiavi diverse):

    android.applicationVariants.each{ variant -> 
        variant.processManifest.doLast{ 
         copy{ 
          from("${buildDir}/manifests"){ 
           include "${variant.dirName}/AndroidManifest.xml" 
          } 
          into("${buildDir}/manifests/$variant.name") 
    
          // define a variable for your key: 
          def gmaps_key = "<your-key>" 
    
          filter{ 
           String line -> line.replaceAll("<meta-data android:name=\"com.google.android.maps.v2.API_KEY\" android:value=\"\"/>", 
                   "<meta-data android:name=\"com.google.android.maps.v2.API_KEY\" android:value=\"" + gmaps_key + "\"/>") 
          } 
    
          // set the path to the modified Manifest: 
          variant.processResources.manifestFile = file("${buildDir}/manifests/${variant.name}/${variant.dirName}/AndroidManifest.xml") 
         }  
        } 
    } 
    
11

Io uso quasi esattamente l'approccio che volevi. Lo replaceInManfest è anche generico e può essere utilizzato anche per altri segnaposto. Il metodo getGMapsKey() restituisce semplicemente la chiave appropriata in base a buildType.

applicationVariants.all { variant -> 
    def flavor = variant.productFlavors.get(0) 
    def buildType = variant.buildType 
    variant.processManifest.doLast { 
     replaceInManifest(variant, 
      'GMAPS_KEY', 
      getGMapsKey(buildType)) 
    } 
} 

def replaceInManifest(variant, fromString, toString) { 
    def flavor = variant.productFlavors.get(0) 
    def buildtype = variant.buildType 
    def manifestFile = "$buildDir/manifests/${flavor.name}/${buildtype.name}/AndroidManifest.xml" 
    def updatedContent = new File(manifestFile).getText('UTF-8').replaceAll(fromString, toString) 
    new File(manifestFile).write(updatedContent, 'UTF-8') 
} 

ce l'ho su un gist troppo se si vuole vedere se si evolve in seguito.

Ho trovato questo un approccio più elegante e generalizzabile rispetto agli altri (anche se la sostituzione del token funzionante sarebbe stata più bella).

0

Nell'attuale Gradle DSL Android, la classe ApplicationVariant è stata modificata e l'approccio di Saad deve essere riscritto, ad es. come segue:

Il nuovo DSL offre anche un approccio più pulito per accedere direttamente al file manifest.

2

Le risposte sono abbastanza obsolete, ora ci sono modi migliori per archiviarlo. È possibile utilizzare il comando nel build.gradle:

manifestPlaceholders = [ 
      myPlaceholder: "placeholder", 
    ] 

e nel vostro manifesto:

più
android:someManifestAttribute="${myPlaceholder}" 

informazioni possono essere trovate qui: https://developer.android.com/studio/build/manifest-merge.html

Problemi correlati