(Andypott/iStock) Fonte: https://bit.ly/3bBGcwy

Publicando sua biblioteca Android no GitHub Packages

Nelson Glauber
6 min readApr 24, 2020

--

Estou devendo esse post a mim mesmo há um bom tempo. Desde quando escrevi a primeira edição do meu livro, um dos leitores sugeriu que eu colocasse uma seção demonstrando como publicar bibliotecas de modo que elas fossem acessíveis a outros desenvolvedores.

Acabei esquecendo desse assunto. Mas recentemente trabalhei em um projeto em que cada grande feature era separada em um repositório à parte, e para isso é usado o JFrog. Mas como já usamos o GitHub, surgiu então possibilidade de utilizar o GitHub Packages. Fiz o teste e achei bem mais simples de configurar do que no JFrog e resolvi compartilhar aqui.

Esse post foi praticamente uma tradução do post original de Prasad Pulikal que originalmente eu encontrei aqui.

Publicando sua biblioteca

Estou partindo do pressuposto que você (ou sua empresa) já possui uma conta no GitHub e sua biblioteca Android já está em um repositório do GitHub. Se quiser saber mais sobre como criar uma biblioteca Android, dê uma olhada nesse link.

Passo 1

A primeira coisa que deve ser feita é gerar uma chave para publicar sua biblioteca. Para isso, acesse sua conta no GitHub e vá até a opção Settings. Em seguida, selecione Developer Settings. Agora clique em Personal Access Tokens e pressione o botão Generate New Token.

Insira uma nota informando para que essa chave será utilizada. Esse campo é livre, mas de preenchimento obrigatório. Agora certifique-se de ter selecionado os escopos read:packages e write:packages.

Configurando o access token para publicar a biblioteca no GitHub packages.

Por fim, clique em Generate Token. Quando o token for gerado, certifique-se de copiá-lo, pois ele não poderá ser mostrado novamente. Se você o perder, terá que gerar um novo token.

Passo 2

Agora devemos fazer as configurações no projeto da biblioteca que será publicada. Crie o arquivo github.properties na raiz do seu projeto e deixe-o como a seguir:

gpr.usr=SEU_USUARIO_NO_GITHUB
gpr.key=chave_gerada_no_passo_anterior

Se o repositório dessa biblioteca for público, assegure-se de adicionar esse arquivo no seu .gitignore.

Agora faça os seguintes ajustes no build.gradle do módulo da biblioteca que você deseja publicar.

apply plugin: 'maven-publish' 
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'

def githubProperties = new Properties()
githubProperties.load(
new FileInputStream(rootProject.file("github.properties"))
)

def getVersionName = { ->
return "1.0.2"
}

def getArtifactId = { ->
return "mylib"
}


android { ... }

dependencies { ... }

publishing {
publications {
mylib(MavenPublication) {
groupId 'br.com.nglauber'
artifactId getArtifactId()
version getVersionName()
artifact("$buildDir/outputs/aar/${getArtifactId()}-release.aar")
}
}

repositories {
maven {
name = "GitHubPackages"
url = uri("https://maven.pkg.github.com/nglauber/mylib")
credentials {
username = githubProperties['gpr.usr'] ?: System.getenv("GPR_USER")
password = githubProperties['gpr.key'] ?: System.getenv("GPR_API_KEY")
}
}
}
}

Na primeira linha estamos aplicando o plugin maven-publish para publicar a biblioteca a partir da linha de comando. Em seguida, a variável gradleProperties está sendo instanciada para armazenar as propriedades declaradas no arquivo github.properties que criamos anteriormente. As funções getVersionName e getArtifactId retornam respectivamente a versão da biblioteca e o nome que será utilizado pelos clientes para identificá-la como dependência.

Na seção publishing é onde são declaradas as informações para a publicação da biblioteca. Perceba que no bloco publications foram utilizadas informações que obviamente você deve ajustar para a sua biblioteca:

  • A função mylib que deve ser o mesmo nome do módulo da sua biblioteca;
  • Em groupId, use seu domínio da sua empresa invertido, ou caso não tenha domínio, siga uma estratégia similar a que você utiliza para definir o application id de uma aplicação.
  • artifactId e version são obtidos por meio das funções getArtifactId e getVersionName declaradas anteriormente.
  • Perceba que na função artifact está sendo utilizado o arquivo *.aar no modo release. Para que esse arquivo seja gerado, certifique de escolher esse build variant na opção View > Tool Windows > Build Variants do Android Studio.
Escolhendo a build de release no Android Studio.

