You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android库发布Maven Central失败(400错误),请求协助排查

MavenCentral发布Compose Android库失败(400 Bad Request)排查方案

我开发了一款基于Compose的Android库,能正常发布到本地.m2/repository目录并使用,但发布到MavenCentral时失败,报错400 Bad Request。以下是我的build.gradle配置和报错日志,需要找出问题根源并解决。

原配置文件

plugins {
    id("com.android.library")
    id("org.jetbrains.kotlin.android")
    id("signing")
    id("maven-publish")
}

// Configure the signing block
signing {
    val signingKey: String? by project
    val signingPassword: String? by project
    useInMemoryPgpKeys(signingKey, signingPassword)
}


android {
    namespace = "com.gk.image_preview"
    compileSdk = 34

    defaultConfig {
        minSdk = 24

        testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
        consumerProguardFiles("consumer-rules.pro")
    }

    buildTypes {
        release {
            isMinifyEnabled = false
            proguardFiles(
                getDefaultProguardFile("proguard-android-optimize.txt"),
                "proguard-rules.pro"
            )
        }
    }
    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_1_8
        targetCompatibility = JavaVersion.VERSION_1_8
    }
    kotlinOptions {
        jvmTarget = "1.8"
    }
    buildFeatures {
        compose = true
    }
    composeOptions {
        kotlinCompilerExtensionVersion = "1.5.1"
    }

//    afterEvaluate {
//        android.libraryVariants.forEach { libraryVariant ->
//            publishing.publications.create(libraryVariant.name, MavenPublication::class.java) {
//                from(components.getByName(libraryVariant.name))
//                groupId = "io.github.cypher103360"
//                artifactId = "image-preview"
//                version = "1.0.0"
//            }
//        }
//    }

}

afterEvaluate {
    publishing {
        publications {
            create<MavenPublication>("release") {
                from(components["release"])

                groupId = "io.github.cypher103360"
                artifactId = "image-preview"
                version = "1.0.0"

                pom {
                    name = artifactId
                    description = "This is the image preview library."

                    scm {
                        connection = "scm:git@github.com:Cypher103360/MyLibrary.git"
                        url = "https://github.com/Cypher103360/MyLibrary.git"
                    }
                    developers {
                        developer {
                            id = "cypher103360"
                            name = "Gaurav"
                            email = "gk3854631@gmail.com"
                        }
                    }
                }
            }
        }
        repositories {
            maven {
                name = "MyImagePreviewSnapshot"
                url = uri("https://s01.oss.sonatype.org/content/repositories/snapshots/")

                credentials {
                    username = project.findProperty("ossrhUsername")?.toString()
                    password = project.findProperty("ossrhPassword")?.toString()
                }
            }

            maven {
                name = "imagePreview"
                url = uri("https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/")

                credentials {
                    username = project.findProperty("ossrhUsername")?.toString()
                    password = project.findProperty("ossrhPassword")?.toString()
                }
            }
        }
    }
}


dependencies {
    implementation("androidx.core:core-ktx:1.12.0")
    implementation("androidx.appcompat:appcompat:1.6.1")
    implementation("com.google.android.material:material:1.10.0")
    testImplementation("junit:junit:4.13.2")
    androidTestImplementation("androidx.test.ext:junit:1.1.5")
    androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")

    implementation(platform("androidx.compose:compose-bom:2023.08.00"))
    implementation("androidx.compose.ui:ui")
    implementation("androidx.compose.ui:ui-graphics")
    implementation("androidx.compose.ui:ui-tooling-preview")
    implementation("androidx.compose.material3:material3")
}

报错日志

> Configure project :image-preview
Kotlin DSL property assignment is an incubating feature.

> Task :image-preview:publishReleasePublicationToImagePreviewRepository FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':image-preview:publishReleasePublicationToImagePreviewRepository'.
> Failed to publish publication 'release' to repository 'imagePreview'
   > Could not PUT 'https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/io/github/cypher103360/image-preview/1.0.1-SNAPSHOT/maven-metadata.xml'. Received status code 400 from server: Bad Request

* Try:
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.
> Get more help at https://help.gradle.org.

BUILD FAILED in 4s
26 actionable tasks: 23 executed, 2 from cache, 1 up-to-date

