Publish Android library without JAR asset

Hello team,

I have an Android library project and I want to publish it without JAR sources because I don’t want my code to be visible. When I publish my library with the current setup, it uploads, “.jar”, “.aar”, “.module” and “.pom” but I don’t want “.jar” to be published to secure my source code.

Below is my build.gradle.kts file. I have it in kotlin dsl and here is the gradle wrapper distribution url I am using in my project: distributionUrl=https://services.gradle.org/distributions/gradle-8.6-bin.zip

import com.android.ddmlib.Log
import java.io.BufferedReader
import java.io.InputStreamReader

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

/**
 * Comment the code above and Uncomment the code below to publish the library
 * Code above is used for continuous development and below is used for library publish
 */
plugins {
    id("com.android.library") version "8.2.2" apply true
    id("org.jetbrains.kotlin.android") version "1.9.21" apply true
    id("maven-publish")
}

version = "1.0.0-pre-alpha01-aws-test06"

android {
    namespace = "com.example.my_sdk"
    compileSdk = 34

    defaultConfig {
        minSdk = 24
        testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        release {
            isMinifyEnabled = true
            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 {
        buildConfig = true
        compose = true
    }
    composeOptions {
        kotlinCompilerExtensionVersion = "1.5.7"
    }
}

dependencies {
    val koinVersion = "3.5.3"

    implementation("androidx.core:core-ktx:1.12.0")
    implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.7.0")
    implementation("androidx.activity:activity-compose:1.9.0")
    implementation(platform("androidx.compose:compose-bom:2024.05.00"))
    implementation("androidx.compose.ui:ui")
    implementation("androidx.compose.ui:ui-graphics")
    implementation("androidx.compose.ui:ui-tooling-preview")
    implementation("androidx.compose.material3:material3")
    implementation("androidx.compose.runtime:runtime-livedata")
    implementation("androidx.compose.foundation:foundation:1.7.0-alpha08")
    implementation("androidx.appcompat:appcompat:1.6.1")

    //  KUBRA Modules
    implementation("com.example.mobile-android:my-sdk-stitch:1.0.0-pre-alpha06")

    //  Koin Dependencies
    runtimeOnly("io.insert-koin:koin-core:$koinVersion")
    implementation("io.insert-koin:koin-android:$koinVersion")
    runtimeOnly("io.insert-koin:koin-androidx-compose:$koinVersion")

    //  Express payment
    implementation ("com.example.mobile-android:express-payments:1.3.0")

    //  AWS for S3
    implementation ("com.amazonaws:aws-android-sdk-s3:2.75.0")
    implementation ("com.amazonaws:aws-android-sdk-core:2.75.0")
    implementation ("com.amazonaws:aws-android-sdk-cognitoidentityprovider:2.75.0")

    testImplementation("junit:junit:4.13.2")
    androidTestImplementation("androidx.test.ext:junit:1.1.5")
    androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
    debugImplementation("androidx.compose.ui:ui-tooling")
}

buildscript {
    extra.set("lastToken", null)
    extra.set("tokenExpiryTime", 0L)
}


fun fetchTokenIfNeeded(): String {
    val currentTime = System.currentTimeMillis()

    val lastToken: String? = extra.get("lastToken") as String?
    val tokenExpiryTime: Long = extra.get("tokenExpiryTime") as Long

    if (lastToken == null || currentTime >= tokenExpiryTime) {
        val newToken = fetchToken()
        extra.set("lastToken", newToken)
        extra.set("tokenExpiryTime", currentTime + 43200 * 1000)
        return newToken
    } else {
        println("CodeArtifact token is still valid. $lastToken")
        return lastToken
    }
}

fun fetchToken(): String {
    val command = "aws codeartifact get-authorization-token --domain kubra-mobile --domain-owner 730335359451 --region us-west-2 --query authorizationToken --output text"
    val process = ProcessBuilder("/bin/sh", "-c", command).start()

    val reader = BufferedReader(InputStreamReader(process.inputStream))
    val token = reader.readText()
    val exitCode = process.waitFor()

    if (exitCode != 0) {
        val errorOutput = BufferedReader(InputStreamReader(process.errorStream)).readText()
        throw GradleException("Failed to refresh AWS CodeArtifact token. Error: $errorOutput")
    }

    return token.trim()
}


    publishing {
        publications {
            create<MavenPublication>("maven") {
                artifactId = "wallet"
                groupId = "com.example.mobile.android.sdk"
                version = version
                afterEvaluate {
                    components["release"]?.let { component ->
                        from(component)
                    }
                }
            }
        }
        repositories {
            maven {
                val releasesUrl = "https://my-domain-123456789.d.codeartifact.us-west-2.amazonaws.com/maven/wallet/"
                val snapshotsUrl = "https://my-domain-123456789.d.codeartifact.us-west-2.amazonaws.com/maven/wallet/"
                url = uri(if (version.toString().endsWith("SNAPSHOT")) snapshotsUrl else releasesUrl)
                credentials {
                    username = "aws"
                    password = fetchTokenIfNeeded()
                }
            }
        }
    }

Please help as this has been a blocker couple of months now and none of the solution seem to be working.

Hello, @Vampire - I see that you seem to have quite expertise about gradle. Can you please help me here?

Thank you in advance.

Maybe I could, but that is in no way a reason to be that rude.
It is absolutely rude and inappropriate in any usual community (except there are some written rules that allow it) to DM or ping users with questions just because you think they might have an answer. Only if you have something really confidential, or want something personal of specifically that person it is appropriate.

I did see your question and if I would have wanted to answer, I would have done it.
But I’m not into Android stuff and Android is always special.
So I have no idea how to do what you intend, and could not even play with it as you did not provide an MCVE.

Also by making me write an answer you also decreased the likelihood that someone else might find and answer your question as they might like you assume I already answered helpfully, hence I decided not to answer at all initially.

You probably have to get the component, cast it to AdhocComponentWithVariants and reconfigure it how you need it or something like that. But I have no idea whether that works with Android, because as I said, Android is always a bit special.

Hi @Vampire , I apologize if my mention seemed rude. That was not my intention, and I fully respect your expertise and contributions. I appreciate your message and look forward to communicating more clearly and respectfully in future.
Thank you for taking time to provide a hint and point me in the direction where I might find answer. I appreciate your guidance and will explore the approach you’ve suggested. Thank you again for your support.

1 Like