2013-07-04 48 views
25

我有我的項目的兩個版本:如何在android studio中用gradle替換buildvariant的字符串?

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

現在我想建立flavor1和flavor2的buildvariant。 buildvariant的唯一區別是另一個包名。

我的項目使用MapFragments並且只有一個Manifest - 因此我將MAPS_RECEIVE的權限名稱放在我的字符串資源文件中。

問題是:如何替換buildvariant的字符串資源?

我嘗試以下方法(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']) 
    } 
} 

但是使用這個我得到這個錯誤:

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

我必須定義過濾器方法的爲己任?

EDIT [2013_07_09]:將src/flavor1/RES

字符串:

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

代碼中的build.gradle替換的字符串:

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

嘿,我嘗試另一種解決方案。但它不起作用。雖然構建是成功的,但字符串不會被替換。任何人都可以給我一個提示我的複製任務有什麼問題嗎? – owe

+2

新Manifest Merger的情況如何?這可以爲你工作嗎? http://tools.android.com/tech-docs/new-build-system/user-guide/manifest-merger – OriolJ

回答

35

我解決了問題在我自己的,所以這裏是解決方案「一步一步」 - 也許它會幫助一些其他新手gradle :)

  • 複製任務一般:

    copy{ 
        from("pathToMyFolder"){ 
         include "my.file" 
        } 
        // you have to use a new path for youre modified file 
        into("pathToFolderWhereToCopyMyNewFile") 
    } 
    
  • 一般更換行:

    copy { 
        ... 
        filter{ 
         String line -> line.replaceAll("<complete line of regular expression>", 
                 "<complete line of modified expression>") 
        } 
    } 
    
  • 我認爲最大的問題是要找到正確的路徑,因爲我不得不作出這動態地(this link was very helpful for me)。我通過替換清單中的特殊行而不是字符串文件來解決我的問題。

  • 下面的示例演示瞭如何更換「元數據」 - 標記的清單以使用您選擇谷歌地圖的API密鑰(對我來說有一些使用不同的密鑰不同的口味):

    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

我幾乎完全使用你想要的方法。 replaceInManfest也是通用的,也可以用於其他佔位符。 getGMapsKey()方法只是根據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') 
} 

我有它在gist太多,如果你想看看它以後的發展。

我發現這是一個比其他人更優雅和更一般化的方法(雖然令牌更換隻是工作會更好)。

0

在當前的Android Gradle DSL中,ApplicationVariant類已更改,並且必須重寫Saad的方法,例如,如下:

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

新的DSL還提供了一個更清晰的方法來直接獲取清單文件。

2

答案相當過時,現在有更好的方法來存檔它。你可以在你的build.gradle使用命令:

manifestPlaceholders = [ 
      myPlaceholder: "placeholder", 
    ] 

,並在您的清單:

android:someManifestAttribute="${myPlaceholder}" 

的更多信息可以在這裏找到: https://developer.android.com/studio/build/manifest-merge.html