44 */
55
66
7+ import com.android.build.api.artifact.SingleArtifact
8+ import com.android.build.api.variant.ResValue
9+ import org.gradle.api.GradleException
10+ import java.io.File
711import com.android.ddmlib.DdmPreferences
812import java.io.FileInputStream
913import java.text.SimpleDateFormat
@@ -15,7 +19,6 @@ DdmPreferences.setTimeOut(10 * 60 * 1000)
1519
1620plugins {
1721 id(" com.android.application" )
18- id(" kotlin-android" )
1922 id(" androidx.navigation.safeargs.kotlin" )
2023 id(" com.starter.easylauncher" )
2124 id(" kotlin-parcelize" )
@@ -30,7 +33,7 @@ if (propertiesFile.exists()) {
3033}
3134
3235android {
33- compileSdk = extra[" compileSdkVersion" ] as Int
36+ compileSdk = rootProject. extra[" compileSdkVersion" ] as Int
3437 namespace = " com.flowcrypt.email"
3538
3639 defaultConfig {
@@ -42,10 +45,10 @@ android {
4245 testInstrumentationRunnerArguments + = mapOf (" clearPackageData" to " true" )
4346
4447 applicationId = " com.flowcrypt.email"
45- minSdk = extra[" minSdkVersion" ] as Int
46- targetSdk = extra[" targetSdkVersion" ] as Int
47- versionCode = extra[" appVersionCode" ] as Int
48- versionName = extra[" appVersionName" ] as String
48+ minSdk = rootProject. extra[" minSdkVersion" ] as Int
49+ targetSdk = rootProject. extra[" targetSdkVersion" ] as Int
50+ versionCode = rootProject. extra[" appVersionCode" ] as Int
51+ versionName = rootProject. extra[" appVersionName" ] as String
4952 testInstrumentationRunner = " androidx.test.runner.AndroidJUnitRunner"
5053 buildConfigField(" int" , " MIN_SDK_VERSION" , " $minSdk " )
5154 multiDexEnabled = true
@@ -191,6 +194,7 @@ android {
191194 buildFeatures {
192195 buildConfig = true
193196 viewBinding = true
197+ resValues = true
194198 }
195199
196200 packaging {
@@ -264,23 +268,89 @@ ksp {
264268}
265269
266270androidComponents {
271+
267272 beforeVariants { variantBuilder ->
268- if (variantBuilder.name in listOf (" devRelease" , " devUiTests" )) {
269- // Gradle ignores any variants that satisfy the conditions above.
273+ if (variantBuilder.name in setOf (" devRelease" , " devUiTests" )) {
270274 println (" INFO: Excluded \" ${variantBuilder.name} \" from build variant list as unused" )
271275 variantBuilder.enable = false
272276 }
273277 }
274278
279+ // --- Applies to ALL variants ---
275280 onVariants { variant ->
276- // we share applicationId as a res value
281+ // Share applicationId as a res value
277282 variant.resValues.put(
278283 variant.makeResValueKey(" string" , " application_id" ),
279- com.android.build.api.variant. ResValue (variant.applicationId.get())
284+ ResValue (variant.applicationId.get())
280285 )
281286 }
287+
288+ val releaseSelector = selector().withBuildType(" release" )
289+
290+ // --- Release-only tasks ---
291+ onVariants(releaseSelector) { variant ->
292+ val cap = variant.name.replaceFirstChar { it.uppercase() }
293+
294+ // APK output directory provider
295+ val apkDirProvider = variant.artifacts.get(SingleArtifact .APK )
296+
297+ fun listApks (): List <java.io.File > {
298+ val dir = apkDirProvider.get().asFile
299+ return dir.walkTopDown().filter { it.isFile && it.extension == " apk" }.toList()
300+ }
301+
302+ val checkTask = tasks.register(" check${cap} ApkSize" ) {
303+ doLast {
304+ val apks = listApks()
305+ if (apks.isEmpty()) {
306+ throw GradleException (" No APK files found in: ${apkDirProvider.get().asFile.absolutePath} " )
307+ }
308+
309+ val maxExpected = 50L * 1024L * 1024L
310+ apks.forEach { apk ->
311+ val size = apk.length()
312+ if (size > maxExpected) {
313+ throw GradleException (
314+ " Release APK is bigger than expected. max=$maxExpected , actual=$size , file=${apk.name} "
315+ )
316+ }
317+ }
318+ }
319+ }
320+
321+ val renameTask = tasks.register(" rename${cap} Builds" ) {
322+ doLast {
323+ val apks = listApks()
324+ if (apks.isEmpty()) {
325+ logger.lifecycle(" No APK files found to rename in: ${apkDirProvider.get().asFile.absolutePath} " )
326+ return @doLast
327+ }
328+
329+ val ts = SimpleDateFormat (" yyyy_MM_dd_HH_mm" ).format(Date ())
330+
331+ // If multiple outputs exist (splits), versionCode/versionName can differ;
332+ // fallback to defaultConfig if not available.
333+ val vCode =
334+ variant.outputs.singleOrNull()?.versionCode?.orNull ? : android.defaultConfig.versionCode
335+ val vName =
336+ variant.outputs.singleOrNull()?.versionName?.orNull ? : android.defaultConfig.versionName
337+
338+ apks.forEach { apk ->
339+ val newName = apk.name.removeSuffix(" .apk" ) + " _${vCode} _${vName} _${ts} .apk"
340+ val target = apk.parentFile.resolve(newName)
341+
342+ if (! apk.renameTo(target)) {
343+ throw GradleException (" Failed to rename ${apk.absolutePath} -> ${target.absolutePath} " )
344+ } else {
345+ logger.lifecycle(" Renamed: ${apk.name} -> ${target.name} " )
346+ }
347+ }
348+ }
349+ }
350+ }
282351}
283352
353+
284354easylauncher {
285355 buildTypes {
286356 register(" debug" ) {
@@ -345,44 +415,6 @@ tasks.register("checkCorrectBranch") {
345415 }
346416}
347417
348- tasks.register(" checkReleaseBuildsSize" ) {
349- doLast {
350- android.applicationVariants.forEach { applicationVariant ->
351- if (applicationVariant.buildType.name == " release" ) {
352- applicationVariant.outputs.forEach { variantOutput ->
353- val apkFile = variantOutput.outputFile
354- // for now apk up to 50Mb is normal
355- val maxExpectedSizeInBytes = 50 * 1024 * 1024
356- if (apkFile.length() > maxExpectedSizeInBytes) {
357- throw GradleException (
358- " The generated release build is bigger then expected: " +
359- " expected = not big then $maxExpectedSizeInBytes , actual = ${apkFile.length()} "
360- )
361- }
362- }
363- }
364- }
365- }
366- }
367-
368- tasks.register(" renameReleaseBuilds" ) {
369- doLast {
370- android.applicationVariants.forEach { applicationVariant ->
371- if (applicationVariant.buildType.name == " release" ) {
372- applicationVariant.outputs.forEach { variantOutput ->
373- val file = variantOutput.outputFile
374- val newName = file.name.replace(
375- " .apk" , " _" + android.defaultConfig.versionCode +
376- " _" + android.defaultConfig.versionName + " _"
377- + SimpleDateFormat (" yyyy_MM_dd_HH_mm" ).format(Date ()) + " .apk"
378- )
379- variantOutput.outputFile.renameTo(File (file.parent, newName))
380- }
381- }
382- }
383- }
384- }
385-
386418tasks.register<Copy >(" copyReleaseApks" ) {
387419 includeEmptyDirs = false
388420
0 commit comments