DEV Community

Akshay
Akshay

Posted on

How to Publish an Android Library to Maven Central Using Sonatype Central Portal

Publishing an Android library to Maven Central is one of the most important steps if you want developers to use your library professionally.

Once your library is available on Maven Central, users can install it directly using:

implementation 'io.github.yourusername:yourlibrary:1.0.0'
Enter fullscreen mode Exit fullscreen mode

In this guide, we will publish an Android library to Maven Central using:

  • Gradle
  • maven-publish
  • GPG signing
  • Sonatype Central Portal
  • Manual Central Portal bundle upload
  • A PowerShell script for creating the upload bundle

This guide focuses only on the complete library publishing flow.


Final Publishing Flow

The complete flow looks like this:

Android Library Project
        ↓
Gradle Maven Publish
        ↓
Signed Maven Local Artifacts
        ↓
Central Portal Bundle ZIP
        ↓
Upload to Maven Central
        ↓
Library Available for Users
Enter fullscreen mode Exit fullscreen mode

Step 1: Prepare Your Library Details

In your Android library module, define your Maven publishing information.

Example library build.gradle version:

ext {
    PUBLISH_GROUP_ID = 'io.github.yourusername'
    PUBLISH_VERSION = '1.0.0'
    PUBLISH_ARTIFACT_ID = 'yourlibrary'

    PUBLISH_DESCRIPTION = 'yourLibrary description'
    PUBLISH_URL = 'https://github.com/yourUsername/yourLibraryName'

    PUBLISH_LICENSE_NAME = 'Apache License'
    PUBLISH_LICENSE_URL = 'https://github.com/yourUsername/yourLibraryName/blob/master/LICENSE'

    PUBLISH_DEVELOPER_ID = 'yourUsername'
    PUBLISH_DEVELOPER_NAME = 'Your Name'
    PUBLISH_DEVELOPER_EMAIL = 'youremail@example.com'

    PUBLISH_SCM_CONNECTION = 'scm:git:github.com/yourUsername/yourLibraryName.git'
    PUBLISH_SCM_DEVELOPER_CONNECTION = 'scm:git:ssh://github.com/yourUsername/yourLibraryName.git'
    PUBLISH_SCM_URL = 'https://github.com/yourUsername/yourLibraryName/tree/master'
}
Enter fullscreen mode Exit fullscreen mode

Example library build.gradle.kts version:

extra.apply {
    set("PUBLISH_GROUP_ID", "io.github.yourusername")
    set("PUBLISH_VERSION", "1.0.0")
    set("PUBLISH_ARTIFACT_ID", "yourlibrary")

    set("PUBLISH_DESCRIPTION", "Smart Android network monitoring and offline retry toolkit for Java and Kotlin apps.")
    set("PUBLISH_URL", "https://github.com/tutorialsandroid/yourlibrary")

    set("PUBLISH_LICENSE_NAME", "Apache License")
    set("PUBLISH_LICENSE_URL", "https://github.com/tutorialsandroid/yourlibrary/blob/main/LICENSE")

    set("PUBLISH_DEVELOPER_ID", "tutorialsandroid")
    set("PUBLISH_DEVELOPER_NAME", "Akshay Masram")
    set("PUBLISH_DEVELOPER_EMAIL", "akshaysunilmasram@yahoo.com")

    set("PUBLISH_SCM_CONNECTION", "scm:git:github.com/tutorialsandroid/yourlibrary.git")
    set("PUBLISH_SCM_DEVELOPER_CONNECTION", "scm:git:ssh://github.com/tutorialsandroid/yourlibrary.git")
    set("PUBLISH_SCM_URL", "https://github.com/tutorialsandroid/yourlibrary/tree/main")
}
Enter fullscreen mode Exit fullscreen mode

For your own library, update:

PUBLISH_GROUP_ID
PUBLISH_VERSION
PUBLISH_ARTIFACT_ID
PUBLISH_DESCRIPTION
PUBLISH_URL
PUBLISH_DEVELOPER_NAME
PUBLISH_DEVELOPER_EMAIL
PUBLISH_SCM_URL
Enter fullscreen mode Exit fullscreen mode

Example final dependency:

implementation 'io.github.yourUsername:yourLibraryName:1.0.0'
Enter fullscreen mode Exit fullscreen mode

Step 2: Configure Root build.gradle

