26

我的项目有两种风格:

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

现在我想构建一个风味 1 和风味 2 的 buildvariant。buildvariant 的唯一区别是另一个包名。

我的项目使用 MapFragments 并且只有一个 Manifest - 所以我将 MAPS_RECEIVE 的权限名称放在各自风格的字符串资源文件中。

问题是:如何替换 buildvariant 的字符串资源?

我尝试了以下方法(在这篇文章中描述):

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

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

找不到参数 [{tokens={package_permission=com.example.rev.flavor1.permission.MAPS_RECEIVE}} 的方法 filter(), 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}] 在 BuildTypeD sl_Decorated{name=buderusFinal, debuggable=false, jniDebugBuild=false, renderscr iptDebugBuild=false, renderscriptOptimLevel=3 , packageNameSuffix=null, versionNameSuffix=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'
                 filter{String line -> line.replaceAll(package_permission, 'com.example.rev.flavor1.permission.MAPS_RECEIVE')}
            }
            into '$buildDir/res'
        }
    }
} 
4

4 回答 4

39

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

  • 一般复制任务:

    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>")
       }
    }
    
  • 我认为最大的问题是获得正确的路径,因为我必须动态地进行此操作(此链接对我非常有帮助)。我通过替换清单中的特殊行而不是字符串文件中的特殊行来解决我的问题。

  • 以下示例显示如何替换清单中的“元数据”标签以使用您的 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")
            }    
       }
    }
    
于 2013-07-10T14:00:11.233 回答
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如果你想看看它以后是否会发展,我也有它。

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

于 2014-04-04T03:03:49.237 回答
4

The answers are quite outdated, there are better ways now to archive it. You can use the command in your build.gradle:

manifestPlaceholders = [
            myPlaceholder: "placeholder",
    ]

and in your manifest:

android:someManifestAttribute="${myPlaceholder}"

more information can be found here: https://developer.android.com/studio/build/manifest-merge.html

于 2016-10-05T01:07:10.420 回答
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 还提供了一种更简洁的方法来直接访问清单文件。

于 2015-12-04T07:14:25.557 回答