在Gradle中编辑google-services.json以获得不同的风格

时间:2017-12-12 11:36:17

标签: android android-gradle build.gradle google-play-services

已回答here

我的应用程序中有多种风格,我想对所有这些使用相同的google-service.json,所以我考虑将属性package_name的值设置为正则表达式并使用task(应用模块)中的build.gradle替换它。

我的口味是以这种方式定义的:

android {
    productFlavors {
        FirstFlavor {
            applicationId "com.thisapp.first"
            versionCode = 1
            versionName "1.0"
        }
        SecondFlavor {
            applicationId "com.myapp.second"
            versionCode = 1
            versionName "1.0"
        }
    }
}

我的想法是这样的:

task runBeforeBuild(type: Exec) {
    def google_json = file('./google-services.json')
    google_json.getText().replace('${package_name_value}', myPackageName)
}

问题是我不知道如何访问PackageName(代码中的 myPackageName ),或者甚至是否可能。

也许我必须使用其他任务而不是runBeforeBuild,我对Gradle不是很熟悉。

2 个答案:

答案 0 :(得分:2)

答案更新

首先,我必须解释我使用Jenkins编译我的应用程序,因此构建过程与Android Studio中的完全不同。在我的情况下,Jenkins只构建发行版本,而不是以与IDE相同的方式获得这些版本。我将解释两种解决方案:

build.gradle (Module: app)

<强>矿

buildscript{
...
}
android {
...
}

afterEvaluate {
    android.applicationVariants.all { variant ->
        preBuild.doLast {
            setGoogleServicesJson(variant)
        }
    }
    // Only for Jenkins
    assembleRelease.doFirst {
        deleteGoogleServicesJson()
    }
}

def setGoogleServicesJson(variant) {
    def originalFileName = "google-services.bak"
    def newFileName = "google-services.json"
    def originalFile = "./$originalFileName"
    def newFile = "./$newFileName"
    def applicationId = variant.applicationId
    def regularExpression = "\\\"package_name\\\" : \\\"(\\w(\\.\\w)?)+\\\""
    def packageName = "\\\"package_name\\\" : \\\"$applicationId\\\""

    copy {
        from (originalFile)
        into ("./")
        rename (originalFileName, newFileName)
    }
    ant.replaceregexp(
            file: newFile,
            match: regularExpression,
            replace: packageName,
            byLine: true)
}

def deleteGoogleServicesJson() {
    file("./google-services.json").delete()
}

apply plugin: 'com.google.gms.google-services'

Jenkins正在&#39; Project / app /&#39; 文件夹中找到google-services.json并且它没有使用那些风味的文件夹,所以每个变体并且尽快(在preBuild任务之后)我从我的*.bak文件创建一个新的JSON,覆盖package_name并让Gradle继续建造。< / p>

完成所有操作后,在发布应用程序(assembleRelease.doFirst)之前,我会删除google-services.json并保留*.bak

在我的情况下,我只想更改我的JSON的package_name值,但如果我想将另一个值更改为project_number,{{1},此解决方案将无法工作或其他任何其他取决于风味。

替代解决方案(使用口味)

client_id

在此解决方案中,我在&#39; Project / app /&#39; 文件夹中有afterEvaluate { android.applicationVariants.all { variant -> def fileName = "google-services.json" def originalFile = "./$fileName" def flavorName = variant.flavorName def destinationPath = "." // If there is no flavor we use the original path if (!flavorName.empty) { destinationPath = "$destinationPath/src/$flavorName/" copy { from file(originalFile) into destinationPath } } def regularExpression = "\\\"package_name\\\" : \\\"(\\w(\\.\\w)?)+\\\"" def packageName = "\\\"package_name\\\" : \\\"$variant.applicationId\\\"" ant.replaceregexp( file: "./$destinationPath/$fileName", match: regularExpression, replace: packageName, byLine: true) } } ,我在每个flavor文件夹中复制了它。然后我重写 package_name 。如果你的工作没有风味,应用程序将使用原始的JSON进行编译。

在覆盖它之前,您可以检查flavor文件夹中是否存在另一个JSON,以防其他值具有不同的值。

旧解决方案

我找到了混合thisthis答案的解决方案。

这是我的google-services.json

build.gradle (Module: app)

其中afterEvaluate { android.applicationVariants.all { variant -> def applicationId = variant.applicationId ant.replaceregexp(file: './google-services.json', match:'package_name_value', replace: applicationId, byLine: true) } } 是&#34;正则表达式&#34;我已经定义要被替换。

package_name_value的位置是&#34; MyProject / ppp / google-services.json&#34; ,我已经测试过,如果你放另一个{ {1}}在您的flavor文件夹中,它会覆盖第一个。

*如果同时定义了多个flavor,则存在(至少)一个问题,因为此任务始终覆盖同一个文件,因此最终的应用程序ID将是您定义的最后一个。

如果您有其他方式,请随意发布。

答案 1 :(得分:0)

我找到了另一种方法,并想分享它。 请注意,这是我第一次使用gradle编写一些任务,因此代码根本不是最优的(我现在不能花更多的时间来改进它)。

说明

我所做的很简单。

1)在任务processFlavorBuildTypeGoogleServices之前,即Google服务中将读取google-services.json文件的任务,我会触发一些代码来更新google-services.json文件。 为了做到这一点:

gradle.taskGraph.beforeTask { Task task ->
    if (task.name.startsWith("process") && task.name.endsWith("GoogleServices")) {
    }
}

2)从任务名称中检索当前flavor和buildType(任务名称的示例:processProdReleaseGoogleServices,以流程&#39; Flavor&#39; BuildType&#39; GoogleServices)的形式

String currentFlavor = task.name.replace("process", "").replace("GoogleServices", "")
currentFlavor = currentFlavor.toLowerCase()

3)从currentFlavor变量中删除buildType。为了做到这一点,我只是循环遍历项目中的所有buildTypes,并从currentFlavor变量中删除它们

android.applicationVariants.all { variant ->
    currentFlavor = currentFlavor.replace(variant.buildType.name, "")
}

此时,变量currentFlavor具有currentFlavor(例如&#34; prod&#34;)

4)从我的build.gradle

中定义的flavor中检索包名

在我的build.gradle中,我为每个flavor指定packageName:

productFlavors {
    prod {
        applicationId 'packageName1'
    }
    rec {
        applicationId 'packageName2'
    }
}

我检索它是这样的: (包名称随[]返回,所以我必须删除它们。例如我会检索[packageName1])

String currentApplicationId;
android.applicationVariants.all { variant ->
    if (variant.flavorName == currentFlavor) {
        currentApplicationId = variant.productFlavors.applicationId.toString().replace("[", "").replace("]", "")
    }
}

5)现在我有了当前版本的软件包名称,我只需打开当前的google-services.json文件,然后更新其中的软件包名称。为此,我添加了一个方法updateGoogleServicesJsonFile。 小心更改第二行的filePath以指向您的位置。

def updateGoogleServicesJsonFile(applicationId) {
    File file = new File(getProjectDir(), "/google-services.json")
    if (!file.exists())
    {
        project.logger.log(LogLevel.ERROR, "Error updating the google-services.json because the file doesn't exists...")
        return
    }

    List<String> lineList = file.readLines()
    for (int i = 0; i < lineList.size(); i++)
    {
        if (lineList.get(i).trim().startsWith("\"package_name\": \""))
        {
            String line = lineList.get(i)
            line = line.substring(0, line.indexOf(":") + 1)
            line += " \"" + applicationId + "\""

            lineList.set(i, line)
        }
    }

    file.write(lineList.join("\n"))
}

并且你有它,一些代码在执行读取任务之前更新google-services.json文件。

代码

def updateGoogleServicesJsonFile(applicationId) {
    File file = new File(getProjectDir(), "/google-services.json")
    if (!file.exists())
    {
        project.logger.log(LogLevel.ERROR, "Error updating the google-services.json because the file doesn't exists...")
        return
    }

    List<String> lineList = file.readLines()
    for (int i = 0; i < lineList.size(); i++)
    {
        if (lineList.get(i).trim().startsWith("\"package_name\": \""))
        {
            String line = lineList.get(i)
            line = line.substring(0, line.indexOf(":") + 1)
            line += " \"" + applicationId + "\""

            lineList.set(i, line)
        }
    }

    file.write(lineList.join("\n"))
}

gradle.taskGraph.beforeTask { Task task ->
    // Before the task processFlavorBuildTypeGoogleServices (such as processProdReleaseGoogleServices), we update the google-services.json
    if (task.name.startsWith("process") && task.name.endsWith("GoogleServices")) {
        // Getting current flavor name out of the task name
        String currentFlavor = task.name.replace("process", "").replace("GoogleServices", "")
        currentFlavor = currentFlavor.toLowerCase()

        android.applicationVariants.all { variant ->
            currentFlavor = currentFlavor.replace(variant.buildType.name, "")
       }

        // Getting current application id that are defined in the productFlavors
        String currentApplicationId;
        android.applicationVariants.all { variant ->
            if (variant.flavorName == currentFlavor) {
                currentApplicationId = variant.productFlavors.applicationId.toString().replace("[", "").replace("]", "")
            }
        }

       updateGoogleServicesJsonFile(currentApplicationId)
    }
}