Vamos considerar que você já desenvolveu seu aplicativo matador, que vai te gerar milhões de reais em 2 dias, e agora vai gerar a sua build de release para publicar no Google Play. Nesse caso, precisamos criar a nossa assinatura de release no arquivo build.gradle do nosso projeto. Alguma coisa mais ou menos assim:
signingConfigs { release { storeFile file('/home/rafael/minha_key.jks') storePassword 'senha secreta' keyAlias 'app_android' keyPassword 'senha mais secreta ainda' } }
Mas… tem alguma coisa errada aí. Principalmente se estamos utilizando algum controle de versão, como o Git ou SVN, não é uma boa prática enviarmos dados sensíveis para eles (como senhas, keystores e coisas do tipo). Durante algum tempo, a saída utilizada por mim foi adicionar esses dados ao arquivo gradle.properties na raiz do projeto, e não enviá-lo para o controle de versão.
STORE_FILE=/home/rafael/minha_key.jks STORE_PASSWORD=senha secreta KEY_ALIAS=app_android KEY_PASSWORD=senha mais secreta ainda
Dessa forma, a nossa configuração de assinatura ficaria algo assim:
signingConfigs { release { storeFile file(STORE_FILE) storePassword STORE_PASSWORD keyAlias KEY_ALIAS keyPassword KEY_PASSWORD } }
Funciona bem, não temos dados sensíveis no nosso controle de versão. Mas… temos basicamente dois problemas principais nessa abordagem:
- No clone do projeto, você terá um erro de build. Ou seja, se entrar alguém na equipe e clonar o projeto, baterá com a cara na porta logo de cara. Isso já vai atrasar um pouco o join no projeto. Esse problema também se aplica quando o código está em um servidor de CI (Jenkins, Travis, CircleCI etc.);
- Tem o agravante humano, ou seja, sempre há o risco de, sem querer, você enviar o arquivo original por algum motivo. Obviamente que você pode adicionar esse arquivo ao .gitignore ou equivalente no SVN, mas nesse caso caímos no primeiro cenário problemático.
Então… qual a saída?
Depois de pensar um pouco, acabei encontrando a melhor saída com o uso de variáveis de ambiente! Como assim?
Vamos lá: o primeiro passo é criarmos uma assinatura default para o projeto. No meu caso, eu simplesmente copio a debug.keystore (que fica dentro da pasta .android do usuário) e coloco, por exemplo, dentro de um diretório chamado distribution na raiz do meu projeto. Essa chave vai garantir que a build não vai quebrar quando alguém clonar o projeto ou em um servidor de CI, por exemplo, em um primeiro momento.
Agora, na configuração da minha assinatura, podemos fazer algo do tipo:
signingConfigs { release { storeFile file(System.getenv('STORE_FILE') != null ? System.getenv('STORE_FILE') : '../distribution/debug.keystore') storePassword System.getenv('STORE_PASSWORD') != null ? System.getenv('STORE_PASSWORD') : 'android' keyAlias System.getenv('KEY_ALIAS') != null ? System.getenv('KEY_ALIAS') : 'androiddebug' keyPassword System.getenv('KEY_PASSWORD') != null ? System.getenv('KEY_PASSWORD') : 'android' } }
Nota: caso seu servidor de CI esteja gerando builds de release, você pode setar as variáveis de ambiente nele também para gerar builds assinadas corretamente.
E pronto! Agora, para gerar a build corretamente, você pode exportar as variáveis de ambiente ou, como eu faço, colocar os dados da chave no comando apenas na hora de gerar a build de release:
$ STORE_FILE='/home/rafael/minha_key.jks' STORE_PASSWORD='senha secreta' KEY_ALIAS='app_android' KEY_PASSWORD='senha mais secreta ainda' ./gradlew clean assembleRelease
E é isso! Espero que a dica seja útil para vocês e, caso tenham sugestões, podem postar aí nos comentários =). Até a próxima!
***
Artigo originalmente publicado no blog pessoal do autor. Veja aqui.