Android projects can use two Gradle styles.

Older projects usually use:

buildscript {
    repositories {
        google()
        mavenCentral()
        gradlePluginPortal()
    }

    dependencies {
        classpath 'com.android.tools.build:gradle:9.1.0'
    }
}

apply from: "${rootDir}/scripts/publish-root.gradle"
Enter fullscreen mode Exit fullscreen mode

New Android Studio projects usually use the modern plugins block with Version Catalog:

// Top-level build file where you can add configuration options common to all sub-projects/modules.

plugins {
    alias(libs.plugins.android.application) apply false
    alias(libs.plugins.android.library) apply false
}
Enter fullscreen mode Exit fullscreen mode

If your project already uses this new format, keep it as it is.

Then add this line below the plugins {} block:

apply(from = "${rootProject.projectDir}/scripts/publish-root.gradle")
Enter fullscreen mode Exit fullscreen mode

Your final root build.gradle should look like this:

// Top-level build file where you can add configuration options common to all sub-projects/modules.

plugins {
    alias(libs.plugins.android.application) apply false
    alias(libs.plugins.android.library) apply false
}

apply(from = "${rootProject.projectDir}/scripts/publish-root.gradle")
Enter fullscreen mode Exit fullscreen mode

This line loads publishing and signing credentials from:

local.properties
Enter fullscreen mode Exit fullscreen mode

The credentials include:

ossrhUsername=
ossrhPassword=
signing.keyId=
signing.password=
signing.secretKeyRingFile=
Enter fullscreen mode Exit fullscreen mode

If your project uses settings.gradle or settings.gradle.kts, make sure repositories are available there.

Example settings.gradle:

pluginManagement {
    repositories {
        google()
        mavenCentral()
        gradlePluginPortal()
    }
}

dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        google()
        mavenCentral()
        maven { url 'https://jitpack.io' }
    }
}

rootProject.name = 'YourProjectName'
include ':app'
include ':library'
Enter fullscreen mode Exit fullscreen mode

If you are using Version Catalog, your Android Gradle Plugin versions are usually defined in:

gradle/libs.versions.toml
Enter fullscreen mode Exit fullscreen mode

Example:

[versions]
agp = "9.1.0"

[plugins]
android-application = { id = "com.android.application", version.ref = "agp" }
android-library = { id = "com.android.library", version.ref = "agp" }
Enter fullscreen mode Exit fullscreen mode

Recommended structure:

root build.gradle           -> applies common scripts
settings.gradle             -> manages repositories
libs.versions.toml          -> manages plugin/dependency versions
library/build.gradle        -> configures Android library and Maven publishing
scripts/publish-root.gradle -> loads credentials
scripts/publish-module.gradle -> creates Maven publication
Enter fullscreen mode Exit fullscreen mode

Step 3: Configure Gradle Wrapper

Open:

gradle/wrapper/gradle-wrapper.properties
Enter fullscreen mode Exit fullscreen mode

Use a Gradle version compatible with your Android Gradle Plugin.

Example:

distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-9.4.1-all.zip
Enter fullscreen mode Exit fullscreen mode

Step 4: Configure library/build.gradle

Now configure your Android library module.

Example library/build.gradle:

apply plugin: 'com.android.library'

ext {
    PUBLISH_GROUP_ID = 'io.github.yourusername'
    PUBLISH_VERSION = '1.0.0'
    PUBLISH_ARTIFACT_ID = 'yourlibrary'

    PUBLISH_DESCRIPTION = 'yourLibrary description'
    PUBLISH_URL = 'https://github.com/yourUsername/yourLibraryName'

    PUBLISH_LICENSE_NAME = 'Apache License'
    PUBLISH_LICENSE_URL = 'https://github.com/yourUsername/yourLibraryName/blob/master/LICENSE'

    PUBLISH_DEVELOPER_ID = 'yourUsername'
    PUBLISH_DEVELOPER_NAME = 'Your Name'
    PUBLISH_DEVELOPER_EMAIL = 'youremail@example.com'

    PUBLISH_SCM_CONNECTION = 'scm:git:github.com/yourUsername/yourLibraryName.git'
    PUBLISH_SCM_DEVELOPER_CONNECTION = 'scm:git:ssh://github.com/yourUsername/yourLibraryName.git'
    PUBLISH_SCM_URL = 'https://github.com/yourUsername/yourLibraryName/tree/master'
}

