在Android项目(该平台是用于创建用于查看视频内容的应用程序的平台)上工作时,有必要通过将有关将配置签名的信息传输到外部文件来动态配置产品风格。 细节剪下。
源数据
有一个Android项目,这是一个用于创建用于查看视频内容的应用程序的平台。 代码库对于所有应用程序都是通用的,区别在于REST API参数的设置和应用程序外观的设置(横幅,颜色,字体等)。 在项目中使用了三种风味维度:
- 市场 :谷歌或亚马逊。 因为 应用程序既可以在Google Play上发布,也可以在Amazon Marketplace上分发,需要根据分发位置共享一些功能。 例如:亚马逊禁止使用Google的应用内购买机制,并要求实施其机制。
- 端点 :“ pro”或“ staging”。 生产和登台版本的特定配置。
- site :特定应用程序的实际尺寸。 设置applicationId和signingConfig。
我们遇到的问题
创建新应用程序时,有必要添加Product Flavor:
application1 { dimension 'site' applicationId 'com.damsols.application1' signingConfig signingConfigs.application1 }
另外,有必要添加适当的签名配置:
application1 { storeFile file("path_to_keystore1.jks") storePassword "password1" keyAlias "application1" keyPassword "password1" }
问题:
- 五行添加一个应用程序,仅在applicationId和signingConfig上有所不同。 当应用程序数量超过50个时,build.gradle文件开始包含500余行应用程序信息。
- 以纯文本形式存储有关用于签名应用程序的密钥库的信息。
Build.gradle示例 apply plugin: 'com.android.application' android { compileSdkVersion 28 defaultConfig { minSdkVersion 23 targetSdkVersion 28 versionCode 1 versionName "1.0" } buildTypes { release { minifyEnabled false } } flavorDimensions "site", "endpoint", "market" signingConfigs { application1 { storeFile file("application1.jks") storePassword "password1" keyAlias "application1" keyPassword "password1" } application2 { storeFile file("application2.jks") storePassword "password2" keyAlias "application2" keyPassword "password2" } application3 { storeFile file("application3.jks") storePassword "password3" keyAlias "application3" keyPassword "password3" } } productFlavors { pro { dimension 'endpoint' } staging { dimension 'endpoint' } google { dimension 'market' } amazon { dimension 'market' } application1 { dimension 'site' applicationId "com.damsols.application1" signingConfig signingConfigs.application1 } application2 { dimension 'site' applicationId "com.damsols.application2" signingConfig signingConfigs.application2 } application3 { dimension 'site' applicationId "com.damsols.application3" signingConfig signingConfigs.application3 } } } dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation 'com.android.support:appcompat-v7:28.0.0' implementation 'com.android.support.constraint:constraint-layout:1.1.3' }
第一步是将证书信息传输到一个单独的json文件中。 例如,信息也以纯文本形式存储,但是没有什么可以阻止您以加密形式存储文件(我们使用GPG)并在应用程序构建期间直接对其进行解密。 JSON文件具有以下结构:
{ "signingConfigs":[ { "configName":"application1", "storeFile":"application1.jks", "storePassword":"password1", "keyAlias":"application1", "keyPassword":"password1" }, { "configName":"application2", "storeFile":"application2.jks", "storePassword":"password2", "keyAlias":"application2", "keyPassword":"password2" }, { "configName":"application3", "storeFile":"application3.jks", "storePassword":"password3", "keyAlias":"application3", "keyPassword":"password3" }, ] }
build.gradle文件中的signingConfigs部分将被删除。
简化产品风味部分
为了减少描述尺寸=“站点”的产品风味所需的行数,创建了一个数组,其中包含描述特定应用程序的必要信息,并且删除了所有尺寸为“站点”的产品风味。
那是:
... productFlavors { pro { dimension 'endpoint' } staging { dimension 'endpoint' } google { dimension 'market' } amazon { dimension 'market' } application1 { dimension 'site' applicationId "com.damsols.application1" signingConfig signingConfigs.application1 } application2 { dimension 'site' applicationId "com.damsols.application2" signingConfig signingConfigs.application2 } application3 { dimension 'site' applicationId "com.damsols.application3" signingConfig signingConfigs.application3 } } } ...
它变成了:
... productFlavors { pro { dimension 'endpoint' } staging { dimension 'endpoint' } google { dimension 'market' } amazon { dimension 'market' } } def applicationDefinitions = [ ['name': 'application1', 'applicationId': 'com.damsols.application1'], ['name': 'application2', 'applicationId': 'com.damsols.application2'], ['name': 'application3', 'applicationId': 'com.damsols.application3'] ] } ...
动态产品风味创造
最后一步是使用带有来自applicationDefinitions数组的证书信息的外部JSON文件,动态创建产品风味和签名配置。
def applicationDefinitions = [ ['name': 'application1', 'applicationId': 'com.damsols.application1'], ['name': 'application2', 'applicationId': 'com.damsols.application2'], ['name': 'application3', 'applicationId': 'com.damsols.application3'] ] def signKeysFile = file('signkeys/signkeys.json') def signKeys = new JsonSlurper().parseText(signKeysFile.text) def configs = signKeys.signingConfigs def signingConfigsMap = [:] configs.each { config -> signingConfigsMap[config.configName] = config } applicationDefinitions.each { applicationDefinition -> def signingConfig = signingConfigsMap[applicationDefinition['name']] android.productFlavors.create(applicationDefinition['name'], { flavor -> flavor.dimension = 'site' flavor.applicationId = applicationDefinition['applicationId'] flavor.signingConfig = android.signingConfigs.create(applicationDefinition['name']) flavor.signingConfig.storeFile = file(signingConfig.storeFile) flavor.signingConfig.storePassword = signingConfig.storePassword flavor.signingConfig.keyAlias = signingConfig.keyAlias flavor.signingConfig.keyPassword = signingConfig.keyPassword }) }
要添加来自加密存储的读取,您需要替换该部分
def signKeysFile = file('signkeys/signkeys.json') def signKeys = new JsonSlurper().parseText(signKeysFile.text) def configs = signKeys.signingConfigs
从加密文件中读取。
整个构建 import groovy.json.JsonSlurper apply plugin: 'com.android.application' android { compileSdkVersion 28 defaultConfig { minSdkVersion 23 targetSdkVersion 28 versionCode 1 versionName "1.0" } buildTypes { release { minifyEnabled false } } flavorDimensions "site", "endpoint", "market" signingConfigs {} productFlavors { pro { dimension 'endpoint' } staging { dimension 'endpoint' } google { dimension 'market' } amazon { dimension 'market' } } } def applicationDefinitions = [ ['name': 'application1', 'applicationId': 'com.damsols.application1'], ['name': 'application2', 'applicationId': 'com.damsols.application2'], ['name': 'application3', 'applicationId': 'com.damsols.application3'] ] def signKeysFile = file('signkeys/signkeys.json') def signKeys = new JsonSlurper().parseText(signKeysFile.text) def configs = signKeys.signingConfigs def signingConfigsMap = [:] configs.each { config -> signingConfigsMap[config.configName] = config } applicationDefinitions.each { applicationDefinition -> def signingConfig = signingConfigsMap[applicationDefinition['name']] android.productFlavors.create(applicationDefinition['name'], { flavor -> flavor.dimension = 'site' flavor.applicationId = applicationDefinition['applicationId'] flavor.signingConfig = android.signingConfigs.create(applicationDefinition['name']) flavor.signingConfig.storeFile = file(signingConfig.storeFile) flavor.signingConfig.storePassword = signingConfig.storePassword flavor.signingConfig.keyAlias = signingConfig.keyAlias flavor.signingConfig.keyPassword = signingConfig.keyPassword }) } dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation 'com.android.support:appcompat-v7:28.0.0' implementation 'com.android.support.constraint:constraint-layout:1.1.3' }
GitHub链接
谢谢你