Подпишите APK, не помещая информацию о хранилище ключей в сборку.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, если это имеет значение.

10 109

10 ответов:

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

создать keystore.properties file (в этом примере в корневом каталоге вашего проекта рядом с 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']
        }
    }
}

кроме того, если вы хотите применить ответ Скотта Барты более похожим на автоматически сгенерированный код gradle, вы можете создать keystore.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, и вы также можете изменить этот код, чтобы иметь несколько наборов свойств для различных хранилищ ключей и псевдонимов ключей.

самый простой способ создать .

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

прочитав несколько ссылок:

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

Так как вы используете Mac OSX, вы можете использовать Keychain Access для хранения паролей.

How to add password in 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
        }
    }
}

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

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

принято отвечать использовать файл который ключей для подписи APK, который находится в той же корневой папке проекта. Когда мы используем vcs как Git, может быть плохо, когда мы забываем добавить файл свойств в игнор лист. Потому что мы раскроем наш пароль всему миру. Проблемы все еще сохраняются.

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

вот шаги:

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

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

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

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

3.In сборка модуля вашего приложения.gradle (не ваша корневая сборка проекта.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.подписание свойства в gradle.свойства С Шаг 1. Если свойство найдено, оно будет переводить значение свойства как путь к файлу, который указывает на androidproject.свойства, которые мы создаем в Шаг 2. Тогда все значение свойства из него будет использоваться как конфигурация подписи для нашей сборки.градля.

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

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

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

на my_project/учетные данные.json:

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

my_project/android/app / 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
                // ...
            }
        }
    }
// ...
}

причина, по которой я выбрал .json тип файла, а не .properties тип файла (как и в принятом ответе), потому что я хотел также хранить другие данные (другие пользовательские свойства, которые мне нужны) в том же файле (my_project/credentials.json), и по-прежнему есть gradle анализировать информацию о подписи из этого файла, а также.

можно взять любой существующий проект Android Studio gradle и построить/подписать его из командной строки без редактирования каких-либо файлов. Это делает его очень хорошим для хранения вашего проекта в системе управления версиями, сохраняя ваши ключи и пароли отдельно, а не в вашей сборке.файл 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

этот вопрос получил много правильных ответов, но я хотел поделиться своим кодом, который может быть полезен для мейнтейнеров библиотека, потому что оставляет оригиналы build.gradle довольно чистый!--12-->.

добавить папку в каталог модуля, который я gitignore. Выглядит это так:

/signing
    /keystore.jks
    /signing.gradle
    /signing.properties

keystore.jks и signing.properties должны быть понятны. И signing.gradle выглядит так:

def propsFile = file('signing/signing.properties')
def buildType = "release"

if (!propsFile.exists()) throw new IllegalStateException("signing/signing.properties file missing")

def props = new Properties()
props.load(new FileInputStream(propsFile))

def keystoreFile = file("signing/keystore.jks")
if (!keystoreFile.exists()) throw new IllegalStateException("signing/keystore.jks file missing")

android.signingConfigs.create(buildType, {
    storeFile = keystoreFile
    storePassword = props['storePassword']
    keyAlias = props['keyAlias']
    keyPassword = props['keyPassword']
})

android.buildTypes[buildType].signingConfig = android.signingConfigs[buildType]

и оригинал build.gradle

apply plugin: 'com.android.application'
if (project.file('signing/signing.gradle').exists()) {
    apply from: 'signing/signing.gradle'
}

android {
    compileSdkVersion 27
    defaultConfig {
        applicationId ...
    }
}

dependencies {
    implementation ...
}

как вы можете видеть, Вам не нужно указывать типы зданий вообще, если пользователь имеет доступ к действительному signing каталог, он просто помещает его в модуль, и он может создать действительное подписанное приложение для выпуска, иначе оно просто работает для него, как обычно.

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

...

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