plugins { id "com.android.application" id "kotlin-android" id "dev.flutter.flutter-gradle-plugin" id "com.google.gms.google-services" } def localProperties = new Properties() def localPropertiesFile = rootProject.file("local.properties") if (localPropertiesFile.exists()) { localPropertiesFile.withReader("UTF-8") { reader -> localProperties.load(reader) } } def flutterVersionCode = localProperties.getProperty("flutter.versionCode") ?: "1" def flutterVersionName = localProperties.getProperty("flutter.versionName") ?: "1.0" def keystoreProperties = new Properties() def keystorePropertiesFile = rootProject.file("key.properties") if (keystorePropertiesFile.exists()) { keystoreProperties.load(new FileInputStream(keystorePropertiesFile)) } android { namespace = "com.nearle.partner" compileSdk = 36 // Must be >= the highest NDK required by any plugin (maplibre_gl needs // 28.1.13356709). NDK releases are backward compatible, so the highest wins. ndkVersion "28.1.13356709" packagingOptions { jniLibs { useLegacyPackaging = true } // ❌ removed doNotStrip (this was breaking your AAB build) } compileOptions { sourceCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8 coreLibraryDesugaringEnabled true } kotlinOptions { jvmTarget = "1.8" } defaultConfig { applicationId = "com.nearle.partner" minSdkVersion flutter.minSdkVersion targetSdkVersion 36 versionCode flutterVersionCode.toInteger() versionName flutterVersionName manifestPlaceholders = [ applicationName: "android.app.Application" ] // Build only ARM64 ndk { abiFilters "arm64-v8a" } } signingConfigs { release { keyAlias keystoreProperties["keyAlias"] keyPassword keystoreProperties["keyPassword"] storeFile keystoreProperties["storeFile"] ? file(keystoreProperties["storeFile"]) : null storePassword keystoreProperties["storePassword"] } } buildTypes { debug { minifyEnabled false debuggable true } release { signingConfig signingConfigs.release minifyEnabled true shrinkResources true proguardFiles getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro" // ❌ removed ndk { debugSymbolLevel } (this caused strip crash) } } } dependencies { implementation "androidx.core:core:1.10.0" implementation "com.google.android.gms:play-services-location:21.0.1" coreLibraryDesugaring "com.android.tools:desugar_jdk_libs:2.1.5" } flutter { source = "../.." } tasks.register("copyNotificationSounds", Copy) { def audioDir = file("$projectDir/../../assets/audio") from(audioDir) include("*.mp3") into("$projectDir/src/main/res/raw") rename { String fileName -> fileName.replaceAll(/[^A-Za-z0-9_.]/, "_").toLowerCase() } } tasks.named("preBuild").configure { dependsOn("copyNotificationSounds") } // --------------------------------------------------------------------------- // Release artifact naming: nearlepartnerv.aab / .apk // // The file is RENAMED rather than copied, and any previous nearlepartner* // artifact is removed first, so exactly one bundle ever sits in the output // directory. That matters: when two .aab files are present, Flutter's // "✓ Built ..." line can name the wrong one, which is an easy way to upload a // stale build to the Play Store. // --------------------------------------------------------------------------- // `versionName` is passed in explicitly: script-level `def` variables such as // flutterVersionName are not in scope inside a `def` method in Groovy. def renameReleaseArtifact(File outputDir, String defaultName, String extension, String versionName) { def source = new File(outputDir, defaultName) if (!source.exists()) { return } outputDir.listFiles({ File f -> f.name.startsWith("nearlepartner") && f.name.endsWith(extension) } as FileFilter)?.each { it.delete() } def stamp = new Date().format("ddMMyy") def target = new File(outputDir, "nearlepartner${stamp}v${versionName}${extension}") if (source.renameTo(target)) { println "Release artifact renamed -> ${target.name}" } else { println "WARNING: could not rename ${source.name}; leaving it in place" } } def releaseArtifactVersion = flutterVersionName tasks.matching { it.name == "bundleRelease" }.configureEach { doLast { renameReleaseArtifact( layout.buildDirectory.dir("outputs/bundle/release").get().asFile, "app-release.aab", ".aab", releaseArtifactVersion ) } } tasks.matching { it.name == "assembleRelease" }.configureEach { doLast { renameReleaseArtifact( layout.buildDirectory.dir("outputs/apk/release").get().asFile, "app-release.apk", ".apk", releaseArtifactVersion ) } }