android {
    namespace 'com.example.yourlibrary'

    compileSdk 35

    defaultConfig {
        minSdk 19
        targetSdk 34
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }

    publishing {
        singleVariant("release") {
            withSourcesJar()
            withJavadocJar()
        }
    }

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_11
        targetCompatibility JavaVersion.VERSION_11
    }

    lint {
        abortOnError false
    }
}

dependencies {
    implementation fileTree(include: ['*.jar'], dir: 'libs')

    implementation 'androidx.appcompat:appcompat:1.6.1'
    implementation 'com.google.android.material:material:1.12.0'

    implementation 'com.github.bumptech.glide:glide:4.16.0'
    annotationProcessor 'com.github.bumptech.glide:compiler:4.16.0'
}

apply from: "${rootProject.projectDir}/scripts/publish-module.gradle"
Enter fullscreen mode Exit fullscreen mode

Example library/build.gradle.kts version:

plugins {
    alias(libs.plugins.android.library)
}

extra.apply {
    set("PUBLISH_GROUP_ID", "io.github.yourusername")
    set("PUBLISH_VERSION", "1.0.0")
    set("PUBLISH_ARTIFACT_ID", "yourlibrary")

    set("PUBLISH_DESCRIPTION", "Smart Android network monitoring and offline retry toolkit for Java and Kotlin apps.")
    set("PUBLISH_URL", "https://github.com/tutorialsandroid/yourlibrary")

    set("PUBLISH_LICENSE_NAME", "Apache License")
    set("PUBLISH_LICENSE_URL", "https://github.com/tutorialsandroid/yourlibrary/blob/main/LICENSE")

    set("PUBLISH_DEVELOPER_ID", "tutorialsandroid")
    set("PUBLISH_DEVELOPER_NAME", "Akshay Masram")
    set("PUBLISH_DEVELOPER_EMAIL", "akshaysunilmasram@yahoo.com")

    set("PUBLISH_SCM_CONNECTION", "scm:git:github.com/tutorialsandroid/yourlibrary.git")
    set("PUBLISH_SCM_DEVELOPER_CONNECTION", "scm:git:ssh://github.com/tutorialsandroid/yourlibrary.git")
    set("PUBLISH_SCM_URL", "https://github.com/tutorialsandroid/yourlibrary/tree/main")
}

android {
    namespace = "io.tutorialsandroid.yourlibrary"
    compileSdk {
        version = release(36) {
            minorApiLevel = 1
        }
    }

    defaultConfig {
        minSdk = 24

        testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
        consumerProguardFiles("consumer-rules.pro")
    }
    publishing {
        singleVariant("release") {
            withSourcesJar()
            withJavadocJar()
        }
    }
    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_11
        targetCompatibility = JavaVersion.VERSION_11
    }

}

dependencies {
    implementation(libs.appcompat)
    implementation(libs.material)
    testImplementation(libs.junit)
    androidTestImplementation(libs.espresso.core)
    androidTestImplementation(libs.ext.junit)
}
apply(from = "${rootProject.projectDir}/scripts/publish-module.gradle")
Enter fullscreen mode Exit fullscreen mode

The important publishing block is:

publishing {
    singleVariant("release") {
        withSourcesJar()
        withJavadocJar()
    }
}
Enter fullscreen mode Exit fullscreen mode

This generates:

AAR file
Sources JAR
Javadoc JAR
Enter fullscreen mode Exit fullscreen mode

These are required for a professional Maven Central release.


Step 5: Create scripts/publish-root.gradle

Create a scripts folder in your project root:

scripts/
    publish-root.gradle
    publish-module.gradle
Enter fullscreen mode Exit fullscreen mode

Now create:

scripts/publish-root.gradle
Enter fullscreen mode Exit fullscreen mode

Add this code:

ext["signing.keyId"] = ''
ext["signing.password"] = ''
ext["signing.secretKeyRingFile"] = ''

ext["ossrhUsername"] = ''
ext["ossrhPassword"] = ''

File secretPropsFile = project.rootProject.file('local.properties')

