For stcPay Bahrain Android Team
This guide covers everything a stcPay Android team member needs to:
feature/stcpay-android-sdk branch locally on a fresh machinestcpay-customer-android and stcpay-ui-kit-android repositories. This is NOT for the super app integration team.
local.propertiesThe feature/stcpay-android-sdk branch packages the entire stcpay-customer-android app experience as a distributable Android library: com.stcpay:stcpay-sdk:1.0.1. A super app team can integrate the complete stcPay Bahrain experience by adding a single Gradle dependency and calling StcPaySDK.launch(context).
| Repository | Branch | Purpose |
|---|---|---|
stcpay-customer-android |
feature/stcpay-android-sdk |
Main SDK source — contains :stcpay-sdk module and all 30+ feature modules |
stcpay-ui-kit-android |
feature/stcpay-android-sdk |
UI component library — integrated as a Gradle composite build inside stcpay-customer-android. Branch exists for consistency only; no separate publishing is needed. |
All 30+ stcpay-customer-android repo modules are published to Maven Local (~/.m2/repository/com/stcpay/) as individual Maven artifacts under the group com.stcpay, version 1.0.1. A super app then resolves everything from Maven Local (or a private Maven server in the future).
Three artifacts cannot be auto-published because they are flat-dir local AARs with no Gradle module source. These must be manually installed to Maven Local once on each developer machine:
com.stcpay:secureutility:1.0.1com.stcpay:benefit_pay_sdk:1.0.0stcpay-ui-kit-android (com.stcpay:stcpay-ui-kit:1.0.0) is handled automatically because it is included as a Gradle composite build — Gradle substitutes the Maven coordinate with the local source project during publish.
JAVA_HOME explicitly — do not omit it.
JBR 21 is bundled with Android Studio. Typical path on macOS:
/Users/<username>/Library/Java/JavaVirtualMachines/jbr-21.0.x/Contents/Home
Find yours with:
$ /usr/libexec/java_home -V
Look for a line containing JetBrains and 21.x. Use that path for every JAVA_HOME= in this guide.
Verify all of the following before running any commands:
mvn) installed — used for manual AAR installationmvn --version · Install on macOS: brew install mavenstcpay-customer-android and stcpay-ui-kit-android repositories# Pull the stcpay-customer-android SDK branch $ cd /path/to/stcpay-customer-android $ git fetch origin $ git checkout feature/stcpay-android-sdk $ git pull origin feature/stcpay-android-sdk # Pull the stcpay-ui-kit-android branch (for branch name consistency) $ cd /path/to/stcpay-ui-kit-android $ git fetch origin $ git checkout feature/stcpay-android-sdk $ git pull origin feature/stcpay-android-sdk
stcpay-ui-kit-android branch feature/stcpay-android-sdk is branched from develop and contains no SDK-specific changes. It exists only so both repos share the same branch name. No separate build or publish step is needed for stcpay-ui-kit-android.
local.propertiesIn the root of the stcpay-customer-android project, open local.properties (create it if it does not exist) and add:
# Absolute path to the stcpay-ui-kit-android project root # Replace with the actual path on your machine stcpay-ui-kit-androidProjectPath=/Users/<username>/path/to/stcpay-ui-kit-android # Android SDK path (if not already present) sdk.dir=/Users/<username>/Library/Android/sdk
publishToMavenLocal runs, Gradle will automatically substitute com.stcpay:stcpay-ui-kit:1.0.0 with the local stcpay-ui-kit-android project source and publish it alongside all other modules. No separate step is needed.
These two artifacts are flat-dir local AARs (no Gradle module source) and must be installed once per developer machine. They will not be re-installed on each publish.
secureutility$ mvn install:install-file \
-Dfile=/path/to/stcpay-customer-android/util/libs/secureutility-1.0.1.aar \
-DgroupId=com.stcpay \
-DartifactId=secureutility \
-Dversion=1.0.1 \
-Dpackaging=aar \
-DgeneratePom=true
Verify:
$ ls ~/.m2/repository/com/stcpay/secureutility/1.0.1/ # Expected: secureutility-1.0.1.aar secureutility-1.0.1.pom
benefit_pay_sdk$ mvn install:install-file \
-Dfile=/path/to/stcpay-customer-android/benefit_pay_sdk/libs/benefitinappsdk-1.0.23.aar \
-DgroupId=com.stcpay \
-DartifactId=benefit_pay_sdk \
-Dversion=1.0.0 \
-Dpackaging=aar \
-DgeneratePom=true
Verify:
$ ls ~/.m2/repository/com/stcpay/benefit_pay_sdk/1.0.0/ # Expected: benefit_pay_sdk-1.0.0.aar benefit_pay_sdk-1.0.0.pom
This compiles and publishes all 30+ stcpay-customer-android repo modules plus stcpay-ui-kit-android. It takes approximately ~20 minutes.
$ cd /path/to/stcpay-customer-android $ JAVA_HOME=/Users/<username>/Library/Java/JavaVirtualMachines/jbr-21.0.x/Contents/Home \ ./gradlew publishToMavenLocal --parallel
JAVA_HOME=… as shown.
stcpay-sdk source only)If you only changed files inside stcpay-sdk/src/ or stcpay-sdk/build.gradle.kts, run a faster targeted publish (~5–10 min):
$ cd /path/to/stcpay-customer-android $ JAVA_HOME=/Users/<username>/Library/Java/JavaVirtualMachines/jbr-21.0.x/Contents/Home \ ./gradlew :stcpay-sdk:publishToMavenLocal
$ ls ~/.m2/repository/com/stcpay/ # Expected: a folder for every stcpay-customer-android module $ ls ~/.m2/repository/com/stcpay/stcpay-sdk/1.0.1/ # Expected 6 variant AARs + .module + .pom: # stcpay-sdk-1.0.1-gmsUat.aar # stcpay-sdk-1.0.1-gmsPreProd.aar # stcpay-sdk-1.0.1-gmsProd.aar # stcpay-sdk-1.0.1-hmsUat.aar # stcpay-sdk-1.0.1-hmsPreProd.aar # stcpay-sdk-1.0.1-hmsProd.aar # stcpay-sdk-1.0.1.module # stcpay-sdk-1.0.1.pom $ ls ~/.m2/repository/com/stcpay/stcpay-ui-kit/1.0.0/ # Expected: stcpay-ui-kit-1.0.0*.aar (composite build auto-published)
| Change made | Command to run |
|---|---|
Any file under stcpay-sdk/src/ or stcpay-sdk/build.gradle.kts | ./gradlew :stcpay-sdk:publishToMavenLocal |
| Any feature module, util, common, navigator, etc. | ./gradlew publishToMavenLocal --parallel |
| Any file in stcpay-ui-kit-android | ./gradlew publishToMavenLocal --parallel (composite build republishes it) |
Create a new Android project in Android Studio with these settings:
| Template | Empty Activity |
| Package name | com.yourcompany.stcpaysuperapp (or any name) |
| Language | Kotlin |
| Minimum SDK | API 24 |
Then apply the following configuration to each file:
settings.gradle.ktsReplace the existing dependencyResolutionManagement block entirely:
dependencyResolutionManagement { repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) repositories { mavenLocal() // resolves com.stcpay:* from ~/.m2 google() mavenCentral() maven { url = uri("https://jitpack.io") } // dotlottie-android transitive dep exclusiveContent { forRepository { maven { url = uri("https://repo.mobile.jumio.ai") } } filter { includeGroup("com.jumio.android") includeGroup("com.iproov.sdk") } } } }
mavenLocal() — you can skip §05–§08 entirely. See §15 for the full repository block and credentials.
build.gradle.kts (project-level)plugins { id("com.android.application") version "9.0.1" apply false id("org.jetbrains.kotlin.android") version "2.0.21" apply false id("com.google.dagger.hilt.android") version "2.56.2" apply false // Required: generates a Crashlytics build UUID at compile time. // The SDK bundles firebase-crashlytics which checks for this UUID at runtime. // Without this plugin the app crashes on launch with "Crashlytics build ID is missing". id("com.google.firebase.crashlytics") version "3.0.2" apply false }
gradle/libs.versions.toml — add these entries[versions] composeBom = "2025.12.01" [libraries] # Must use compose-bom-alpha:2025.12.01 to match the Compose version # the SDK was compiled against. Using a different BOM causes runtime crashes. androidx-compose-bom = { group = "androidx.compose", name = "compose-bom-alpha", version.ref = "composeBom" }
app/build.gradle.kts — full fileimport com.android.build.api.attributes.BuildTypeAttr import org.gradle.api.attributes.AttributeCompatibilityRule import org.gradle.api.attributes.AttributeDisambiguationRule import org.gradle.api.attributes.CompatibilityCheckDetails import org.gradle.api.attributes.MultipleCandidatesDetails import org.jetbrains.kotlin.gradle.dsl.JvmTarget // ── Android Studio / IntelliJ variant resolution fix ────────────────────── // The stcPay SDK uses custom build types (uat / preProd / prod) instead of // debug/release. AGP's matchingFallbacks covers most configs, but Android // Studio's internal ijDownloadArtifact bypasses AGP — these rules cover it. abstract class StcPayBuildTypeCompatibility : AttributeCompatibilityRule<BuildTypeAttr> { override fun execute(details: CompatibilityCheckDetails<BuildTypeAttr>) { val consumer = details.consumerValue?.name ?: return val producer = details.producerValue?.name ?: return when { consumer == "release" && producer in setOf("prod", "preProd", "uat") -> details.compatible() consumer == "debug" && producer in setOf("uat", "preProd", "prod") -> details.compatible() } } } abstract class StcPayBuildTypeDisambiguation : AttributeDisambiguationRule<BuildTypeAttr> { override fun execute(details: MultipleCandidatesDetails<BuildTypeAttr>) { val consumer = details.consumerValue?.name ?: return val preferred = when (consumer) { "release" -> "prod"; "debug" -> "uat"; else -> return } details.candidateValues.firstOrNull { it.name == preferred }?.let { details.closestMatch(it) } } } // ───────────────────────────────────────────────────────────────────────── plugins { alias(libs.plugins.kotlin.compose) id("com.android.application") id("org.jetbrains.kotlin.android") id("com.google.dagger.hilt.android") id("org.jetbrains.kotlin.kapt") id("com.google.firebase.crashlytics") } android { namespace = "com.yourcompany.stcpaysuperapp" compileSdk = 36 defaultConfig { applicationId = "com.yourcompany.stcpaysuperapp" minSdk = 24 targetSdk = 36 versionCode = 1 versionName = "1.0" // Required: SDK has a 'contentType' product flavor dimension (gms/hms). // Host app has no such dimension — tell Gradle which to pick. missingDimensionStrategy("contentType", "gms") } buildTypes { release { isMinifyEnabled = false proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro") signingConfig = signingConfigs.getByName("debug") // SDK has no "release" type — map to prod matchingFallbacks += listOf("prod", "preProd", "uat") } debug { // SDK has no "debug" type — map to uat matchingFallbacks += listOf("uat", "preProd", "prod") } } compileOptions { sourceCompatibility = JavaVersion.VERSION_11 targetCompatibility = JavaVersion.VERSION_11 isCoreLibraryDesugaringEnabled = true } buildFeatures { compose = true } firebaseCrashlytics { mappingFileUploadEnabled = false nativeSymbolUploadEnabled = false } } kotlin { compilerOptions { jvmTarget.set(JvmTarget.JVM_11) } } dependencies { attributesSchema { attribute(BuildTypeAttr.ATTRIBUTE) { compatibilityRules.add(StcPayBuildTypeCompatibility::class.java) disambiguationRules.add(StcPayBuildTypeDisambiguation::class.java) } } implementation(libs.androidx.core.ktx) implementation(libs.androidx.lifecycle.runtime.ktx) implementation(libs.androidx.activity.compose) // Compose BOM — must be compose-bom-alpha:2025.12.01 implementation(platform(libs.androidx.compose.bom)) implementation("androidx.compose.ui:ui") implementation("androidx.compose.ui:ui-graphics") implementation("androidx.compose.ui:ui-tooling-preview") implementation("androidx.compose.material3:material3") debugImplementation("androidx.compose.ui:ui-tooling") // Required: backports java.time to devices below API 26 coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.1.5") // Required: SDK uses Hilt throughout implementation("com.google.dagger:hilt-android:2.56.2") kapt("com.google.dagger:hilt-android-compiler:2.56.2") // stcPay SDK — single dependency. The following are auto re-exported: // coil-compose, coil-network-okhttp, material-icons-extended, hilt-work implementation("com.stcpay:stcpay-sdk:1.0.1") }
MyApplication.ktpackage com.yourcompany.stcpaysuperapp import com.stcpay.sdk.StcPayApplication import dagger.hilt.android.HiltAndroidApp @HiltAndroidApp class MyApplication : StcPayApplication()
StcPayApplication is an open class provided by the SDK. Extending it automatically handles Firebase initialisation, analytics, WorkManager, and all other internal SDK dependencies in onCreate().
AndroidManifest.xml<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"> <application android:name=".MyApplication" android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:theme="@style/Theme.StcPaySuperApp" tools:replace="android:allowBackup"> <!-- tools:replace required: Jumio declares allowBackup="false" --> <activity android:name=".MainActivity" android:exported="true" android:theme="@style/Theme.StcPaySuperApp"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <!-- Required: disables WorkManager default initializer. StcPayApplication provides custom config via Hilt @EntryPoint. Default initializer running first causes a crash. --> <provider android:name="androidx.startup.InitializationProvider" android:authorities="${applicationId}.androidx-startup" tools:node="merge"> <meta-data android:name="androidx.work.WorkManagerInitializer" android:value="androidx.startup" tools:node="remove" /> </provider> </application> </manifest>
package com.yourcompany.stcpaysuperapp import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.compose.foundation.layout.* import androidx.compose.material3.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import com.stcpay.sdk.StcPaySDK import com.stcpay.sdk.StcPayConfig import com.stcpay.sdk.StcPayEnvironment import dagger.hilt.android.AndroidEntryPoint @AndroidEntryPoint class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { Column( modifier = Modifier.fillMaxSize().padding(32.dp), verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally ) { Button(onClick = { StcPaySDK.configure(StcPayConfig(environment = StcPayEnvironment.UAT)) StcPaySDK.launch(this@MainActivity) }) { Text("Launch stcPay (UAT)") } Spacer(Modifier.height(16.dp)) Button(onClick = { StcPaySDK.configure(StcPayConfig(environment = StcPayEnvironment.PROD)) StcPaySDK.launch(this@MainActivity) }) { Text("Launch stcPay (PROD)") } } } } }
In Android Studio: Run → Run 'app' (or ⇧F10). The debug build type maps to the SDK's gmsUat variant.
Filter Logcat by package com.yourcompany.stcpaysuperapp. Within 2–3 seconds of app start:
SdkOrchestrator D Security SDK initialised SdkOrchestrator D Timber tree planted SdkAdjustInit D Adjust initialised: <token> SdkIntercomInit D Intercom initialised SdkOneSignalInit D OneSignal initialised: <app-id>
SdkActivity opens — the full stcPay Bahrain UI loadsMainActivityIn Android Studio: Build → Generate Signed Bundle/APK → APK → use debug signing for testing. Or from the terminal:
$ cd /path/to/super-app $ JAVA_HOME=/Users/<username>/Library/Java/JavaVirtualMachines/jbr-21.0.x/Contents/Home \ ./gradlew assembleRelease
$ adb install app/build/outputs/apk/release/app-release.apk
SdkOrchestrator debug logs (Timber disabled in prod)# 1. Publish — use full or SDK-only depending on what changed $ cd /path/to/stcpay-customer-android $ JAVA_HOME=… ./gradlew :stcpay-sdk:publishToMavenLocal # SDK-only changes # OR $ JAVA_HOME=… ./gradlew publishToMavenLocal --parallel # Any module changes # 2. Clean rebuild super app — REQUIRED to bust Gradle AAR cache $ cd /path/to/super-app $ JAVA_HOME=… ./gradlew clean assembleDebug
./gradlew clean assembleDebug in the super app after every re-publish.
| Error | Root cause | Fix |
|---|---|---|
IllegalStateException: The Crashlytics build ID is missing |
com.google.firebase.crashlytics Gradle plugin not applied |
Add to project-level and app-level build.gradle.kts as shown in §8.2 |
IllegalStateException: Default FirebaseApp is not initialized |
Stale AAR in Gradle cache from old SDK version | Run ./gradlew clean assembleDebug in the super app |
IllegalStateException: You need to use a Theme.AppCompat theme |
Old SDK version where SdkActivity had no theme declared |
Ensure SDK version is 1.0.1. Clean rebuild. |
Manifest merger failed: allowBackup conflict |
Jumio declares allowBackup="false" |
Add tools:replace="android:allowBackup" to <application> tag |
Unable to find a matching variant of com.stcpay:stcpay-sdk:1.0.1 |
missingDimensionStrategy or matchingFallbacks missing |
Add both as shown in §8.4 |
Execution failed for task ':app:ijDownloadArtifact...' |
Android Studio's ijDownloadArtifact bypasses AGP variant resolution |
Add StcPayBuildTypeCompatibility and StcPayBuildTypeDisambiguation attribute rules shown in §8.4 |
NoClassDefFoundError: Failed resolution of: Lsome/library/ClassName |
SDK uses that library as implementation (not exported to consumers) |
Add the missing library to app/build.gradle.kts using same version as in stcpay-customer-android/gradle/libs.versions.toml. Notify SDK lead to promote to api(). |
FATAL EXCEPTION: BAD_DECRYPT / OPENSSL_internal |
AES key mismatch between debug (uat) and release (prod) on same device + same package | Fixed in SDK via PreferencesUtil.decryptOrClear(). Ensure SDK version is 1.0.1. |
| SDK Logcat tags not visible after re-publish | Gradle cache serving the old AAR | Run ./gradlew clean assembleDebug in the super app |
Could not resolve com.stcpay:secureutility:1.0.1 or benefit_pay_sdk:1.0.0 |
Manual AARs not installed to Maven Local | Run the mvn install:install-file commands from §07 |
Could not GET '…maven.pkg.github.com…' Received status code 401 (GitHub Packages) |
PAT missing/invalid, or not present in ~/.gradle/gradle.properties |
Add a token with read:packages as shown in §15.2–§15.3. Confirm you have access to the stcpaybh/stcpay-customer-android repo. |
Received status code 422: Unprocessable Entity (publishing to GitHub Packages) |
Maven coordinate contains uppercase letters — GitHub Packages requires lowercase | Maintainers only: the publish convention plugin lowercases every artifactId. Ensure you publish from the SDK branch where this fix is present. |
feature/stcpay-android-sdkstcpay-ui-kit-androidProjectPath set in stcpay-customer-android/local.propertiesmvn --version returns a versionsecureutility-1.0.1 installed — ls ~/.m2/repository/com/stcpay/secureutility/1.0.1/ shows filesbenefit_pay_sdk-1.0.0 installed — ls ~/.m2/repository/com/stcpay/benefit_pay_sdk/1.0.0/ shows files./gradlew publishToMavenLocal --parallel completed without errorsstcpay-sdk/1.0.1/ directory contains 6 variant AARsmavenLocal(), jitpack.io, Jumio repo added to settings.gradle.ktsbuild.gradle.ktsmissingDimensionStrategy("contentType", "gms") in defaultConfigmatchingFallbacks on both release and debug build typesStcPayBuildTypeCompatibility + StcPayBuildTypeDisambiguation attribute rules addedisCoreLibraryDesugaringEnabled = true + coreLibraryDesugaring dep addedfirebaseCrashlytics { mappingFileUploadEnabled = false } block addedcompose-bom-alpha:2025.12.01kaptimplementation("com.stcpay:stcpay-sdk:1.0.1") addedStcPayApplication + @HiltAndroidApptools:replace="android:allowBackup" in manifest <application> tagInitializationProvider entry removed from manifestSdkOrchestrator, SdkAdjustInit, SdkIntercomInit, SdkOneSignalInitThe SDK is also published to a private GitHub Packages Maven registry. If you only want to consume and test a published build — not modify the SDK source — use this path instead of Maven Local. You can skip the entire local-publish pipeline (§05–§08): no cloning, no manual AAR install, no publishToMavenLocal.
| Maven Local step | Needed for GitHub Packages? |
|---|---|
| §05 Pull both repositories | ❌ Not needed |
§06 Configure local.properties | ❌ Not needed |
| §07 Manually install local AARs | ❌ Not needed — already on the registry |
| §08 Publish to Maven Local | ❌ Not needed — already published |
| §09 Create the test super app | ✅ Yes — with the repo block in §15.5 |
| §10 / §11 Build & verify (UAT / PROD) | ✅ Yes — identical |
Far lighter than the Maven Local path — you are only consuming a published artifact, not building the SDK:
stcpaybh/stcpay-customer-android repositoryread:packages — created in §15.3maven.pkg.github.comstcpay-customer-android or stcpay-ui-kit-android clone · no local.properties · no manual AAR install · no publishToMavenLocal. You never compile the SDK from source.
| Registry URL | https://maven.pkg.github.com/stcpaybh/stcpay-customer-android |
| Group | com.stcpay |
| Current published version | 1.0.1 |
1.0.1. Use it in your dependency. All com.stcpay coordinates are lowercase — GitHub Packages rejects uppercase Maven coordinates, so each published artifactId is the lowercased form of its Gradle module name (e.g. securityNDK → securityndk).
Create a Personal Access Token (classic) at github.com/settings/tokens with these scopes:
read:packages — required to download artifactsrepo — required because the repository is privateYou must be a member of stcpaybh with access to the stcpay-customer-android repository.
~/.gradle/gradle.propertiesUse the global Gradle properties file (in your home directory) — it is never committed, so it is the safe place for tokens:
# ~/.gradle/gradle.properties — global, never committed to git stcPayMavenUser=<your-github-username> stcPayMavenPassword=<your-PAT-with-read:packages>
~/.gradle/gradle.properties (global) or a CI secret — never in the project's committed gradle.properties or settings.gradle.kts.
settings.gradle.kts — GitHub Packages instead of mavenLocal()This is the only structural difference from §9.1: the mavenLocal() line is replaced by the StcPayPrivateMaven repository. The content { includeGroup("com.stcpay") } filter ensures Gradle only queries the registry for stcPay artifacts — all other dependencies still come from Google / Maven Central / JitPack.
dependencyResolutionManagement { repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) repositories { // ⬇ Replaces mavenLocal() — resolves com.stcpay:* from GitHub Packages maven { name = "StcPayPrivateMaven" url = uri("https://maven.pkg.github.com/stcpaybh/stcpay-customer-android") credentials { username = providers.gradleProperty("stcPayMavenUser").orNull ?: System.getenv("STCPAY_MAVEN_USER") ?: "" password = providers.gradleProperty("stcPayMavenPassword").orNull ?: System.getenv("STCPAY_MAVEN_PASSWORD") ?: "" } content { includeGroup("com.stcpay") } } google() mavenCentral() maven { url = uri("https://jitpack.io") } // dotlottie-android transitive dep exclusiveContent { forRepository { maven { url = uri("https://repo.mobile.jumio.ai") } } filter { includeGroup("com.jumio.android") includeGroup("com.iproov.sdk") } } } }
app/build.gradle.kts — dependencyIdentical to §9.4, but point at the remote version:
implementation("com.stcpay:stcpay-sdk:1.0.1")
Every other file in §09 — the project-level build.gradle.kts, libs.versions.toml, the StcPayApplication subclass, AndroidManifest.xml, and MainActivity — is exactly the same as the Maven Local path. Build and verify using §10 (UAT) and §11 (PROD) unchanged.
Build the debug variant in Android Studio (Run → Run 'app'). To prove resolution comes from the registry — not a stale local cache — force a clean re-resolve from the terminal:
$ cd /path/to/super-app $ ./gradlew clean :app:assembleDebug --refresh-dependencies
A successful build downloads every com.stcpay:* artifact from maven.pkg.github.com into the Gradle cache. Then run the same functional checks as the Maven Local path — they are identical:
gmsUat variant.Could not GET … 401, your token is missing, expired, or lacks read:packages — re-check §15.3–§15.4. A 403 usually means your account lacks access to the stcpaybh repository. See also §13.
read:packages created and saved in ~/.gradle/gradle.propertiesStcPayPrivateMaven repo block added to settings.gradle.kts (no mavenLocal() needed)content { includeGroup("com.stcpay") } filter present on that repoimplementation("com.stcpay:stcpay-sdk:1.0.1") in app/build.gradle.ktsmissingDimensionStrategy, matchingFallbacks, attribute rules, desugaring, Compose BOM, Hilt, manifest, Application class./gradlew clean :app:assembleDebug --refresh-dependencies completes without errorsFor context, a maintainer pushes a release to the registry from stcpay-customer-android (credentials read from the same ~/.gradle/gradle.properties, with a token that also has write:packages):
$ cd /path/to/stcpay-customer-android # Publishes all com.stcpay modules to the GitHub Packages registry $ JAVA_HOME=/Users/<username>/Library/Java/JavaVirtualMachines/jbr-21.0.x/Contents/Home \ ./gradlew publishAllPublicationsToStcPayPrivateMavenRepository
secureutility:1.0.1, stcpay-ui-kit:1.0.0, and benefit_pay_sdk:1.0.0 are published once and resolved automatically — consumers do not install them manually (unlike §07 for Maven Local).