apply plugin: 'com.android.application' apply plugin: 'kotlin-android' android { namespace 'com.example.app' compileSdk 34 defaultConfig { applicationId "com.example.app" minSdk 21 targetSdk 34 versionCode 1 versionName "1.0" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } // Signing configuration for release builds. // Configure the following properties in either your // - ~/.gradle/gradle.properties (recommended for secrets), or // - /gradle.properties (do NOT commit passwords) // // Example properties: // MYAPP_STORE_FILE=keystores/my-release-key.jks // MYAPP_STORE_PASSWORD=your_store_password // MYAPP_KEY_ALIAS=my_key_alias // MYAPP_KEY_PASSWORD=your_key_password signingConfigs { release { // Only configure signing when the properties are provided. if (project.hasProperty('MYAPP_STORE_FILE')) { storeFile file(MYAPP_STORE_FILE) storePassword MYAPP_STORE_PASSWORD keyAlias MYAPP_KEY_ALIAS keyPassword MYAPP_KEY_PASSWORD } } } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' // Apply signing config if available. This keeps debug and CI builds // working even when signing properties are absent locally. if (project.hasProperty('MYAPP_STORE_FILE')) { signingConfig signingConfigs.release } // Ensure release builds are not debuggable. debuggable false } } compileOptions { sourceCompatibility JavaVersion.VERSION_17 targetCompatibility JavaVersion.VERSION_17 } kotlinOptions { jvmTarget = "17" } } dependencies { implementation 'androidx.core:core-ktx:1.9.0' implementation 'androidx.appcompat:appcompat:1.6.1' implementation "org.jetbrains.kotlin:kotlin-stdlib:1.9.22" implementation 'androidx.webkit:webkit:1.8.0' implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3' // JSONObject is provided by Android SDK (org.json) } // Task: package webapp assets into a zip for release and optionally upload def webappSrc = file("src/main/assets") def webappZip = file("${buildDir}/outputs/webapp/webapp.zip") tasks.register("zipWebApp") { group = "release" description = "Create zip of web assets (app/src/main/assets -> webapp.zip)" inputs.dir(webappSrc) outputs.file(webappZip) doLast { webappZip.parentFile.mkdirs() ant.zip(destfile: webappZip) { fileset(dir: webappSrc) } println "Created webapp zip: ${webappZip.absolutePath}" } } tasks.register("uploadWebApp") { group = "release" description = "Upload webapp zip to remote server if UPLOAD_WEBAPP_URL is set" dependsOn "zipWebApp" doLast { def uploadUrl = System.getenv('UPLOAD_WEBAPP_URL') def token = System.getenv('UPLOAD_WEBAPP_TOKEN') if (!uploadUrl) { println "UPLOAD_WEBAPP_URL not set, skipping upload" return } if (!webappZip.exists()) { throw new GradleException("webapp zip not found: ${webappZip}") } println "Uploading webapp to ${uploadUrl}" def cmd = ["curl", "--fail", "-X", "PUT", "-H", "Content-Type: application/zip"] if (token) { cmd += ["-H", "Authorization: Bearer ${token}"] } cmd += ["--data-binary", "@${webappZip.absolutePath}", uploadUrl] def process = cmd.execute() process.in.eachLine { println it } process.err.eachLine { System.err.println it } def rc = process.waitFor() if (rc != 0) throw new GradleException("Upload failed with exit code ${rc}") println "Upload successful" } }