Come sostituire una stringa per un buildvariant con gradle in android studio?

Ho due sapori del mio progetto:

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

Ora voglio costruire un buildvariant di flavor1 e flavor2.
L’unica differenza del buildvariant è un altro nomepacchetto.

Mio progetto utilizza MapFragments e ha un solo Manifesto – così ho messo il nome di autorizzazione di MAPS_RECEIVE nella mia stringa file di risorse dei rispettivi sapori.

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

Ho provato il seguente approccio (descritto in questo 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 con questa ho ottenuto questo errore:

Non riusciva a trovare il metodo filter() per argomenti
[{token={package_permission=com.esempio.rev.flavor1.il permesso.MAPS_RECEIVE}},
BuildTypeDsl_D ecorated{nome=ReplaceTokens, debuggable=false,
jniDebugBuild=false, renderscript DebugBuild=false,
renderscriptOptimLevel=3, packageNameSuffix=null, versionNameS
uffix=null, runProguard=false, zipAlign=true, signingConfig=null}] su
BuildTypeD sl_Decorated{nome=buderusFinal, debuggable=false,
jniDebugBuild=false, renderscr iptDebugBuild=false,
renderscriptOptimLevel=3, packageNameSuffix=null, versionNa
meSuffix=null, runProguard=false, zipAlign=true, signingConfig=null}.

Devo definire una propria attività per il metodo a filtro?

MODIFICA [2013_07_09]:

Stringa 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'
        }
    }
} 
  • Hey, ho provato un’altra soluzione. Ma non funziona. Anche se la build è successo, ma la stringa non viene sostituito. Qualcuno mi può dare un suggerimento di ciò che è sbagliato con la mia copia di attività?
  • il nuovo Manifesto di Fusione? questo può funzionare per voi? tools.android.com/tech-docs/new-build-system/user-guide/…
InformationsquelleAutor owe | 2013-07-04



4 Replies
  1. 37

    Ho risolto il problema, e così ecco la soluzione “step by step” – forse aiutare alcuni altri neofiti di gradle 🙂

    • Attività di copia in Generale:

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

      copy {
         ...
         filter{
             String line -> line.replaceAll("<complete line of regular expression>",
                                            "<complete line of modified expression>")
         }
      }
    • Penso che il problema più grande era quello di ottenere il giusto cammino, perché ho dovuto fare questo in modo dinamico (questo link è stato molto utile per me). Ho risolto il problema sostituendo le linee speciali nel manifesto e non nella Stringa di file.

    • L’esempio seguente mostra come sostituire il “meta-dati”-tag nel manifesto di utilizzare youre google-maps-api-key (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")
              }    
         }
      }
  2. 11

    Io uso quasi esattamente l’approccio che si voleva. Il replaceInManfest è generica e può essere utilizzato per altri segnaposto così. Il getGMapsKey() metodo restituisce il tasto appropriato basato sul 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')
    }

    Ho su un gist troppo se si vuole vedere se si evolve in seguito.

    Ho trovato questo per essere più elegante e generalizzabile approccio rispetto agli altri (anche se la sostituzione di token solo lavorando sarebbe stato meglio).

  3. 0

    Nell’attuale Android Gradle DSL, il ApplicationVariant classe ha cambiato e Saad l’approccio deve essere riscritto ad esempio, come segue:

    applicationVariants.all { variant ->
        variant.outputs.each { output ->
            output.processManifest.doLast {
                replaceInManifest(output,
                        'GMAPS_KEY',
                        getGmapsKey(buildType))
    
                }
            }
        }
    
    def replaceInManifest(output, fromString, toString) {
        def updatedContent = output.processManifest.manifestOutputFile.getText('UTF-8')
            .replaceAll(fromString, toString)
        output.processManifest.manifestOutputFile.write(updatedContent, 'UTF-8')
    }

    Il nuovo DSL offre anche un approccio più “pulito” per raggiungere direttamente il file manifest.

Lascia un commento