Já na seção repositories, no bloco maven, temos:

  • Na URL onde a sua biblioteca será publicada, certifique-se de indicar corretamente o usuário ou empresa (no lugar de nglauber) e o repositório (no lugar de mylib);
  • No bloco credentials, obtemos o usuário e a chave do GitHub por meio do arquivo github.properties. Mas perceba que caso esse arquivo não exista, está sendo utilizadas as variáveis de ambiente GPR_USER e GPR_API_KEY.

Compile sua biblioteca e se tudo correr bem, podemos passar para o último passo: a publicação.

Passo 3

A publicação da biblioteca exige apenas a digitação do seguinte comando no terminal.

./gradlew publish

Se tudo correr bem, sua biblioteca já aparecerá no GitHub. 🎉

Biblioteca disponibilizada no GitHub packages.

É importante ressaltar que as dependências da biblioteca não são incluídas automaticamente. Em repositórios Maven, as dependências são obtidas a partir do arquivo *.pom. O código abaixo adiciona as dependências da lib no arquivo pom da biblioteca para que suas dependências (também chamadas de "dependências transitivas") sejam baixadas automaticamente por quem utilizar a biblioteca.

publishing {
publications {
mylib(MavenPublication) {
groupId 'br.com.nglauber'
artifactId getArtifactId()
version getVersionName()
artifact("$buildDir/outputs/aar/${getArtifactId()}-release.aar")
pom.withXml { // adding transitive dependencies...
final dependenciesNode = asNode().appendNode('dependencies')
ext.addDependency = { Dependency dep, String scope ->
if (dep.group == null || dep.version == null ||
dep.name == null || dep.name == "unspecified")
return
final dependencyNode = dependenciesNode
.appendNode('dependency')
dependencyNode.appendNode('groupId', dep.group)
dependencyNode.appendNode('artifactId', dep.name)
dependencyNode.appendNode('version', dep.version)
dependencyNode.appendNode('scope', scope)
if (!dep.transitive) {
final exclusionNode = dependencyNode
.appendNode('exclusions')
.appendNode('exclusion')
exclusionNode.appendNode('groupId', '*')
exclusionNode.appendNode('artifactId', '*')
} else if (!dep.properties.excludeRules.empty) {
final exclusionNode = dependencyNode
.appendNode('exclusions')
.appendNode('exclusion')
dep.properties.excludeRules.each { ExcludeRule rule ->
exclusionNode.appendNode(
'groupId', rule.group ?: '*')
exclusionNode.appendNode(
'artifactId', rule.module ?: '*')
}
}
} // end addDependency
configurations.compile.getDependencies().each { dep ->
addDependency(dep, "compile")
}
configurations.api.getDependencies().each { dep ->
addDependency(dep, "compile")
}
configurations.implementation.getDependencies().each {dep ->
addDependency(dep, "runtime")
}
} // end pomWithXml
}
// myLib
}
// publications
repositories {
...
}
} // publishing

Resumidamente, o bloco pom.withXml itera sobre as dependências da biblioteca e faz um parser para modificar o arquivo pom. Esse arquivo, contendo as dependências, pode ser visualizado no diretório SUA_LIB/build/publications/SUA_LIB/pom-default.xml. E após a publicação é possível verificar no GitHub que essas dependências foram incluídas.

Dependências e arquivo *.pom no GitHub

Utilizando sua biblioteca

Para utilizar a biblioteca de um repositório público, é bem simples. Basta adicionar o repositório no build.gradle e declarar a dependência.

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'

android { ... }

repositories {
maven {
name = "GitHubPackages"
url = uri("https://maven.pkg.github.com/nglauber/mylib")
}
}

dependencies {
...

implementation 'br.com.nglauber:mylib:1.0.2'
}

Caso seja um repositório privado, o usuário que quiser consumir a biblioteca deverá ter acesso ao repositório e gerar uma chave pessoal conforme foi mostrado anteriormente. Em seguida, no build.gradle, deve-se adicionar as credenciais.

def githubProperties = new Properties()
githubProperties.load(
new FileInputStream(rootProject.file("github.properties"))
)

repositories {
maven {
name = "GitHubPackages"
url = uri("https://maven.pkg.github.com/nglauber/mylib")
credentials {
username = githubProperties['gpr.usr'] ?: System.getenv("GPR_USER")
password = githubProperties['gpr.key'] ?: System.getenv("GPR_API_KEY")
}
}
}

Lembrando mais uma vez, que o arquivo github.properties é opcional. Você pode usar variáveis de ambiente.

Espero que gostem.

4br4ç05,
nglauber

--

--

Nelson Glauber

Android Developer. Google Developer Expert for Android/Kotlin. Author of “Dominando o Android”.