@file:Suppress("SpellCheckingInspection") import com.android.build.gradle.internal.api.ApplicationVariantImpl import com.android.build.gradle.internal.api.BaseVariantOutputImpl import org.gradle.kotlin.dsl.support.uppercaseFirstChar import kotlin.text.RegexOption.IGNORE_CASE plugins { id("org.autojs.build.utils") id("org.autojs.build.versions") id("org.autojs.build.signs") id("org.autojs.build.jvm-convention") id("com.android.application") id("com.google.devtools.ksp") id("org.jetbrains.kotlin.android") /* kotlin("android") */ id("idea") } idea { module { excludeDirs.addAll(listOf( file("$rootDir/app/src/main/java/com/stardust/"), file("$rootDir/app/src/main/assets/modules/obsolete/"), file("$rootDir/app/src/main/assets-app/js-beautify/"), )) } } val globalApplicationId = "org.autojs.autojs6" val flavorDimension = "channel" val flavorNameApp = "app" val flavorNameInrt = "inrt" val buildTypeDebug = "debug" val buildTypeRelease = "release" val buildActionAssemble = "assemble" val taskNames: List = gradle.startParameter.taskNames val isAppAssembleTaskRequested = taskNames.any { it.contains(Regex("^(:?$flavorNameApp:)?$buildActionAssemble", IGNORE_CASE)) } val isInrtAssembleTaskRequested = taskNames.any { it.contains(Regex("^(:?$flavorNameApp:)?$buildActionAssemble$flavorNameInrt", IGNORE_CASE)) } val isInrtTaskRequested = taskNames.any { it.contains(flavorNameInrt, true) } utils.registerTemplateApkCopy(project) dependencies /* Unclassified */ { // Compose // implementation("androidx.compose.ui:ui-android:1.6.7") // Kotlin reflect implementation(kotlin("reflect")) // AndroidX Core implementation(libs.core.ktx) // LeakCanary debugImplementation(libs.leakcanary) // Android supports implementation(libs.cardview) implementation(libs.multidex) // Material Components implementation(libs.material) // SwipeRefreshLayout implementation(libs.swiperefreshlayout) // ConstraintLayout implementation(libs.constraintlayout) // FlexboxLayout implementation(libs.flexbox) // Common Markdown implementation(libs.commonmark) // Flexmark Java HTML to Markdown Extensible Converter implementation(libs.flexmark.html2md) // Licenses Dialog implementation(libs.licensesdialog) // Apache Commons implementation(libs.commons.lang3) // Retrofit implementation(libs.retrofit) implementation(libs.retrofit.converter.gson) implementation(libs.retrofit.adapter.rxjava2) implementation(libs.retrofit2.kotlin.coroutines.adapter) // Glide implementation(libs.glide) ksp(libs.glide.ksp) // Joda Time implementation(libs.joda.time) // OkHttp implementation(libs.okhttp) // Webkit implementation(libs.webkit) // Gson implementation(libs.gson) // Zip4j implementation(libs.zip4j) // FIXME by SuperMonster003 on Aug 14, 2024. // ! Vulnerable dependency (5 vulnerabilities) for log4j (version 1): // ! - CVE-2022-23307, Score: 8.8 // ! - CVE-2022-23305, Score: 9.8 // ! - CVE-2022-23302, Score: 8.8 // ! - CVE-2021-4104, Score: 7.5 // ! - CVE-2019-17571, Score: 9.8 // ! However, log4j version 2 which requires Android API Level not lower than 26 // ! is not compatible with current project with min API Level 24. // ! // ! zh-CN: // ! // ! 依赖库 log4j (第一版本) 是易受攻击的 (含 5 项漏洞): // ! - CVE-2022-23307, 评分: 8.8 // ! - CVE-2022-23305, 评分: 9.8 // ! - CVE-2022-23302, 评分: 8.8 // ! - CVE-2021-4104, 评分: 7.5 // ! - CVE-2019-17571, 评分: 9.8 // ! 但 log4j 第二版本要求安卓 API 级别不低于 26, // ! 与最低 API 级别为 24 的当前项目无法兼容. // Log4j implementation(libs.log4j) // Android Logging Log4j implementation(libs.android.logging.log4j) // Preference implementation(libs.preference.ktx) // RootShell // implementation("com.github.Stericson:RootShell:1.6") implementation(project(":libs:root-shell-1_6")) // JDeferred implementation(libs.jdeferred) // Rx implementation(libs.rxjava) implementation(libs.rxandroid) // Device Names implementation(libs.android.device.names) // Version Compare implementation(libs.versioncompare) // Terminal Emulator implementation(project(":libs:jackpal-androidterm-libtermexec-1_0")) implementation(project(":libs:jackpal-androidterm-emulatorview-1_0_42")) implementation(project(":libs:jackpal-androidterm-1_0_70")) // Dex implementation(files("$rootDir/libs/com-android-dx-1_14.jar")) implementation(files("$rootDir/libs/com-legacy-android-dx-1_7_0.jar")) // OpenCV implementation(project(":libs:org-opencv-4_8_0")) // RapidOCR implementation(project(":libs:rapidocr")) // Image Quantization implementation(project(":libs:imagequant")) // Android Job implementation(project(":libs:android-job-simplified-1_4_3")) // Androidx Work Runtime implementation(libs.work.runtime) // APK Parser // implementation("com.jaredrummler:apk-parser:1.0.2") // implementation("com.github.AndroidDeveloperLB:apk-parser:6") implementation(project(":modules:apk-parser")) // Prism4j implementation(files("$rootDir/libs/prism4j-2_0_0.jar")) implementation(files("$rootDir/libs/prism4j-bundler-2_0_0.jar")) implementation(project(":libs:markwon-core-4_6_2")) implementation(project(":libs:markwon-syntax-highlight-4_6_2")) // Rhino implementation(files("$rootDir/libs/org-mozilla-rhino-2_0_0-SNAPSHOT.jar")) // Tasker Plugin implementation(project(":libs:android-spackle-9_0_0")) implementation(project(":libs:android-assertion-9_0_0")) implementation(project(":libs:android-plugin-client-sdk-for-locale-9_0_0")) // JavaMail for Android implementation(files("$rootDir/libs/javamail-android/activation.jar")) implementation(files("$rootDir/libs/javamail-android/additionnal.jar")) implementation(files("$rootDir/libs/javamail-android/mail.jar")) // Shizuku implementation(libs.shizuku.api) implementation(libs.shizuku.provider) // ARSCLib implementation(libs.arsclib) // Toaster implementation(libs.toaster) implementation(libs.easywindow) // Pinyin4j implementation(libs.pinyin4j) // Jieba Analysis (zh-CN: 结巴分词) // implementation("com.huaban:jieba-analysis:1.0.2") implementation(project(":modules:jieba-analysis")) // Tiny Sign implementation(files("$rootDir/libs/tiny-sign-0_9.jar")) // Room implementation(libs.room.runtime) implementation(libs.room.ktx) ksp(libs.room.compiler) // ApkSig // implementation("com.android.tools.build:apksig:8.7.3") // ApkSigner implementation(project(":modules:apk-signer")) // Prov implementation(libs.prov) // MQTT implementation(libs.paho.client.mqttv3) implementation(libs.paho.android.service) // Jsoup implementation(libs.jsoup) // Material Date Time Picker implementation(project(":modules:material-date-time-picker")) // ICU4J implementation(libs.icu4j) // R8 implementation(libs.r8) // Plugin API: Paddle OCR implementation(project(":plugin-api:paddle-ocr")) } dependencies /* MIME */ { // @Hint by SuperMonster003 on Oct 5, 2023. // ! Only for Android API 26 (8.0) [O] and above. // ! zh-CN: 仅适用于安卓 API 级别 26 (8.0) [O] 及以上. // Apache Tika Core // implementation("org.apache.tika:tika-core:2.9.2") // MIME Util // implementation("eu.medsea.mimeutil:mime-util:2.1.3") implementation(files("$rootDir/libs/mime-util-2_1_3.jar")) } dependencies /* Test */ { testImplementation(libs.junit) androidTestImplementation(libs.test.runner) androidTestImplementation(libs.junit.jupiter) } dependencies /* Annotations */ { // Android Annotations implementation(libs.androidannotations.api) implementation(libs.annotation) ksp(libs.androidannotations) // JCIP Annotations implementation(libs.jcip.annotations) // EventBus implementation(libs.eventbus) } dependencies /* AppCompat */ { // @Hint by SuperMonster003 on Oct 5, 2023. // ! To check the releases for Appcompat library, // ! visit https://developer.android.com/jetpack/androidx/releases/appcompat. // ! zh-CN: // ! 查看 Appcompat 库的发行版本, // ! 可访问 https://developer.android.com/jetpack/androidx/releases/appcompat. implementation(libs.appcompat) // AppCompat for legacy views (such as JsTextViewLegacy) implementation(project(":libs:androidx-appcompat-1_0_2")) { setVersion("1.0.2") } } dependencies /* Material Dialogs */ { // TODO by SuperMonster003 on Feb 5, 2022. // ! Upgrade to 3.3.0 (more difficult than expected). // ! zh-CN: 升级至 3.3.0 (实际难度超出预期较多). // # val configuration: (ExternalModuleDependency).() -> Unit = { // # version { // # prefer("0.9.6.0") // # because("Not ready to update to version 3.3.0 yet") // # } // # } // # configuration.let { cfg -> // # implementation("com.afollestad.material-dialogs:core", cfg) // # implementation("com.afollestad.material-dialogs:commons", cfg) // # } // Material Dialogs implementation(project(":modules:material-dialogs")) implementation(libs.materialprogressbar) } dependencies /* Layout */ { // Expandable Layout // implementation("com.github.aakira:expandable-layout:1.6.0") implementation(project(":libs:expandable-layout-1_6_0")) // Expandable RecyclerView implementation(libs.expandablerecyclerview) // Flexible Divider // implementation("com.yqritc:recyclerview-flexibledivider:1.4.0") implementation(project(":libs:recyclerview-flexibledivider-1_4_0")) } dependencies /* View */ { // RoundedImageView implementation(libs.roundedimageview) // CircleImageView implementation(libs.circleimageview) // Animated SVG implementation(libs.animated.svg.view) } dependencies /* GitHub API */ { // GitHub API implementation(files("$rootDir/libs/github-api-1_306.jar")) // @Hint by SuperMonster003 on Sep 25, 2025. // ! Strict version: "2.8.0". // ! Compatibility for Android API Level < 26 (Android 8.0) [O]. // ! Exception on newer versions: 'NoClassDefFoundError: org.apache.commons.io.IObuildUtils'. // Commons IO implementation(libs.commons.io) // Jackson Databind implementation(libs.jackson.databind) // Desugar coreLibraryDesugaring(libs.desugar) } dependencies /* MLKit */ { // OCR implementation(libs.text.recognition.chinese) // Barcode implementation(libs.barcode.scanning) } dependencies /* OpenCC */ { // OpenCC // implementation("com.github.qichuan:android-opencc:1.2.0") implementation(libs.opencc) } dependencies /* Auto.js Extensions */ { // Settings Compat // @Integrated by SuperMonster003 on Mar 30, 2023. // # implementation("com.github.hyb1996:settingscompat:1.1.5") // Enhanced Floaty // @Integrated by SuperMonster003 on Mar 30, 2023. // # implementation("com.github.hyb1996:EnhancedFloaty:0.31") // MultiLevelListView // @Integrated by SuperMonster003 on Mar 30, 2023. // # implementation("com.github.hyb1996:android-multi-level-listview:1.1") // Auto.js APK Builder // @Integrated by SuperMonster003 on Mar 30, 2023. // # implementation(project(":libs:Autojs-ApkBuilder-1_0_3")) // Extracted from com.github.hyb1996:MutableTheme:1.0.0 implementation(libs.recyclerview) implementation(libs.circularreveal) // @Legacy com.jrummyapps:colorpicker:2.1.7 // @Integrated by SuperMonster003 on Mar 25, 2025. // # implementation("com.jaredrummler:colorpicker:1.1.0") implementation(project(":modules:color-picker")) } dependencies /* Build Logic */ { // Version Codes Generator ksp(libs.ksp.version.codes.processor) } dependencies /* Archived */ { // @Comment by SuperMonster003 on May 19, 2022. // ! It is no longer necessary to declare a dependency on the stdlib library in any Kotlin Gradle project. // ! The dependency is added by default. // ! See https://kotlinlang.org/docs/gradle.html#dependency-on-the-standard-library. // ! zh-CN: // ! 已无需在 Kotlin Gradle 项目中显式声明标准库 (stdlib). // ! 相关依赖已默认被添加. // ! 参阅 https://kotlinlang.org/docs/gradle.html#dependency-on-the-standard-library. // Kotlin // implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.6.21") // @Comment by SuperMonster003 on Jun 1, 2022. // ! Not necessary for current project but worth keeping the trace. // ! zh-CN: 于当前项目已不再需要, 但依然值得留存其踪迹 (以备不时之需). // Google Guava // implementation("com.google.guava:guava:31.1-jre") // @Comment by SuperMonster003 on Apr 9, 2024. // ! It was ever imported and used for MediaType constants. // ! zh-CN: 曾用于 MediaType 常量的导入及使用. // Javax WS RS API (Java API for RESTful Web Services) // implementation("javax.ws.rs:javax.ws.rs-api:2.1.1") // @Hint by SuperMonster003 on Jan 11, 2026. // ! The AutoJs6 core project has deprecated the Local Broadcast Manager library, // ! replaced by LiveData and SharedFlow. // ! It is only retained for dependencies of certain libraries (such as MQTT). // ! zh-CN: // ! AutoJs6 核心项目已弃用 Local Broadcast Manager 库, // ! 由 LiveData 及 SharedFlow 替代. // ! 仅用于某些库 (如 MQTT) 的依赖而保留. // Local Broadcast Manager implementation(libs.localbroadcastmanager) } dependencies /* Reserved for auto append by IDE */ { } android { namespace = globalApplicationId compileSdk = versions.sdkVersionCompile defaultConfig { applicationId = applicationId minSdk = versions.sdkVersionMin targetSdk = versions.sdkVersionTarget versionCode = versions.appVersionCode versionName = versions.appVersionName testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" multiDexEnabled = true buildConfigField("String", "VERSION_DATE", "\"${utils.getDateString("MMM d, yyyy", "GMT+08:00")}\"") buildConfigField("String", "VSCODE_EXT_REQUIRED_VERSION", "\"${versions.vscodeExtRequiredVersion}\"") buildConfigField("boolean", "is${flavorNameInrt.uppercaseFirstChar()}", "false") javaCompileOptions { annotationProcessorOptions { mapOf( "resourcePackageName" to (this@defaultConfig.applicationId ?: globalApplicationId), "androidManifestFile" to ("$projectDir/src/main/AndroidManifest.xml") ).let { arguments(it) } } } } flavorDimensions.add(flavorDimension) productFlavors { create(flavorNameApp) { dimension = flavorDimension versionCode = versions.appVersionCode versionName = versions.appVersionName buildConfigField("String", "CHANNEL", "\"$flavorNameApp\"") buildConfigField("boolean", "is${flavorNameInrt.uppercaseFirstChar()}", "false") manifestPlaceholders.putAll( mapOf( "CHANNEL" to flavorNameApp, "appName" to "@string/app_name", "intentCategory" to "android.intent.category.LAUNCHER", "intentCategoryInrt" to "android.intent.category.DEFAULT", "authorities" to "org.autojs.autojs6.fileprovider", "icon" to "@mipmap/ic_app_launcher_adaptive", ) ) } create(flavorNameInrt) { dimension = flavorDimension applicationIdSuffix = ".$flavorNameInrt" minSdk = versions.sdkVersionMin targetSdk = versions.sdkVersionTargetInrt compileSdk = versions.sdkVersionCompile versionCode = versions.appVersionCode versionName = versions.appVersionName buildConfigField("String", "CHANNEL", "\"$flavorNameInrt\"") buildConfigField("boolean", "is${flavorNameInrt.uppercaseFirstChar()}", "true") manifestPlaceholders.putAll( mapOf( "CHANNEL" to flavorNameInrt, "appName" to "AutoJs6.$flavorNameInrt", "intentCategory" to "android.intent.category.DEFAULT", "intentCategoryInrt" to "android.intent.category.LAUNCHER", "authorities" to "org.autojs.autojs6.$flavorNameInrt.fileprovider", "icon" to "@mipmap/ic_launcher", ) ) // @Reference to kkevsekk1/AutoX (https://github.com/kkevsekk1/AutoX) by SuperMonster003 on Nov 16, 2023. // ! https://github.com/kkevsekk1/AutoX/blob/a6d482189291b460c3be60970b74c5321d26e457/inrt/build.gradle.kts#L93 // noinspection ChromeOsAbiSupport ndk.abiFilters += "" } androidResources { if (isAppAssembleTaskRequested) { ignoreAssetsPatterns.addAll(listOf(".idea", "declarations", "sample/declarations")) } if (isInrtAssembleTaskRequested) { // @Hint by SuperMonster003 on Oct 16, 2023. // ! Runtime assets will be copied from flavor "app" // ! while building an apk on org.autojs.autojs.ui.project.BuildActivity. // ! zh-CN: // ! 类 org.autojs.autojs.ui.project.BuildActivity 构建 APK 时, // ! 运行时资产文件 (runtime assets) 将由名为 "app" 的 Gradle flavor 作为源地址进行复制. ignoreAssetsPatterns.addAll(emptyList()) } } } sourceSets { // @Hint by LZX284 (https://github.com/LZX284) on Nov 15, 2023. // ! The assets file is divided into three directories according to different flavors. // ! But the files are not actually moved to avoid conflicts with the latest modifications. // ! zh-CN (translated by SuperMonster003 on Jul 26, 2024): // ! 资产文件根据不同的 Gradle flavor 被隔离为三个不同的目录. // ! 不过真实文件并没有进行移动, 以避免与最新的项目修改发生冲突. // ! // @Hint by SuperMonster003 on Nov 16, 2023. // ! The assets division idea was accepted, and it wouldn't hurt to try. :) // ! zh-CN: 资产隔离的想法可以被接受, 毕竟试一下也无妨. [笑脸符号] getByName("main") { assets.srcDirs("src/main/assets") } getByName("release") { java.srcDirs("src/release/java") } getByName("debug") { java.srcDirs("src/debug/java") } getByName(flavorNameApp) { assets.srcDirs("src/main/assets-$flavorNameApp") } getByName(flavorNameInrt) { assets.srcDirs("src/main/assets-$flavorNameInrt") } } compileOptions { isCoreLibraryDesugaringEnabled = true } packaging { listOf( "META-INF/DEPENDENCIES", "META-INF/LICENSE", "META-INF/LICENSE.*", "META-INF/LICENSE-notice.*", "META-INF/license.*", "META-INF/NOTICE", "META-INF/NOTICE.*", "META-INF/notice.*", "META-INF/ASL2.0", "META-INF/*.kotlin_module", "lib/x86/libc++_shared.so", "lib/x86_64/libc++_shared.so", "lib/armeabi-v7a/libc++_shared.so", "lib/arm64-v8a/libc++_shared.so", "lib/armeabi/libc++_shared.so", ).let { resources.pickFirsts.addAll(it) } listOf( "com/**/*", "frameworks/**/*", "junit/**/*", "LICENSE-junit.txt", "spec.txt", "EmojiReference.txt", ).let { resources.excludes.addAll(it) } if (isInrtTaskRequested) { listOf( "**/prob_emit.txt", // Jieba Analysis (zh-CN: 结巴分词) "**/dict-chinese-*.db.gzip", // Jieba Analysis (zh-CN: 结巴分词) ).let { resources.excludes.addAll(it) } } jniLibs { // @Reference to kkevsekk1/AutoX (https://github.com/kkevsekk1/AutoX) by SuperMonster003 on Nov 16, 2023. // ! https://github.com/kkevsekk1/AutoX/blob/a6d482189291b460c3be60970b74c5321d26e457/inrt/build.gradle.kts#L91 excludes += "*" useLegacyPackaging = true } } lint { abortOnError = false } signingConfigs { if (signs.isValid) { create(buildTypeRelease) { storeFile = signs.properties["storeFile"]?.let { file(it as String) } keyPassword = signs.properties["keyPassword"] as String keyAlias = signs.properties["keyAlias"] as String storePassword = signs.properties["storePassword"] as String } } } buildTypes { val proguardFiles = arrayOf( getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro", ) val niceSigningConfig = takeIf { signs.isValid }?.let { signingConfigs.getByName(buildTypeRelease) } debug { isMinifyEnabled = getByName(buildTypeRelease).isMinifyEnabled proguardFiles(*proguardFiles) niceSigningConfig?.let { signingConfig = it } } release { isMinifyEnabled = false proguardFiles(*proguardFiles) niceSigningConfig?.let { signingConfig = it } } } buildFeatures { aidl = true viewBinding = true // @Hint by SuperMonster003 on Aug 14, 2023. // ! Substitution of "android.defaults.buildfeatures.buildconfig=true" // ! zh-CN: "android.defaults.buildfeatures.buildconfig=true" 的替代方案 buildConfig = true // @Archived by SuperMonster003 on Sep 23, 2024. // ! Jetpack Compose // # compose = true // # composeOptions { // # kotlinCompilerExtensionVersion = "1.5.12" // # } } applicationVariants.all { mergeAssetsProvider.configure { doLast { mapOf( "dir" to outputDir, "includes" to when (variantName.startsWith(flavorNameInrt)) { true -> listOf( "mlkit-google-ocr-models/**/*", "mlkit_barcode_models/**/*", "models/**/*", "modules/obsolete/**/*", "openccdata/**/*", "project/**/*", "android-devices.db", "autojs.keystore", "**/prob_emit.txt", // Jieba Analysis (zh-CN: 结巴分词) "**/dict-chinese-*.db.gzip", // Jieba Analysis (zh-CN: 结巴分词) ) else -> listOf( "declarations/**/*", "sample/declarations/**/*", "modules/obsolete/**/*", ) }, ).let { delete(fileTree(it)) } } } outputs.map { it as BaseVariantOutputImpl }.forEach { it.outputFileName = run { val variant = this@all as ApplicationVariantImpl val autojs = variant.applicationId.replace("^.+\\.(.+)$".toRegex(), "$1") // e.g. autojs6 val version = variant.versionName.replace("\\s".toRegex(), "-") // e.g. 6.1.0 val architecture = it.getFilter("ABI") ?: "universal" val extension = utils.FILE_EXTENSION_APK "$autojs-v$version-$architecture.$extension".lowercase() } } } splits { // Configures multiple APKs based on ABI. abi { // Enables building multiple APKs per ABI. isEnable = !isInrtAssembleTaskRequested // By default, all ABIs are included, so use reset() and include to specify that we only // want APKs for x86 and x86_64. // Resets the list of ABIs that Gradle should create APKs for to none. reset() // Specifies a list of ABIs that Gradle should create APKs for. include("arm64-v8a", "x86_64", "armeabi-v7a", "x86", "armeabi") // Specifies that we do not want to also generate a universal APK that includes all ABIs. isUniversalApk = true } } } tasks { withType(JavaCompile::class.java) { options.encoding = "UTF-8" // @Hint by SuperMonster003 on May 18, 2022. // ! Comment or remove this option if you are tired of plenty of warnings. :) // ! zh-CN: 注释或移除此选项可避免过多警告消息造成的困扰. [笑脸符号] // options.compilerArgs.addAll(listOf("-Xlint:deprecation", "-Xlint:unchecked")) } register("appendDigestToReleasedFiles") { listOf(flavorNameApp, flavorNameInrt).forEach { flavorName -> val src = "$flavorName/$buildTypeRelease" val dst = "${src}s" val ext = utils.FILE_EXTENSION_APK if (!file(src).isDirectory) { return@forEach } from(src); into(dst); include("*.$ext") rename { name -> utils.digestCRC32(file("${src}/$name")).let { digest -> name.replace(Regex("^(.+?)(\\.$ext)$"), "$1-$digest$2") } } doLast { println("Destination: ${file(dst)}") } } } } extra { versions.handleIfNeeded(project, flavorNameApp, listOf(buildTypeDebug, buildTypeRelease)) }