如何在android studio中用gradle替换buildvariant的字符串?

Posted

技术标签:

【中文标题】如何在android studio中用gradle替换buildvariant的字符串?【英文标题】:How to replace a string for a buildvariant with gradle in android studio? 【发布时间】:2013-07-02 04:01:48 【问题描述】:

我的项目有两种风格:

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

但是使用这个我得到了这个错误:

找不到参数的方法 filter() [tokens=package_permission=com.example.rev.flavor1.permission.MAPS_RECEIVE, BuildTypeDsl_D ecoratedname=ReplaceTokens, debuggable=false, jniDebugBuild=false,renderscript DebugBuild=false, renderscriptOptimLevel=3, packageNameSuffix=null, versionNameS 后缀=null,runProguard=false,zipAlign=true,signingConfig=null] on BuildTypeD sl_Decoratedname=buderusFinal, debuggable=false, jniDebugBuild=false,renderscr iptDebugBuild=false, renderscriptOptimLevel=3, packageNameSuffix=null, versionNa meSuffix=null,runProguard=false,zipAlign=true,signingConfig=null。

我必须为过滤方法定义一个自己的任务吗?

编辑 [2013_07_09]:

src/flavor1/res 中的字符串:

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

build.gradle 中替换字符串的代码:

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

【问题讨论】:

嘿,我尝试了另一种解决方案。但它不起作用。虽然构建成功,但字符串没有被替换。谁能给我提示一下我的复制任务出了什么问题? 新的 Manifest 合并怎么样?这对你有用吗? tools.android.com/tech-docs/new-build-system/user-guide/… 【参考方案1】:

我自己解决了这个问题,所以这里是“一步一步”的解决方案——也许它会帮助其他一些新手毕业:)

一般复制任务:

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)。我通过替换清单中的特殊行而不是字符串文件中的特殊行来解决我的问题。

以下示例展示了如何替换清单中的“元数据”标签以使用您的 google-maps-api-key(在我的例子中,有不同的风格使用不同的键):

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】:

我几乎完全按照您想要的方法使用。 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 上。

我发现这是一种比其他方法更优雅和更通用的方法(尽管令牌替换会更好)。

【讨论】:

【参考方案3】:

答案已经过时了,现在有更好的方法来存档它。您可以在 build.gradle 中使用该命令:

manifestPlaceholders = [
            myPlaceholder: "placeholder",
    ]

在你的清单中:

android:someManifestAttribute="$myPlaceholder"

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

【讨论】:

【参考方案4】:

在当前的 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 还提供了一种更简洁的方法来直接访问清单文件。

【讨论】:

以上是关于如何在android studio中用gradle替换buildvariant的字符串?的主要内容,如果未能解决你的问题,请参考以下文章

如何建立与 Android studio和 gradle android 库

Eclipse 工程迁移到 Android Studio

Eclipse 工程迁移到 Android Studio

Eclipse 工程迁移到 Android Studio

Eclipse 工程迁移到 Android Studio

如何建立与 Android studio和 gradle android 库