if (secretPropsFile.exists()) {
    Properties p = new Properties()

    new FileInputStream(secretPropsFile).withCloseable { is ->
        p.load(is)
    }

    p.each { name, value ->
        ext[name] = value
    }
} else {
    ext["ossrhUsername"] = System.getenv('OSSRH_USERNAME') ?: ''
    ext["ossrhPassword"] = System.getenv('OSSRH_PASSWORD') ?: ''

    ext["signing.keyId"] = System.getenv('SIGNING_KEY_ID') ?: ''
    ext["signing.password"] = System.getenv('SIGNING_PASSWORD') ?: ''
    ext["signing.secretKeyRingFile"] = System.getenv('SIGNING_SECRET_KEY_RING_FILE') ?: ''
}
Enter fullscreen mode Exit fullscreen mode

This script loads secret credentials from:

local.properties
Enter fullscreen mode Exit fullscreen mode

or from system environment variables.


Step 6: Create scripts/publish-module.gradle

Create this file:

scripts/publish-module.gradle
Enter fullscreen mode Exit fullscreen mode

Add this code:

apply plugin: 'maven-publish'
apply plugin: 'signing'

group = PUBLISH_GROUP_ID
version = PUBLISH_VERSION

afterEvaluate {
    publishing {
        publications {
            release(MavenPublication) {
                from components.release

                groupId = PUBLISH_GROUP_ID
                artifactId = PUBLISH_ARTIFACT_ID
                version = PUBLISH_VERSION

                pom {
                    packaging = 'aar'

                    name = PUBLISH_ARTIFACT_ID
                    description = PUBLISH_DESCRIPTION
                    url = PUBLISH_URL

                    licenses {
                        license {
                            name = PUBLISH_LICENSE_NAME
                            url = PUBLISH_LICENSE_URL
                        }
                    }

                    developers {
                        developer {
                            id = PUBLISH_DEVELOPER_ID
                            name = PUBLISH_DEVELOPER_NAME
                            email = PUBLISH_DEVELOPER_EMAIL
                        }
                    }

                    scm {
                        connection = PUBLISH_SCM_CONNECTION
                        developerConnection = PUBLISH_SCM_DEVELOPER_CONNECTION
                        url = PUBLISH_SCM_URL
                    }
                }
            }
        }
    }

    signing {
        required {
            gradle.taskGraph.allTasks.any { task ->
                task.name.toLowerCase().contains("publish")
            }
        }

        sign publishing.publications.release
    }
}

ext["signing.keyId"] = rootProject.ext["signing.keyId"]
ext["signing.password"] = rootProject.ext["signing.password"]
ext["signing.secretKeyRingFile"] = rootProject.ext["signing.secretKeyRingFile"]
Enter fullscreen mode Exit fullscreen mode

The most important line for Android libraries is:

packaging = 'aar'
Enter fullscreen mode Exit fullscreen mode

This tells Maven Central that the main artifact is an Android AAR library.


Step 7: Create Sonatype Central Portal Token

Go to:

https://central.sonatype.com
Enter fullscreen mode Exit fullscreen mode

Login to your Sonatype account. Create an account first if you do not already have one.

After login, open:

Account > User Token
Enter fullscreen mode Exit fullscreen mode

Generate a new user token.

You will get:

Username
Password
Enter fullscreen mode Exit fullscreen mode

These are not your normal login credentials. These are publishing token credentials.

Add them to your project root local.properties:

ossrhUsername=YOUR_TOKEN_USERNAME
ossrhPassword=YOUR_TOKEN_PASSWORD
Enter fullscreen mode Exit fullscreen mode

Your local.properties file should look like this:

## This file must NOT be checked into Version Control Systems,
# as it contains information specific to your local configuration.
#
# Location of the SDK. This is only used by Gradle.

sdk.dir=C\:\\Users\\HP-User1\\AppData\\Local\\Android\\Sdk

ossrhUsername=YOUR_TOKEN_USERNAME
ossrhPassword=YOUR_TOKEN_PASSWORD

signing.keyId=YOUR_SIGNING_KEY_ID
signing.password=YOUR_SIGNING_PASSWORD
signing.secretKeyRingFile=C\:\\Users\\HP-User1\\.gnupg\\secring.gpg
Enter fullscreen mode Exit fullscreen mode

Step 8: Create GPG Signing Key

Maven Central requires signed artifacts.

Install GPG on Windows using Gpg4win.

After installing, open Command Prompt or PowerShell and check if GPG is installed:

gpg --version
Enter fullscreen mode Exit fullscreen mode

