在没有将keystore信息放入build.gradle的情况下签名APK

我正在尝试设置签名过程,以使密钥库密码和密钥密码存储在项目的build.gradle文件中。

目前我在build.gradle有以下build.gradle

 android { ... signingConfigs { release { storeFile file("my.keystore") storePassword "store_password" keyAlias "my_key_alias" keyPassword "key_password" } } buildTypes { release { signingConfig signingConfigs.release } } } 

它工作得很好,但我不能把我的仓库中的storePasswordkeyPassword的值。 我宁愿不把storeFilekeyAlias那里。

有没有办法改变build.gradle以便它会从一些外部来源获取密码(如仅在我的电脑上的文件)?

当然,修改后的build.gradle应该可以在任何其他计算机上使用(即使计算机无法访问密码)。

我正在使用Android Studio和Mac OS X Maverics。

Groovy的好处是可以自由混合Java代码,使用java.util.Properties读取键/值文件非常容易。 也许有更简单的方法使用惯用的Groovy,但Java仍然非常简单。

创build一个keystore.properties文件(在本例中,在settings.gradle旁边的项目根目录中,尽pipe你可以把它放在任何你喜欢的地方:

 storePassword="..." keyPassword="..." keyAlias="..." storeFile="..." 

添加到你的build.gradle

 allprojects { afterEvaluate { project -> def propsFile = rootProject.file('keystore.properties') def configName = 'release' if (propsFile.exists() && android.signingConfigs.hasProperty(configName)) { def props = new Properties() props.load(new FileInputStream(propsFile)) android.signingConfigs[configName].storeFile = file(props['storeFile']) android.signingConfigs[configName].storePassword = props['storePassword'] android.signingConfigs[configName].keyAlias = props['keyAlias'] android.signingConfigs[configName].keyPassword = props['keyPassword'] } } } 

或者,如果您想以更类似于自动生成的gradle代码的方式应用Scott Barta的答案,则可以在项目根文件夹中创buildkeystore.properties文件:

 storePassword=my.keystore keyPassword=key_password keyAlias=my_key_alias storeFile=store_file 

并修改你的gradle代码为:

 // Load keystore def keystorePropertiesFile = rootProject.file("keystore.properties"); def keystoreProperties = new Properties() keystoreProperties.load(new FileInputStream(keystorePropertiesFile)) ... android{ ... signingConfigs { release { storeFile file(keystoreProperties['storeFile']) storePassword keystoreProperties['storePassword'] keyAlias keystoreProperties['keyAlias'] keyPassword keystoreProperties['keyPassword'] } } ... } 

您可以将此属性文件存储在模块的根目录中,在这种情况下,只需省略rootProject ,还可以修改此代码以为不同的密钥库和密钥别名提供多组属性。

阅读了几个链接后:

http://blog.macromates.com/2006/keychain-access-from-shell/ http://www.thoughtworks.com/es/insights/blog/signing-open-source-android-apps-without-disclosing-密码;

由于您使用的是Mac OSX,因此您可以使用钥匙串访问来存储您的密码。

如何在Keychain Access中添加密码

然后在你的gradle脚本中:

 /* Get password from Mac OSX Keychain */ def getPassword(String currentUser, String keyChain) { def stdout = new ByteArrayOutputStream() def stderr = new ByteArrayOutputStream() exec { commandLine 'security', '-q', 'find-generic-password', '-a', currentUser, '-gl', keyChain standardOutput = stdout errorOutput = stderr ignoreExitValue true } //noinspection GroovyAssignabilityCheck (stderr.toString().trim() =~ /password: '(.*)'/)[0][1] } 

像这样使用:

getPassword(currentUser,“Android_Store_Password”)

 /* Plugins */ apply plugin: 'com.android.application' /* Variables */ ext.currentUser = System.getenv("USER") ext.userHome = System.getProperty("user.home") ext.keystorePath = 'KEY_STORE_PATH' /* Signing Configs */ android { signingConfigs { release { storeFile file(userHome + keystorePath + project.name) storePassword getPassword(currentUser, "ANDROID_STORE_PASSWORD") keyAlias 'jaredburrows' keyPassword getPassword(currentUser, "ANDROID_KEY_PASSWORD") } } buildTypes { release { signingConfig signingConfigs.release } } } 

这是我如何做到的。 使用环境variables

  signingConfigs { release { storeFile file(System.getenv("KEYSTORE")) storePassword System.getenv("KEYSTORE_PASSWORD") keyAlias System.getenv("KEY_ALIAS") keyPassword System.getenv("KEY_PASSWORD") } 

最简单的方法是创build一个~/.gradle/gradle.properties文件。

 ANDROID_STORE_PASSWORD=hunter2 ANDROID_KEY_PASSWORD=hunter2 

然后你的build.gradle文件可以像这样:

 android { signingConfigs { release { storeFile file('yourfile.keystore') storePassword ANDROID_STORE_PASSWORD keyAlias 'youralias' keyPassword ANDROID_KEY_PASSWORD } } buildTypes { release { signingConfig signingConfigs.release } } } 

接受的答案使用文件来控制哪个密钥库用于签署驻留在项目的同一根文件夹中的APK。 当我们使用像Git一样的vcs时,当我们忘记添加属性文件来忽略列表时,可能是一件坏事。 因为我们会向世界透露我们的密码。 问题依然存在。

取而代之的是在我们的项目中的同一个目录中创build属性文件,我们应该在外面做。 我们通过使用gradle.properties文件来完成它。

这里的步骤:

1.在你的根项目上编辑或者创buildgradle.properties并添加下面的代码,记得用自己的编辑path:

 AndroidProject.signing=/your/path/androidproject.properties 

2.在/ your / path /中创buildandroidproject.properties,并添加如下代码,不要忘记将/your/path/to/android.keystore更改为你的密钥库path:

 STORE_FILE=/your/path/to/android.keystore STORE_PASSWORD=yourstorepassword KEY_ALIAS=yourkeyalias KEY_PASSWORD=yourkeypassword 

3.在您的应用程序模块build.gradle(而不是您的项目根build.gradle)添加下面的代码,如果不存在或调整:

 signingConfigs { release } buildTypes { debug { debuggable true } release { minifyEnabled true proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' signingConfig signingConfigs.release } } 

4.在步骤3中的代码下面添加以下代码:

 if (project.hasProperty("AndroidProject.signing") && new File(project.property("AndroidProject.signing").toString()).exists()) { def Properties props = new Properties() def propFile = new File(project.property("AndroidProject.signing").toString()) if(propFile.canRead()) { props.load(new FileInputStream(propFile)) if (props!=null && props.containsKey('STORE_FILE') && props.containsKey('STORE_PASSWORD') && props.containsKey('KEY_ALIAS') && props.containsKey('KEY_PASSWORD')) { android.signingConfigs.release.storeFile = file(props['STORE_FILE']) android.signingConfigs.release.storePassword = props['STORE_PASSWORD'] android.signingConfigs.release.keyAlias = props['KEY_ALIAS'] android.signingConfigs.release.keyPassword = props['KEY_PASSWORD'] } else { println 'androidproject.properties found but some entries are missing' android.buildTypes.release.signingConfig = null } } else { println 'androidproject.properties file not found' android.buildTypes.release.signingConfig = null } } 

此代码将从步骤1中searchgradle.properties中的AndroidProject.signing属性。 如果find属性,它会将属性值转换为指向我们在步骤2中创build的androidproject.properties的文件path。 然后从它的所有属性值将被用作我们的build.gradle的签名configuration。

现在我们不必再担心暴露密钥库密码的风险。

阅读更多签署安卓apk,而不是把build.gradle中的keystore信息

对于那些希望把他们的凭据放在一个外部的JSON文件中,并从Gradle中读取的,这就是我所做的:

MY_PROJECT / credentials.json:

 { "android": { "storeFile": "/path/to/acuity.jks", "storePassword": "your_store_password", "keyAlias": "your_android_alias", "keyPassword": "your_key_password" } } 

MY_PROJECT /安卓/应用/的build.gradle

 // ... signingConfigs { release { def credsFilePath = file("../../credentials.json").toString() def credsFile = new File(credsFilePath, "").getText('UTF-8') def json = new groovy.json.JsonSlurper().parseText(credsFile) storeFile file(json.android.storeFile) storePassword = json.android.storePassword keyAlias = json.android.keyAlias keyPassword = json.android.keyPassword } ... buildTypes { release { signingConfig signingConfigs.release //I added this // ... } } } // ... } 

可以使用任何现有的Android Studio gradle项目,并从命令行编译/签名,无需编辑任何文件。 这使得在版本控制中存储项目非常好,同时保持您的密钥和密码分开,而不是在您的build.gradle文件中:

 ./gradlew assembleRelease -Pandroid.injected.signing.store.file=$KEYFILE -Pandroid.injected.signing.store.password=$STORE_PASSWORD -Pandroid.injected.signing.key.alias=$KEY_ALIAS -Pandroid.injected.signing.key.password=$KEY_PASSWORD 

您可以从命令行请求密码:

 ... signingConfigs { if (gradle.startParameter.taskNames.any {it.contains('Release') }) { release { storeFile file("your.keystore") storePassword new String(System.console().readPassword("\n\$ Enter keystore password: ")) keyAlias "key-alias" keyPassword new String(System.console().readPassword("\n\$ Enter keys password: ")) } } else { //Here be dragons: unreachable else-branch forces Gradle to create //install...Release tasks. release { keyAlias 'dummy' keyPassword 'dummy' storeFile file('dummy') storePassword 'dummy' } } } ... buildTypes { release { ... signingConfig signingConfigs.release } ... } ... 

此答案以前出现: https : //stackoverflow.com/a/33765572/3664487