已回答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
不是很熟悉。
答案 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,以防其他值具有不同的值。
这是我的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)
}
}