Configurações de assinatura com gradle android

Aplicativos de assinatura

  • Os aplicativos Android precisam ser assinados digitalmente com um certificado antes da instalação

  • O Android identifica o autor do aplicativo usando este certificado,

  • Este certificado não precisa ser assinado por uma autoridade de certificação (você pode usar um certificado autoassinado)

  • Existem dois tipos de modos de assinatura debug modeerelease mode

  • No modo de depuração, você assina seu aplicativo com um certificado de depuração gerado pelas ferramentas do Android SDK. Este certificado tem uma chave privada com uma senha conhecida

  • Este certificado está localizado em $HOME/.android/debug.keystore

  • No modo de liberação, você assina o aplicativo com seu próprio certificado (na verdade, você deve gerar seu próprio armazenamento de chaves)

  • Mais informações sobre como assinar o aplicativo Android
    http://developer.android.com/tools/publishing/app-signing.html

Configuração de assinatura

  • Em gradleprojetos baseados em Android, a configuração de assinatura deve ser especificada nos scripts de compilação do Gradle

  • A seguir estão os detalhes que precisam ser especificados no script de compilação do Gradle

  1. keystore (localização)
  2. senha do keystore
  3. nome de alias da chave
  4. senha chave
  5. O tipo de loja
  • Na versão de depuração, você não precisa especificar nenhum desses detalhes, ele obtém automaticamente os detalhes do certificado de depuração

  • Mas o sistema de construção não assina a versão de lançamento, a menos que você defina explicitamente uma configuração de assinatura para a construção, portanto, no tipo de lançamento, você deve especificar os detalhes acima no arquivo de construção do gradle

  • O restante deste artigo fornece informações detalhadas sobre como especificar a configuração de assinatura de versão

Estrutura de diretório

  • A seguir está a estrutura do meu projeto

Cenário

  • Tenho um senzaplicativo em Scoreprojeto, estou definindo configurações de assinatura em arquivo no aplicativo (uma vez que é meu aplicativo principal)build.gradlesenz

Basta definir as configurações de assinatura de versão

  • Lançamento da primeira cópia no aplicativokey-storesenz

Cenário

  • Em seguida, defina os detalhes do armazenamento de chaves no arquivo (é necessário adicionar na seção no arquivo de compilação)build.gradleandroid
android {
...
signingConfigs
{
release
{
storeFile file
("release-key.keystore")
storePassword
'passwotd'
keyAlias
'alias'
keyPassword
'password'
}
}

buildTypes
{
release
{
...
signingConfig signingConfigs
.release
}

debug
{
debuggable
true
}
}
}
...
  • Agora execute o seguinte comando na linha de comando
./gradlew assembleRelease
  • Ele irá gerar o apk de lançamento – Score/senz/build/apk/senz-release.apk

  • Na configuração de assinatura acima, defini todos os armazenamentos de chaves e senhas de chaves em meu arquivo gradle, não é uma boa prática de segurança

  • Para resolver o problema de segurança, você pode especificar o prompt do processo de construção para essas senhas (se você estiver construindo a partir da linha de comando)

Senha de prompt com arquivo de compilação do Gradle

  • Você pode obter as senhas de System.console()
storePassword System.console().readLine("\nKeystore password: ")
keyPassword
System.console().readLIne("\nKey password: ")
  • Portanto, o arquivo de compilação seria semelhante a abaixo
android {
...
signingConfigs
{
release
{
storeFile file
("release-key.keystore")
storePassword
System.console().readLine("\nKeystore password: ")
keyAlias
'alias'
keyPassword
System.console().readLIne("\nKey password: ")
}
}
...
}
...
  • Quando você compila a partir da linha de comando, ele solicitará as senhas

Cenário

  • Existem vários problemas com esta abordagem também

Problema 1 – A senha será solicitada sempre

  • Esta senha será solicitada sempre,

  • Por exemplo, se você limpar o build , ele pedirá uma senha./gradlew clean

Cenário

gradle.taskGraph.whenReady { taskGraph ->
if(taskGraph.hasTask(':senz:assembleRelease')) {
password
= System.console().readPassword("\nEnter password: ")
password
= new String(password)

if(password.size() <= 0) {
throw new InvalidUserDataException("Empty password")
}

// set signing config key passwords
android
.signingConfigs.release.storePassword = password
android
.signingConfigs.release.keyPassword = password
}
}

android
{
...
signingConfigs
{
release
{
storeFile file
("release-key.keystore")
storePassword
''
keyAlias
'alias'
keyPassword
''
}
}
...
}
  • Isso pedirá apenas uma senha assembleReleasee atribuirá a senha em senhas de configuração de assinatura (estou usando uma senha para armazenamento de chaves e chave, então posso ter a mesma senha para ambos os valores)

Cenário

  • Neste código que estamos usando em vez de , functions retorna uma matriz char. Portanto, é necessário convertê-lo em String, caso contrário, a construção falharáSystem.console().readPassword()readLine()readPassword()

  • SignConfigs.release senhas definidas como vazias, uma vez que as lemos via taskGraph

android {
...
signingConfigs
{
release
{
storeFile file
("release-key.keystore")
storePassword
''
keyAlias
'alias'
keyPassword
''
}
}
...
}

Problema 2 – Sem console

  • Se você executar a compilação acima no Android Studio, não houver System.console (), ele retornará nulo

  • Portanto, a compilação falhará no AndroidStudio

  • Aqui, em vez de obter a senha do console, podemos solicitá-la na caixa de diálogo quando não tiver o console (na verdade, ao executar a versão do AndroidStudio)

  • O código a seguir fará isso por meio de Groovy SwingBuilder

import groovy.swing.SwingBuilder

...

gradle
.taskGraph.whenReady { taskGraph ->
if(taskGraph.hasTask(':senz:assembleRelease')) {
def password = ""

if (System.console() == null) {
new SwingBuilder().edt {
dialog
(modal: true,
title
: "Enter password",
alwaysOnTop
: true,
resizable
: false,
locationRelativeTo
: null,
pack
: true,
show
: true
) {
vbox
{
label
(text: "Enter password: ")
input
= passwordField()
button
(defaultButton: true,
text
: 'OK',
actionPerformed
: {
password
= input.password;
dispose
();
})
}
}
}
} else {
password
= System.console().readPassword("\nEnter password: ")
password
= new String(password)
}

if (password.size() <= 0) {
throw new InvalidUserDataException("Empty password")
}
}
}

android
{

...

}
Error:(10) java.awt.AWTError: Toolkit not found: apple.awt.CToolkit
> Toolkit not found: apple.awt.CToolkit

Referência

  1. http://developer.android.com/sdk/installing/studio-build.html
  2. http://developer.android.com/tools/publishing/app-signing.html
  3. http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Signing-Configurations
  4. https://www.timroes.de/2013/09/22/handling-signing-configs-with-gradle/
  5. https://www.timroes.de/2014/01/19/using-password-prompts-with-gradle-build-files/
  6. http://gmariotti.blogspot.com/2013/10/common-tips-about-gradle.html