If it shows the GPG version, then GPG is installed correctly.

Now create a new GPG key:

gpg --full-generate-key
Enter fullscreen mode Exit fullscreen mode

GPG will ask a few questions.

For key type, choose:

(1) RSA and RSA
Enter fullscreen mode Exit fullscreen mode

For key size, enter:

4096
Enter fullscreen mode Exit fullscreen mode

For expiry, you can enter:

0
Enter fullscreen mode Exit fullscreen mode

This means the key does not expire.

Then confirm:

y
Enter fullscreen mode Exit fullscreen mode

Now GPG will ask for your identity.

Example:

Real name: Your Name
Email address: youremail@example.com
Comment:
Enter fullscreen mode Exit fullscreen mode

You can leave the comment empty.

Then GPG will show something like:

You selected this USER-ID:
"Your Name <youremail@example.com>"
Enter fullscreen mode Exit fullscreen mode

Confirm it by entering:

O
Enter fullscreen mode Exit fullscreen mode

Now GPG will open a passphrase window.

Enter a strong password and repeat it.

Example:

Passphrase: YourStrongGpgPassword
Repeat: YourStrongGpgPassword
Enter fullscreen mode Exit fullscreen mode

This password protects your private signing key.

Later, the same password will be used in local.properties:

signing.password=YourStrongGpgPassword
Enter fullscreen mode Exit fullscreen mode

So remember this passphrase carefully. If you forget it, you cannot use that GPG key for signing.

After entering the passphrase, GPG may show this message:

We need to generate a lot of random bytes.
It is a good idea to perform some other action during the prime generation.
Enter fullscreen mode Exit fullscreen mode

At this time, move your mouse, type something, or use the system normally for a few seconds. This helps GPG generate randomness.

Once the key is created, list your secret keys:

gpg --list-secret-keys --keyid-format=short
Enter fullscreen mode Exit fullscreen mode

You will see something like:

sec   rsa4096/9D49CDF0
uid           [ultimate] Your Name <youremail@example.com>
Enter fullscreen mode Exit fullscreen mode

Here:

9D49CDF0
Enter fullscreen mode Exit fullscreen mode

is your GPG key ID.

Use this 8-character key ID in local.properties:

signing.keyId=9D49CDF0
Enter fullscreen mode Exit fullscreen mode

Now export the secret key ring file:

gpg --export-secret-keys -o C:\Users\HP-User1\.gnupg\secring.gpg
Enter fullscreen mode Exit fullscreen mode

This creates a file at:

C:\Users\HP-User1\.gnupg\secring.gpg
Enter fullscreen mode Exit fullscreen mode

This file will be used by Gradle for signing Maven artifacts.

Now upload your public key to a keyserver:

gpg --keyserver keyserver.ubuntu.com --send-keys 9D49CDF0
Enter fullscreen mode Exit fullscreen mode

Replace 9D49CDF0 with your own key ID.

This is required because Maven Central verifies your .asc signatures using your public GPG key.

After this step, your GPG details will be used in local.properties:

signing.keyId=9D49CDF0
signing.password=YourStrongGpgPassword
signing.secretKeyRingFile=C:\\Users\\HP-User1\\.gnupg\\secring.gpg
Enter fullscreen mode Exit fullscreen mode

Important:

Do not share your GPG password.
Do not upload secring.gpg to GitHub.
Do not commit local.properties.
Enter fullscreen mode Exit fullscreen mode

Add this to .gitignore:

local.properties
*.gpg
Enter fullscreen mode Exit fullscreen mode

Step 9: Add Signing Details to local.properties

Open your project root:

local.properties
Enter fullscreen mode Exit fullscreen mode

Add:

ossrhUsername=YOUR_TOKEN_USERNAME
ossrhPassword=YOUR_TOKEN_PASSWORD

signing.keyId=YOUR_GPG_KEY_ID
signing.password=YOUR_GPG_PASSWORD
signing.secretKeyRingFile=C:\\Users\\HP-User1\\.gnupg\\secring.gpg
Enter fullscreen mode Exit fullscreen mode

Example:

ossrhUsername=abc123token
ossrhPassword=xyz456tokenpassword

signing.keyId=9D49CDF0
signing.password=YourGpgPassword
signing.secretKeyRingFile=C:\\Users\\HP-User1\\.gnupg\\secring.gpg
Enter fullscreen mode Exit fullscreen mode

