1- import com.android.build.api.artifact.SingleArtifact
21import com.android.build.api.dsl.ApplicationExtension
3- import com.android.build.api.variant.ApplicationAndroidComponentsExtension
4- import org. gradle.api.DefaultTask
2+ import com.android.build.gradle.AbstractAppExtension
3+ import com.android.build. gradle.internal. api.BaseVariantOutputImpl
54import org.gradle.api.JavaVersion
65import org.gradle.api.Project
7- import org.gradle.api.file.DirectoryProperty
8- import org.gradle.api.provider.Property
9- import org.gradle.api.tasks.CacheableTask
10- import org.gradle.api.tasks.Input
11- import org.gradle.api.tasks.OutputDirectory
12- import org.gradle.api.tasks.TaskAction
6+ import org.gradle.api.plugins.ExtensionAware
137import org.gradle.kotlin.dsl.getByName
14- import org.gradle.kotlin.dsl.register
15- import org.gradle.kotlin.dsl.withType
16- import org.jetbrains.kotlin.gradle.dsl.JvmTarget
17- import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
8+ import org.jetbrains.kotlin.gradle.dsl.KotlinJvmOptions
189import java.util.Base64
1910import java.util.Properties
11+ import kotlin.system.exitProcess
2012
2113private val Project .android get() = extensions.getByName<ApplicationExtension >(" android" )
22- private val Project .androidComponents
23- get() = extensions.getByName<ApplicationAndroidComponentsExtension >(" androidComponents" )
2414
2515private lateinit var metadata: Properties
2616private lateinit var localProperties: Properties
@@ -40,6 +30,7 @@ fun Project.requireLocalProperties(): Properties {
4030
4131 val base64 = System .getenv(" LOCAL_PROPERTIES" )
4232 if (! base64.isNullOrBlank()) {
33+
4334 localProperties.load(Base64 .getDecoder().decode(base64).inputStream())
4435 } else if (project.rootProject.file(" local.properties" ).exists()) {
4536 localProperties.load(rootProject.file(" local.properties" ).inputStream())
@@ -50,10 +41,10 @@ fun Project.requireLocalProperties(): Properties {
5041
5142fun Project.setupCommon () {
5243 android.apply {
53- buildToolsVersion = " 36 .0.0 "
54- compileSdk = 36
44+ buildToolsVersion = " 35 .0.1 "
45+ compileSdk = 35
5546 defaultConfig {
56- minSdk = 23
47+ minSdk = 21
5748 targetSdk = 35
5849 }
5950 buildTypes {
@@ -62,15 +53,17 @@ fun Project.setupCommon() {
6253 }
6354 }
6455 compileOptions {
65- sourceCompatibility = JavaVersion .VERSION_17
66- targetCompatibility = JavaVersion .VERSION_17
56+ sourceCompatibility = JavaVersion .VERSION_1_8
57+ targetCompatibility = JavaVersion .VERSION_1_8
58+ }
59+ (android as ExtensionAware ).extensions.getByName<KotlinJvmOptions >(" kotlinOptions" ).apply {
60+ jvmTarget = JavaVersion .VERSION_1_8 .toString()
6761 }
6862 lint {
6963 showAll = true
7064 checkAllWarnings = true
7165 checkReleaseBuilds = true
7266 warningsAsErrors = true
73- baseline = project.file(" lint-baseline.xml" )
7467 textOutput = project.file(" build/lint.txt" )
7568 htmlOutput = project.file(" build/lint.html" )
7669 }
@@ -87,92 +80,61 @@ fun Project.setupCommon() {
8780 " org/**" ,
8881 " **/*.java" ,
8982 " **/*.proto" ,
90- " okhttp3/**" ,
91- ),
83+ " okhttp3/**"
84+ )
9285 )
9386 }
94- // Under AGP 9's new DSL the build types below are configured directly on
95- // ApplicationExtension (no AbstractAppExtension cast needed). APK output renaming is no
96- // longer done here via the removed applicationVariants/BaseVariantOutputImpl API; it is
97- // handled by the RenameApkTask wired in setupApp() through androidComponents.onVariants.
98- buildTypes {
99- getByName(" release" ) {
100- isShrinkResources = true
101- if (System .getenv(" nkmr_minify" ) == " 0" ) {
102- isShrinkResources = false
103- isMinifyEnabled = false
87+ (this as ? AbstractAppExtension )?.apply {
88+ buildTypes {
89+ getByName(" release" ) {
90+ isShrinkResources = true
91+ if (System .getenv(" nkmr_minify" ) == " 0" ) {
92+ isShrinkResources = false
93+ isMinifyEnabled = false
94+ }
95+ }
96+ getByName(" debug" ) {
97+ applicationIdSuffix = " debug"
98+ debuggable(true )
99+ jniDebuggable(true )
104100 }
105- // Plan 027 Stage 3: release keeps the current main-thread-DB allowance until
106- // debug has run StrictMode-clean for a full cycle; then this flips to false and
107- // the allowMainThreadQueries() call is deleted.
108- buildConfigField(" boolean" , " ALLOW_MAIN_THREAD_DB" , " true" )
109101 }
110- getByName( " debug " ) {
111- applicationIdSuffix = " debug "
112- isDebuggable = true
113- isJniDebuggable = true
114- // Debug ships with the allowance OFF so StrictMode + a main-thread DAO access
115- // surfaces as a crash-free IllegalStateException the operator can catch on device.
116- buildConfigField( " boolean " , " ALLOW_MAIN_THREAD_DB " , " false " )
102+ applicationVariants.forEach { variant ->
103+ variant.outputs.forEach {
104+ it as BaseVariantOutputImpl
105+ it.outputFileName = it.outputFileName.replace(
106+ " app " , " ${project.name} - " + variant.versionName
107+ ).replace( " -release " , " " ).replace( " -oss " , " " )
108+ }
117109 }
118110 }
119111 }
120-
121- // Kotlin JVM target. Configured via the compilerOptions DSL on the Kotlin compile tasks
122- // (a project-level call, hence outside the android.apply { } block above); the legacy
123- // `kotlinOptions { jvmTarget = ... }` / KotlinJvmOptions API was removed (turned into a
124- // hard error) in Kotlin 2.3.
125- tasks.withType<KotlinCompile >().configureEach {
126- compilerOptions {
127- jvmTarget.set(JvmTarget .JVM_17 )
128- }
129- }
130112}
131113
132114fun Project.setupAppCommon () {
133115 setupCommon()
134116
135117 val lp = requireLocalProperties()
136- val keystorePwd = (lp.getProperty(" KEYSTORE_PASS" ) ? : System .getenv(" KEYSTORE_PASS" ))
137- ?.takeIf { it.isNotBlank() }
138- val alias = (lp.getProperty(" ALIAS_NAME" ) ? : System .getenv(" ALIAS_NAME" ))
139- ?.takeIf { it.isNotBlank() }
140- val pwd = (lp.getProperty(" ALIAS_PASS" ) ? : System .getenv(" ALIAS_PASS" ))
141- ?.takeIf { it.isNotBlank() }
142- val releaseKeystoreFile = rootProject.file(" release.keystore" )
143- val debugKeystoreFile = rootProject.file(" app/debug.keystore" )
118+ val keystorePwd = lp.getProperty(" KEYSTORE_PASS" ) ? : System .getenv(" KEYSTORE_PASS" )
119+ val alias = lp.getProperty(" ALIAS_NAME" ) ? : System .getenv(" ALIAS_NAME" )
120+ val pwd = lp.getProperty(" ALIAS_PASS" ) ? : System .getenv(" ALIAS_PASS" )
144121
145122 android.apply {
146- signingConfigs {
147- if (keystorePwd != null && alias != null && pwd != null && releaseKeystoreFile.isFile) {
123+ if (keystorePwd != null ) {
124+ signingConfigs {
148125 create(" release" ) {
149- storeFile = releaseKeystoreFile
126+ storeFile = rootProject.file( " release.keystore " )
150127 storePassword = keystorePwd
151128 keyAlias = alias
152129 keyPassword = pwd
153130 }
154131 }
155- if (debugKeystoreFile.isFile) {
156- create(" ciDebug" ) {
157- storeFile = debugKeystoreFile
158- storePassword = " android"
159- keyAlias = " androiddebugkey"
160- keyPassword = " android"
161- }
162- }
163132 }
164133 buildTypes {
165- val releaseKey = signingConfigs.findByName(" release" )
166- val ciDebugKey = signingConfigs.findByName(" ciDebug" )
167- when {
168- releaseKey != null -> {
169- getByName(" release" ).signingConfig = releaseKey
170- getByName(" debug" ).signingConfig = releaseKey
171- }
172-
173- ciDebugKey != null -> {
174- getByName(" debug" ).signingConfig = ciDebugKey
175- }
134+ val key = signingConfigs.findByName(" release" )
135+ if (key != null ) {
136+ getByName(" release" ).signingConfig = key
137+ getByName(" debug" ).signingConfig = key
176138 }
177139 }
178140 }
@@ -188,18 +150,18 @@ fun Project.setupApp() {
188150 versionCode = verCode
189151 versionName = verName
190152 buildConfigField(" String" , " PRE_VERSION_NAME" , " \"\" " )
191- // Runner for instrumented (androidTest) tests, e.g. the Room migration test.
192- testInstrumentationRunner = " androidx.test.runner.AndroidJUnitRunner"
193153 }
194154 }
195155 setupAppCommon()
196156
197157 android.apply {
158+ this as AbstractAppExtension
159+
198160 buildTypes {
199161 getByName(" release" ) {
200162 proguardFiles(
201163 getDefaultProguardFile(" proguard-android-optimize.txt" ),
202- file(" proguard-rules.pro" ),
164+ file(" proguard-rules.pro" )
203165 )
204166 }
205167 }
@@ -223,76 +185,36 @@ fun Project.setupApp() {
223185 buildConfigField(
224186 " String" ,
225187 " PRE_VERSION_NAME" ,
226- " \" ${requireMetadata().getProperty(" PRE_VERSION_NAME" )} \" " ,
188+ " \" ${requireMetadata().getProperty(" PRE_VERSION_NAME" )} \" "
227189 )
228190 }
229191 }
230192
193+ applicationVariants.all {
194+ outputs.all {
195+ this as BaseVariantOutputImpl
196+ val isPreview = outputFileName.contains(" -preview" )
197+ outputFileName = if (isPreview) {
198+ outputFileName.replace(
199+ project.name,
200+ " Throne-" + requireMetadata().getProperty(" PRE_VERSION_NAME" )
201+ ).replace(" -preview" , " " )
202+ } else {
203+ outputFileName.replace(project.name, " Throne-$versionName " )
204+ .replace(" -release" , " " )
205+ .replace(" -oss" , " " )
206+ }
207+ }
208+ }
209+
231210 for (abi in listOf (" Arm64" , " Arm" , " X64" , " X86" )) {
232- tasks.register (" assemble" + abi + " FdroidRelease" ) {
211+ tasks.create (" assemble" + abi + " FdroidRelease" ) {
233212 dependsOn(" assembleFdroidRelease" )
234213 }
235214 }
236215
237216 sourceSets.getByName(" main" ).apply {
238- jniLibs.directories.add(" executableSo" )
239- }
240- }
241-
242- // APK output renaming. The legacy applicationVariants/BaseVariantOutputImpl API was removed in
243- // AGP 9 (new DSL). Instead we react to artifact creation and copy the produced APKs into
244- // build/outputs/renamed_apks/<variant> with friendly NekoBox-<version>[-<abi>].apk names.
245- // The preview flavor uses PRE_VERSION_NAME to match the previous behaviour.
246- val previewVersionName = requireMetadata().getProperty(" PRE_VERSION_NAME" )
247- androidComponents.onVariants { variant ->
248- val shortcutResourcesTask = tasks.register<GenerateShortcutResourcesTask >(
249- " generate${variant.name.replaceFirstChar { it.uppercase() }} ShortcutResources" ,
250- ) {
251- val effectivePackageName = if (variant.buildType == " debug" ) " $pkgName .debug" else pkgName
252- targetPackage.set(effectivePackageName)
253- outputDirectory.set(
254- layout.buildDirectory.dir(" generated/shortcutResources/${variant.name} " ),
255- )
256- }
257- variant.sources.res?.addGeneratedSourceDirectory(
258- shortcutResourcesTask,
259- GenerateShortcutResourcesTask ::outputDirectory,
260- )
261-
262- val isPreview = variant.flavorName == " preview" ||
263- variant.productFlavors.any { (_, flavor) -> flavor == " preview" }
264- val version = if (isPreview) previewVersionName else verName
265- val renameTask = tasks.register<RenameApkTask >(
266- " renameApksFor${variant.name.replaceFirstChar { it.uppercase() }} " ,
267- ) {
268- output.set(layout.buildDirectory.dir(" outputs/renamed_apks/${variant.name} " ))
269- builtArtifactsLoader.set(variant.artifacts.getBuiltArtifactsLoader())
270- baseName.set(" NekoBox-$version " )
217+ jniLibs.srcDir(" executableSo" )
271218 }
272- variant.artifacts.use(renameTask)
273- .wiredWith { it.input }
274- .toListenTo(SingleArtifact .APK )
275219 }
276- }
277-
278- @CacheableTask
279- abstract class GenerateShortcutResourcesTask : DefaultTask () {
280- @get:Input
281- abstract val targetPackage: Property <String >
282-
283- @get:OutputDirectory
284- abstract val outputDirectory: DirectoryProperty
285-
286- @TaskAction
287- fun generate () {
288- val xmlDirectory = outputDirectory.dir(" xml" ).get().asFile.apply { mkdirs() }
289- xmlDirectory.resolve(" shortcuts.xml" ).writeText(renderShortcuts(targetPackage.get()))
290- }
291-
292- private fun renderShortcuts (packageName : String ): String {
293- val template = checkNotNull(javaClass.getResourceAsStream(" /shortcuts-template.xml" )) {
294- " shortcuts-template.xml resource not found"
295- }.bufferedReader().use { it.readText() }
296- return template.replace(" {{TARGET_PACKAGE}}" , packageName)
297- }
298- }
220+ }
0 commit comments