问题根源分析

  1. 版本类型与仓库不匹配:报错中版本是1.0.1-SNAPSHOT,但你试图将快照版本上传到正式staging仓库(service/local/staging/deploy/maven2/),该仓库仅接受不带-SNAPSHOT的正式版本,快照版本必须上传到专门的快照仓库(content/repositories/snapshots/)。

  2. 签名配置不完整:原配置仅加载了PGP密钥,但未指定对发布产物签名,MavenCentral要求所有构件必须签名才能通过审核。

  3. POM信息缺失必填项:原POM未声明许可证信息,这是MavenCentral强制要求的,即使当前报错未触发,后续仓库验证也会失败。


修复后的完整配置

plugins {
    id("com.android.library")
    id("org.jetbrains.kotlin.android")
    id("signing")
    id("maven-publish")
}

android {
    namespace = "com.gk.image_preview"
    compileSdk = 34

    defaultConfig {
        minSdk = 24
        testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
        consumerProguardFiles("consumer-rules.pro")
    }

    buildTypes {
        release {
            isMinifyEnabled = false
            proguardFiles(
                getDefaultProguardFile("proguard-android-optimize.txt"),
                "proguard-rules.pro"
            )
        }
    }
    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_1_8
        targetCompatibility = JavaVersion.VERSION_1_8
    }
    kotlinOptions {
        jvmTarget = "1.8"
    }
    buildFeatures {
        compose = true
    }
    composeOptions {
        kotlinCompilerExtensionVersion = "1.5.1"
    }
}

// 签名配置:自动对所有发布产物签名
signing {
    val signingKey: String? by project
    val signingPassword: String? by project
    useInMemoryPgpKeys(signingKey, signingPassword)
    sign(publishing.publications)
}

afterEvaluate {
    publishing {
        publications {
            create<MavenPublication>("release") {
                from(components["release"])

                groupId = "io.github.cypher103360"
                artifactId = "image-preview"
                // 正式版本去掉-SNAPSHOT,快照版本需上传到对应仓库
                version = "1.0.0"

                pom {
                    name = artifactId
                    description = "This is the image preview library."

                    // 新增必填许可证信息
                    licenses {
                        license {
                            name = "The Apache License, Version 2.0"
                            url = "http://www.apache.org/licenses/LICENSE-2.0.txt"
                            distribution = "repo"
                        }
                    }

                    scm {
                        connection = "scm:git@github.com:Cypher103360/MyLibrary.git"
                        url = "https://github.com/Cypher103360/MyLibrary.git"
                    }
                    developers {
                        developer {
                            id = "cypher103360"
                            name = "Gaurav"
                            email = "gk3854631@gmail.com"
                        }
                    }
                }
            }
        }
        repositories {
            maven {
                name = "MyImagePreviewSnapshot"
                url = uri("https://s01.oss.sonatype.org/content/repositories/snapshots/")
                credentials {
                    username = project.findProperty("ossrhUsername")?.toString()
                    password = project.findProperty("ossrhPassword")?.toString()
                }
            }

            maven {
                name = "imagePreview"
                url = uri("https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/")
                credentials {
                    username = project.findProperty("ossrhUsername")?.toString()
                    password = project.findProperty("ossrhPassword")?.toString()
                }
            }
        }
    }
}

dependencies {
    implementation("androidx.core:core-ktx:1.12.0")
    implementation("androidx.appcompat:appcompat:1.6.1")
    implementation("com.google.android.material:material:1.10.0")
    testImplementation("junit:junit:4.13.2")
    androidTestImplementation("androidx.test.ext:junit:1.1.5")
    androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")

    implementation(platform("androidx.compose:compose-bom:2023.08.00"))
    implementation("androidx.compose.ui:ui")
    implementation("androidx.compose.ui:ui-graphics")
    implementation("androidx.compose.ui:ui-tooling-preview")
    implementation("androidx.compose.material3:material3")
}

发布操作说明

  • 发布正式版本:确保版本号不带-SNAPSHOT,执行命令:./gradlew publishReleasePublicationToImagePreviewRepository
  • 发布快照版本:修改版本号为1.0.1-SNAPSHOT,执行命令:./gradlew publishReleasePublicationToMyImagePreviewSnapshotRepository

额外检查项

  • 确认ossrhUsername和ossrhPassword已在local.properties或系统环境变量中正确配置
  • 确认PGP公钥已上传到公共密钥服务器(如keyserver.ubuntu.com),Sonatype需验证签名有效性
  • 确认Sonatype平台上的io.github.cypher103360 groupId已通过审核(GitHub账号关联验证)

内容的提问来源于stack exchange,提问作者Cypher

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 12:58:21