Important: never commit local.properties.

Add this to .gitignore:

local.properties
*.gpg
Enter fullscreen mode Exit fullscreen mode

Step 10: Publish to Maven Local First

Before uploading to Maven Central, always publish locally first.

Run:

./gradlew clean :library:publishReleasePublicationToMavenLocal
Enter fullscreen mode Exit fullscreen mode

After success, check this folder:

C:\Users\HP-User1\.m2\repository\io\github\yourUsername\yourLibraryName\1.0.0
Enter fullscreen mode Exit fullscreen mode

You should see files like:

yourLibraryName-1.0.0.aar
yourLibraryName-1.0.0.aar.asc
yourLibraryName-1.0.0.pom
yourLibraryName-1.0.0.pom.asc
yourLibraryName-1.0.0-sources.jar
yourLibraryName-1.0.0-sources.jar.asc
yourLibraryName-1.0.0-javadoc.jar
yourLibraryName-1.0.0-javadoc.jar.asc
yourLibraryName-1.0.0.module
yourLibraryName-1.0.0.module.asc
Enter fullscreen mode Exit fullscreen mode

If .asc files are generated, signing is working properly.


Step 11: Create Central Portal Bundle Script

Now create a PowerShell script in your project root:

create-central-bundle.ps1
Enter fullscreen mode Exit fullscreen mode

Add this code:

param(
    [Parameter(Mandatory=$true)]
    [string]$Version
)

$groupPath = "io\github\yourGithubUserName\yourLibraryName"
$repo = "$env:USERPROFILE\.m2\repository"
$source = "$repo\$groupPath\$Version"

$bundle = "$env:USERPROFILE\Desktop\yourLibraryName-central-bundle"
$dest = "$bundle\$groupPath\$Version"
$zip = "$env:USERPROFILE\Desktop\yourLibraryName-$Version-central.zip"

if (!(Test-Path $source)) {
    Write-Host "ERROR: Maven local version folder not found:" -ForegroundColor Red
    Write-Host $source
    exit 1
}

Write-Host "Cleaning old bundle..."
Remove-Item $bundle -Recurse -Force -ErrorAction SilentlyContinue
Remove-Item $zip -Force -ErrorAction SilentlyContinue

Write-Host "Generating md5 and sha1 checksums..."
Get-ChildItem $source -File | Where-Object {
    $_.Name -notlike "*.md5" -and $_.Name -notlike "*.sha1"
} | ForEach-Object {
    $file = $_.FullName

    $md5 = (Get-FileHash $file -Algorithm MD5).Hash.ToLower()
    $sha1 = (Get-FileHash $file -Algorithm SHA1).Hash.ToLower()

    Set-Content -Path "$file.md5" -Value $md5 -NoNewline
    Set-Content -Path "$file.sha1" -Value $sha1 -NoNewline
}

Write-Host "Creating bundle folder..."
New-Item -ItemType Directory -Force -Path $dest | Out-Null

Write-Host "Copying files..."
Copy-Item "$source\*" $dest -Recurse

Write-Host "Creating ZIP..."
Compress-Archive -Path "$bundle\io" -DestinationPath $zip -Force

Write-Host ""
Write-Host "DONE!" -ForegroundColor Green
Write-Host "Upload this file to Maven Central:"
Write-Host $zip -ForegroundColor Cyan
Enter fullscreen mode Exit fullscreen mode

This script does four important things:

1. Finds your Maven Local artifact
2. Generates md5 and sha1 checksums
3. Creates correct Maven folder structure
4. Creates a Central Portal upload ZIP
Enter fullscreen mode Exit fullscreen mode

Step 12: Generate the Upload ZIP

Run this in your project root where create-central-bundle.ps1 is stored:

powershell -ExecutionPolicy Bypass -File .\create-central-bundle.ps1 -Version 1.0.0
Enter fullscreen mode Exit fullscreen mode

It will create:

C:\Users\HP-User1\Desktop\yourLibraryName-1.0.0-central.zip
Enter fullscreen mode Exit fullscreen mode

The ZIP structure should look like this:

