前提条件:
现在要做一个sdk,而这个sdk项目要适用于公司所有的App, 然后sdk的主题色要来自外部的app,所以的那个集成的时候我想根据app层的主题配置文件生成sdk所需要的theme主题色,而某个app可能有多个渠道版本,所以对同一个app来说,又分为多个theme主题色,这时候,我想知道并且根据当前运行的flovar在sdk library中生成相应的theme主题色,那么如何知道当前运行的flavor是哪个呢?或者说怎么当前运行的flavor?查阅相关资料,然后关于如何获取当前Flavor,网上千篇一律的都是这个答案:
https://stackoverflow.com/questions/30621183/how-to-get-current-flavor-in-gradle
然后我试了试,别不是网上说的那样,根本无法得到正确的输出,我得到的是这样的答案,一直是null:
然后我想了想,还是只能靠自己,于是我选择了另一条路,我去了解了Gradle的生命周期, 关于Gradle 生命周期及Task全解,感谢下面这个文章博主的干货给了我很大的帮助,
https://www.shangmayuan.com/a/41cac886af394513986270f7.html
经过一天的努力,终于我把上面所提到的Sdk中想要解决的问题完美的达到了我的目标。
Main module:
[app]: build.gradle
apply from: '../mySDK/auto-generating-build-utils.gradle'
dependencies {
...
//generate multiple color files by flavors .
//android.productFlavors.all { flavor ->
// preBuild.dependsOn autoGenerateFileTask(flavor.name)
// }
//generate single color file by currently running flavor.
afterEvaluate {
// android.productFlavors.all { flavor ->
// def flavorName = "${flavor.name}"
// def capitalizeTaskPrefix = "${flavor.name}".capitalize()
def flavorName = "main"
def capitalizeTaskPrefix = "".capitalize()
def buildConfigDebugTask = tasks.findByName("pre${capitalizeTaskPrefix}DebugBuild")
def buildConfigReleaseTask = tasks.findByName("pre${capitalizeTaskPrefix}ReleaseBuild")
if (buildConfigDebugTask != null) {
println "chatFlavor:pre${capitalizeTaskPrefix}DebugBuild"
buildConfigDebugTask.doLast {
generateChatConfigTask("${flavorName}")
}
} else {
println "chatFlavor:pre${capitalizeTaskPrefix}DebugBuild not found"
}
if (buildConfigReleaseTask != null) {
println "chatFlavor:pre${capitalizeTaskPrefix}ReleaseBuild"
buildConfigReleaseTask.doLast {
generateChatConfigTask("${flavorName}")
}
} else {
println "chatFlavor:pre${capitalizeTaskPrefix}ReleaseBuild not found"
}
// }
}
...
}
local.properties
## This file is automatically generated by Android Studio.
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
#
# This file should *NOT* be checked into Version Control Systems,
# as it contains information specific to your local configuration.
#
# Location of the SDK. This is only used by Gradle.
# For customization when using a Version Control System, please read the
# header note.
sdk.dir=C\:\\android\\sdk
# example: /assets/chat_theme/chatStyle.json
chatThemeAssetsPath=/assets/my_sdk_res/themeStyle.json
auto-generating-build-utils.gradle
import groovy.json.JsonSlurper
import groovy.json.JsonOutput
import groovy.xml.MarkupBuilder
import java.util.regex.Pattern
ext.autoGenerateFileTask = { projectFlavor ->
def myProjectName = "chatSDK"
println projectFlavor
return tasks.create("generateChatThemeTask$projectFlavor", DefaultTask) {
// style_default.json is parsed in baseUILib and we will only maintain that json as default
group = "autoGenerateThemeRelated"
// Retailers' customized colors
def localProperties = new Properties()
def dis = null
try {
def localFile = new File("$projectDir/src/main/chat_config.properties")
println "chat_config_path==========>$localFile"
if (localFile != null && localFile.exists()) {
dis = localFile.newDataInputStream()
localProperties.load(dis)
} else {
println "chat_config_path==========>localProperties load failure}"
}
} catch (Exception e) {
println "chat_config_path==========>Exception occurred}"
e.printStackTrace()
} finally {
if (dis != null) {
dis.close()
}
}
// field definitions
def matchString = "//.*"
def inputFile
def jsonFileString
def patternComment
def matcherComment
def newContent
def json
def chatThemeAssetsPath = localProperties.getProperty("chatSDK.chatThemeAssetsPath")
println "chatSDK.chatThemeAssetsPath==>$projectFlavor:$chatThemeAssetsPath"
if (chatThemeAssetsPath == null || "" == chatThemeAssetsPath || "null".equalsIgnoreCase(chatThemeAssetsPath)) {
throw new NullPointerException(" 'chatSDK.chatThemeAssetsPath' must be configured in '$projectDir/src/main/chat_config.properties' example:\n\n chatSDK.chatThemeAssetsPath=/assets/chat_theme/themeStyle.json\n");
}
inputFile = new File("$projectDir/src/$projectFlavor$chatThemeAssetsPath")
println "chatSDK.chatThemeAssetsPathAbsolutely==>$inputFile.absolutePath"
jsonFileString = inputFile.text
patternComment = Pattern.compile(matchString)
matcherComment = patternComment.matcher(jsonFileString)
newContent = matcherComment.replaceAll("")
json = new JsonSlurper().parseText(newContent)
//do generating color xml.
generateColorXmlTask(json, projectFlavor, myProjectName)
//do generating entity class.
generateEntityTask(localProperties, json, projectFlavor, myProjectName)
// do generating event entity class
generateEventEntityTask(localProperties, projectFlavor, myProjectName)
}
}
private void generateColorXmlTask(Object jsonObject, String flavor, String myProjectName) {
def sw
def xml
def file
// colors.xml for Brand, will generate color file in GoBank flavor
sw = new StringWriter()
xml = new MarkupBuilder(sw)
xml.setDoubleQuotes(true)
xml.resources() {
jsonObject.colors.each {
k, v ->
def colorV = swapAlphaColor(v)
if (colorV.contains("#")) {
color(name: "${k}", "${colorV}")
} else {
color(name: "${k}", "@color/" + "${colorV}")
}
}
}
def desPath = "${rootProject.file("$myProjectName").absolutePath}/src/main"
def fileDirectoryRes = new File("$desPath/res/values")
if (!fileDirectoryRes.exists()) {
fileDirectoryRes.mkdirs()
}
file = new File("$desPath/res/values/generated_chat_colors.xml")
file.write(sw.toString())
}
private String swapAlphaColor(String color) {
if (color.length() == 9 && color.contains("#")) {
def swapStringColor = color.substring(1)
return swapSubstrings(swapStringColor, 7)
} else {
return color
}
}
private String swapSubstrings(String colorValue, Integer index) {
return "#" + colorValue.substring(index - 1) + colorValue.substring(0, index - 1)
}
private void generateEntityTask(Properties localProperties, Object jsonObject, String projectFlavor, String myProjectName) {
def desPath = "${rootProject.file("$myProjectName").absolutePath}/src/main/java/com/patrick/chatsdk/theme/model"
File genDir = new File(desPath)
if (!genDir.exists()) {
genDir.mkdirs()
}
def autoGenerateTips = "auto-generated code. DO NOT MODIFY!"
def packageName = "com.patrick.chatsdk.theme.model;"
def fileHeader = "/**\n*$autoGenerateTips\n*/\npackage $packageName\n\n"
//-------------- auto generating ChatColors.java -------------------
String chatColorFileName = "ChatColors"
StringBuilder chatColorContent = new StringBuilder()
chatColorContent.append("$fileHeader")
chatColorContent.append("public class $chatColorFileName {\n")
jsonObject.colors.each {
k, v ->
chatColorContent.append(" public final String $k = \"$v\";\n")
}
chatColorContent.append("}")
FileWriter colorFw = new FileWriter(new File("$desPath/${chatColorFileName}.java"))
colorFw.write(chatColorContent.toString())
colorFw.flush()
//-------------- auto generating ChatDimens.java -------------------
String chatDimensFileName = "ChatDimens"
StringBuilder chatDimensContent = new StringBuilder()
chatDimensContent.append("$fileHeader")
chatDimensContent.append("public class $chatDimensFileName {\n")
jsonObject.dimens.each {
k, v ->
chatDimensContent.append(" public final Double $k = $v;\n")
}
chatDimensContent.append("}")
FileWriter dimensFw = new FileWriter(new File("$desPath/${chatDimensFileName}.java"))
dimensFw.write(chatDimensContent.toString())
dimensFw.flush()
//-------------- auto generating ChatFonts.java -------------------
//example:chatSDK.chatFontsDirName=/assets/font/
//Implementation 1:
// def assetsDir = "$projectDir/src/$flavor/assets"
// def defaultFontsDir = new File("$assetsDir/fonts")
// if (!defaultFontsDir.exists()) {
// defaultFontsDir = new File("$assetsDir/font")
// }
// println "chatSDK.defaultFontsDir==>${defaultFontsDir}[$flavor]"
// if (!defaultFontsDir.exists()) {
// def chatFontsDirName = localProperties.getProperty("chatSDK.chatFontsDirName")
// defaultFontsDir = "$projectDir/src/$flavor$chatFontsDirName"
// println "chatSDK.chatFontsDirName==>${defaultFontsDir}[$flavor]"
// }
// if (defaultFontsDir == null || "" == defaultFontsDir || "null".equalsIgnoreCase(defaultFontsDir)) {
// throw new NullPointerException(" There is no font files found in ${defaultFontsDir},\n\n either 'chatSDK.chatFontsDirName' must be configured in '$projectDir/src/main/chat_config.properties' example:\n\n chatSDK.chatFontsDirName=/assets/font/ \n");
// }
//Implementation 2:
def defaultFontsDir = localProperties.getProperty("chatSDK.chatFontsDirName")
if (defaultFontsDir == null || "" == defaultFontsDir || "null".equalsIgnoreCase(defaultFontsDir)) {
defaultFontsDir = "font"
}
println "chatSDK.defaultFontsDir==>$defaultFontsDir"
//check first.
def jsonSlurper = new JsonSlurper()
def firstFontStyleJson = ""
jsonObject.fonts.eachWithIndex {
keyValue, index ->
if (index == 0) {
def firstFontEntry = JsonOutput.toJson(keyValue)
def firstFontValue = jsonSlurper.parseText(firstFontEntry).value
def firstFontGroovy = JsonOutput.toJson(firstFontValue)
firstFontStyleJson = jsonSlurper.parseText(firstFontGroovy)
println "chatSDK.firstFontFileJsonStyle==>${firstFontStyleJson.family}|${firstFontStyleJson.weight}|${firstFontStyleJson.size}"
return true
}
println "chatSDK.testLoopBreak==>index=$index"
}
println "\nchatSDK.checkValidFont==>phrase_1"
def validFormatJson = checkValidFont(projectFlavor, "assets", defaultFontsDir, firstFontStyleJson.family, firstFontStyleJson.weight, "_", 0)
if ("" == validFormatJson) {
println "\nchatSDK.checkValidFont==>phrase_2"
validFormatJson = checkValidFont(projectFlavor, "res", defaultFontsDir, firstFontStyleJson.family, firstFontStyleJson.weight, "_", 0)
}
println "chatSDK.checkValidFont==>found in valid font format json '$validFormatJson'\n"
//start generating.
def validFormatJsonObject = jsonSlurper.parseText(validFormatJson)
String chatFontsFileName = "ChatFonts"
StringBuilder chatFontsContent = new StringBuilder()
chatFontsContent.append("$fileHeader")
chatFontsContent.append("public class $chatFontsFileName {\n")
def fontStyleGroovy
def fontStyleJson
def canonicalFamilyChanged
def canonicalWeightChanged
def canonicalName
def isCapital = Boolean.valueOf(validFormatJsonObject.isCapital)
jsonObject.fonts.each {
k, v ->
fontStyleGroovy = JsonOutput.toJson(v)
fontStyleJson = jsonSlurper.parseText(fontStyleGroovy)
canonicalFamilyChanged = capitalChange(fontStyleJson.family, isCapital)
canonicalWeightChanged = capitalChange(fontStyleJson.weight, isCapital)
canonicalName = "${canonicalFamilyChanged}${validFormatJsonObject.splitSymbol}${canonicalWeightChanged}"
chatFontsContent.append(" public final ChatThemeFont $k = new ChatThemeFont(\"$defaultFontsDir/${canonicalName}.ttf\", ${fontStyleJson.size}f);\n")
}
chatFontsContent.append("}")
FileWriter fontsFw = new FileWriter(new File("$desPath/${chatFontsFileName}.java"))
fontsFw.write(chatFontsContent.toString())
fontsFw.flush()
}
ext.validFormatJson = ""
ext.tempFileName = ""
private String checkValidFont(String projectFlavor, String assetsDir, String fontDir, String family, String weight, String splitSymbol, int index) {
ext.tempFileName = "${family}$splitSymbol${weight}.ttf"
def fontCheckingPath = "$projectDir/src/$projectFlavor/$assetsDir/$fontDir/${ext.tempFileName}"
def validFile = new File(fontCheckingPath)
println "chatSDK.checkValidFont path==>${validFile.getCanonicalPath()} |exists=${validFile.exists()}"
if (!validFile.exists()) {//checked: ax_bx.ttf
if (index == 0) {
//check: ax-bx.ttf
checkValidFont(projectFlavor, assetsDir, fontDir, family, weight, "-", 1)
} else if (index == 1) {
//check: Ax_Bx.ttf
checkValidFont("main", assetsDir, fontDir, family, weight, "_", 2)
} else if (index == 2) {
//check: Ax-Bx.ttf
checkValidFont("main", assetsDir, fontDir, family, weight, "-", 3)
} else if (index == 3) {
ext.validFormatJson = ""
}
} else {
def isCapitalStr = ext.tempFileName.matches("^[A-Z].*\$")
if (validFile.getCanonicalPath().contains("${ext.tempFileName}")) {
println "\nchatSDK.checkValidFont==>path contains=${ext.tempFileName}"
ext.validFormatJson = "{\"isCapital\":\"${isCapitalStr}\",\"splitSymbol\":\"$splitSymbol\",\"canonicalName\":\"${ext.tempFileName}\"}"
} else {
def canonicalFamilyChanged = capitalChange(family, !isCapitalStr)
def canonicalWeightChanged = capitalChange(weight, !isCapitalStr)
def canonicalName = "${canonicalFamilyChanged}$splitSymbol${canonicalWeightChanged}"
println "\nchatSDK.checkValidFont==>path not contains='${ext.tempFileName}' ,the correct one should be '$canonicalName'.ttf"
ext.validFormatJson = "{\"isCapital\":\"${!isCapitalStr}\",\"splitSymbol\":\"$splitSymbol\",\"canonicalName\":\"$canonicalName\"}"
}
}
return ext.validFormatJson
}
private String capitalChange(String targetStr, boolean upperCase) {
def targetStrFirst = targetStr.substring(0, 1)
def targetStrAfter = targetStr.substring(1)
if (upperCase) {
return "${targetStrFirst.toUpperCase()}$targetStrAfter"
} else {
return "${targetStrFirst.toLowerCase()}$targetStrAfter"
}
}
private void generateEventEntityTask(Properties localProperties, String projectFlavor, String myProjectName) {
def chatEventAssetsPath = localProperties.getProperty("chatSDK.chatEventAssetsPath")
if (chatEventAssetsPath == null || "" == chatEventAssetsPath || "null".equalsIgnoreCase(chatEventAssetsPath)) {
throw new NullPointerException(" 'chatSDK.chatEventAssetsPath' must be configured in '$projectDir/src/main/chat_config.properties' example:\n\n chatSDK.chatEventAssetsPath=/assets/chat_theme/chatEvent.json\n");
}
def eventInputFile = new File("$projectDir/src/$projectFlavor$chatEventAssetsPath")
println "chatSDK.chatEventAssetsPathAbsolutely==>$eventInputFile.absolutePath"
def eventJsonFileString = eventInputFile.text
def matchString = "//.*"
def patternComment = Pattern.compile(matchString)
def matcherComment = patternComment.matcher(eventJsonFileString)
def eventNewContent = matcherComment.replaceAll("")
def eventJson = new JsonSlurper().parseText(eventNewContent)
def desPath = "${rootProject.file("$myProjectName").absolutePath}/src/main/java/com/patrick/chatsdk/event"
File genDir = new File(desPath)
if (!genDir.exists()) {
genDir.mkdirs()
}
def autoGenerateTips = "auto-generated code. event part DO NOT MODIFY!"
def packageName = "com.patrick.chatsdk.event;"
def fileHeader = "/**\n*$autoGenerateTips\n*/\npackage $packageName\n\n"
String chatEventFileName = "ChatEventKey"
StringBuilder chatEventContent = new StringBuilder()
chatEventContent.append("$fileHeader")
chatEventContent.append("public class $chatEventFileName {\n")
eventJson.eventStateKey.each {
k, v ->
chatEventContent.append(" public final String $k = \"$v\";\n")
}
eventJson.eventKey.each {
k, v ->
chatEventContent.append(" public final String $k = \"$v\";\n")
}
chatEventContent.append("}")
FileWriter eventFw = new FileWriter(new File("$desPath/${chatEventFileName}.java"))
eventFw.write(chatEventContent.toString())
eventFw.flush()
}
-----------------------------End-----------------------------