Подписать 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 } } } 

Он работает отлично, но я не должен помещать значения для storePassword и keyPassword в мой репозиторий. Я бы предпочел не размещать там storeFile и keyAlias .

Есть ли способ изменить build.gradle чтобы он получал пароли из какого-то внешнего источника (например, файл, который находится только на моем компьютере)?

И, конечно же, измененный build.gradle должен использоваться на любом другом компьютере (даже если компьютер не имеет доступа к паролям).

Я использую Android Studio и Mac OS X Maverics, если это имеет значение.

Solutions Collecting From Web of "Подписать APK без размещения информации о хранилище ключей в build.gradle"

Самое приятное в Groovy заключается в том, что вы можете свободно смешивать Java-код, и его довольно легко прочитать в файле key / value с помощью java.util.Properties . Возможно, есть еще более простой способ использования идиоматического Groovy, но Java все еще довольно прост.

Создайте файл keystore.properties (в этом примере в корневом каталоге вашего проекта рядом с settings.gradle , хотя вы можете поместить его в любом месте:

 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'] } } } 

В качестве альтернативы, если вы хотите применить ответ Скотта Барты таким образом, который больше похож на автоматически сгенерированный код градиента, вы можете создать файл keystore.properties в корневой папке проекта:

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

И измените свой код градиента на:

 // 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 для хранения ваших паролей.

Как добавить пароль в Keychain Access

Затем в ваших сценариях градиента:

 /* 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 } } } 

Вот как я это делаю. Использовать переменные среды

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

Самый простой способ – создать файл ~/.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, который находится в одной корневой папке проекта. Когда мы используем vcs, например Git , может быть плохо, когда мы забываем добавить файл свойств в список игнорирования. Потому что мы раскроем наш пароль миру. Проблемы все еще сохраняются.

Вместо того, чтобы делать файл свойств в том же каталоге в нашем проекте, мы должны выйти за его пределы. Мы делаем это снаружи, используя файл gradle.properties.

Здесь шаги:

1. Измените или создайте gradle.properties в своем корневом проекте и добавьте следующий код, не забудьте отредактировать путь со своим собственным:

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

2. Создайте androidproject.properties в / your / path / и добавьте к нему следующий код, не забудьте изменить /your/path/to/android.keystore на ваш путь к хранилищу ключей:

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

3. В вашем модуле app 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 } } 

Этот код будет искать свойство AndroidProject.signing в gradle.properties с шага 1 . Если свойство найдено, оно переведет значение свойства как путь к файлу, указывающий на androidproject.properties, который мы создаем на шаге 2 . Тогда все значение свойства из него будет использоваться в качестве подписи для нашего build.gradle.

Теперь нам не нужно снова беспокоиться о риске разоблачения нашего пароля хранилища ключей.

Подробнее о подписке Android apk, не добавляя информацию о хранилище в build.gradle

Для тех, кто хочет поместить свои учетные данные во внешний файл JSON и прочитать, что из градиента это то, что я сделал:

my_project / credentials.json:

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

my_project / Android / приложение / 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 // ... } } } // ... } 

Вы можете запросить пароли из командной строки:

 ... 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