io/
  github/
    yourGithubUserName/
      yourLibraryName/
        1.0.0/
          yourLibraryName-1.0.0.aar
          yourLibraryName-1.0.0.aar.asc
          yourLibraryName-1.0.0.aar.md5
          yourLibraryName-1.0.0.aar.sha1

          yourLibraryName-1.0.0.pom
          yourLibraryName-1.0.0.pom.asc
          yourLibraryName-1.0.0.pom.md5
          yourLibraryName-1.0.0.pom.sha1

          yourLibraryName-1.0.0-sources.jar
          yourLibraryName-1.0.0-sources.jar.asc
          yourLibraryName-1.0.0-sources.jar.md5
          yourLibraryName-1.0.0-sources.jar.sha1

          yourLibraryName-1.0.0-javadoc.jar
          yourLibraryName-1.0.0-javadoc.jar.asc
          yourLibraryName-1.0.0-javadoc.jar.md5
          yourLibraryName-1.0.0-javadoc.jar.sha1

          yourLibraryName-1.0.0.module
          yourLibraryName-1.0.0.module.asc
          yourLibraryName-1.0.0.module.md5
          yourLibraryName-1.0.0.module.sha1
Enter fullscreen mode Exit fullscreen mode

Step 13: Upload to Maven Central

Open:

https://central.sonatype.com
Enter fullscreen mode Exit fullscreen mode

Go to:

Publishing Settings > Deployments
Enter fullscreen mode Exit fullscreen mode

Click:

Publish Component
Enter fullscreen mode Exit fullscreen mode

Upload the generated ZIP:

yourLibraryName-1.0.0-central.zip
Enter fullscreen mode Exit fullscreen mode

Central Portal will validate the bundle.

After validation, the status will move to:

PUBLISHING
Enter fullscreen mode Exit fullscreen mode

Wait for some time and refresh.

Once published, your library will be available from Maven Central.


Step 14: Add Dependency in User Projects

After the release is available, users can add Maven Central:

repositories {
    google()
    mavenCentral()
}
Enter fullscreen mode Exit fullscreen mode

Then add your library dependency:

dependencies {
    implementation 'io.github.yourGithubUserName:yourLibraryName:1.0.0'
}
Enter fullscreen mode Exit fullscreen mode

That’s it.

Your Android library is now available through Maven Central.


Step 15: Release Flow for Future Versions

For the next release, update your version:

PUBLISH_VERSION = '1.0.1'
Enter fullscreen mode Exit fullscreen mode

Then run:

./gradlew clean :library:publishReleasePublicationToMavenLocal
Enter fullscreen mode Exit fullscreen mode

Create the Central Portal ZIP:

powershell -ExecutionPolicy Bypass -File .\create-central-bundle.ps1 -Version 1.0.1
Enter fullscreen mode Exit fullscreen mode

Upload:

yourLibraryName-1.0.1-central.zip
Enter fullscreen mode Exit fullscreen mode

Future releases become very simple:

1. Update version
2. Publish to Maven Local
3. Create Central ZIP
4. Upload ZIP to Central Portal
5. Publish
Enter fullscreen mode Exit fullscreen mode

Important Release Notes

Maven Central versions are immutable.

Once you publish:

1.0.0
Enter fullscreen mode Exit fullscreen mode

you cannot replace the same version again.

For every update, use a new version:

1.0.1
1.1.1
1.2.1
2.0.0
Enter fullscreen mode Exit fullscreen mode

Never publish secrets.

Do not commit:

local.properties
secring.gpg
GPG password
Sonatype token
Enter fullscreen mode Exit fullscreen mode

Always keep your publishing credentials private.


Conclusion

Publishing an Android library to Maven Central becomes easy once the setup is done correctly.

The complete setup requires:

  • Maven publishing configuration
  • Proper POM metadata
  • AAR packaging
  • Sources JAR
  • Javadoc JAR
  • GPG signing
  • Checksum files
  • Correct Maven folder structure
  • Central Portal upload bundle

After the first successful upload, the process becomes repeatable for every future release.

For Android library authors, publishing to Maven Central gives your library a professional installation method and makes it easy for developers to use your work in real projects.

Final dependency example:

implementation 'io.github.yourGithubUsername:yourLibraryName:1.0.0'
Enter fullscreen mode Exit fullscreen mode

Final dependency example gradle kts version:

implementation("io.github.yourGithubUsername:yourLibraryName:1.0.0")
Enter fullscreen mode Exit fullscreen mode

That is the clean and proper way to publish an Android library to Maven Central.

Top comments (0)