@file:Suppress("UnstableApiUsage", "SpellCheckingInspection") import com.android.build.api.dsl.Packaging import io.sentry.android.gradle.extensions.InstrumentationFeature import io.sentry.android.gradle.instrumentation.logcat.LogcatLevel import com.android.build.api.variant.FilterConfiguration.FilterType.* import java.io.ByteArrayOutputStream import java.util.Properties import java.io.File plugins { // Gradle doesn't allow conditionally enabling/disabling plugins id("io.sentry.android.gradle") id("com.android.application") id("com.mikepenz.aboutlibraries.plugin") kotlin("android") kotlin("kapt") } // apply realm-android apply(plugin = "realm-android") val hasSentryConfig = File(rootProject.projectDir, "sentry.properties").exists() android { // functions to get git info: gitCommitHash, gitBranch, gitRemote val gitCommitHash by lazy { val stdout = ByteArrayOutputStream() rootProject.exec { commandLine("git", "rev-parse", "--short", "HEAD") standardOutput = stdout } stdout.toString().trim() } val gitBranch by lazy { val stdout = ByteArrayOutputStream() rootProject.exec { commandLine("git", "rev-parse", "--abbrev-ref", "HEAD") standardOutput = stdout } stdout.toString().trim() } val gitRemote by lazy { val stdout = ByteArrayOutputStream() rootProject.exec { commandLine("git", "config", "--get", "remote.origin.url") standardOutput = stdout } stdout.toString().trim() } namespace = "com.fox2code.mmm" compileSdk = 33 ndkVersion = "25.2.9519653" defaultConfig { applicationId = "com.fox2code.mmm" minSdk = 24 targetSdk = 33 versionCode = 65 versionName = "2.0.0" vectorDrawables { useSupportLibrary = true } multiDexEnabled = true } splits { // Configures multiple APKs based on ABI. abi { // Enables building multiple APKs per ABI. isEnable = true // By default all ABIs are included, so use reset() and include to specify that you only // want APKs for x86 and x86_64. // Resets the list of ABIs for Gradle to create APKs for to none. reset() // Specifies a list of ABIs for Gradle to create APKs for. include("x86", "x86_64", "arm64-v8a", "armeabi-v7a") // Specifies that you don't want to also generate a universal APK that includes all ABIs. isUniversalApk = true } } buildTypes { getByName("release") { isMinifyEnabled = true isShrinkResources = true proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro") } getByName("debug") { applicationIdSuffix = ".debug" isDebuggable = true // ONLY FOR TESTING SENTRY // minifyEnabled true // shrinkResources true // proguardFiles getDefaultProguardFile("proguard-android-optimize.txt"),"proguard-rules.pro" } } flavorDimensions.add("type") productFlavors { create("default") { // debug http requests. do not set this to true if you care about performance!!!!! buildConfigField("boolean", "DEBUG_HTTP", "false") // Latest commit hash as BuildConfig.COMMIT_HASH buildConfigField("String", "COMMIT_HASH", "\"" + gitCommitHash + "\"") // Get the current branch name as BuildConfig.BRANCH_NAME buildConfigField("String", "BRANCH_NAME", "\"" + gitBranch + "\"") // Get remote url as BuildConfig.REMOTE_URL buildConfigField("String", "REMOTE_URL", "\"" + gitRemote + "\"") dimension = "type" buildConfigField("boolean", "ENABLE_AUTO_UPDATER", "true") buildConfigField("boolean", "DEFAULT_ENABLE_CRASH_REPORTING", "true") buildConfigField("boolean", "DEFAULT_ENABLE_CRASH_REPORTING_PII", "true") buildConfigField("boolean", "DEFAULT_ENABLE_ANALYTICS", "true") val properties = Properties() if (project.rootProject.file("local.properties").exists()) { // grab matomo.url buildConfigField("String", "ANALYTICS_ENDPOINT", "\"" + properties.getProperty("matomo.url", "https://s-api.androidacy.com/matomo.php" + "\"")) } else { buildConfigField("String", "ANALYTICS_ENDPOINT", "\"https://s-api.androidacy.com/matomo.php\"") } buildConfigField("boolean", "ENABLE_PROTECTION", "true") // Get the androidacy client ID from the androidacy.properties val propertiesA = Properties() // If androidacy.properties doesn"t exist, use the default client ID which is heavily // rate limited to 30 requests per minute if (project.rootProject.file("androidacy.properties").exists()) { propertiesA.load(project.rootProject.file("androidacy.properties").inputStream()) properties.setProperty("client_id", "\"" + propertiesA.getProperty("client_id", "5KYccdYxWB2RxMq5FTbkWisXi2dS6yFN9R7RVlFCG98FRdz6Mf5ojY2fyJCUlXJZ") + "\"") } else { properties.setProperty("client_id", "5KYccdYxWB2RxMq5FTbkWisXi2dS6yFN9R7RVlFCG98FRdz6Mf5ojY2fyJCUlXJZ") } buildConfigField("String", "ANDROIDACY_CLIENT_ID", "\"" + propertiesA.getProperty("client_id") + "\"") // If client ID is empty, disable androidacy if (propertiesA.getProperty("client_id").isEmpty()) { buildConfigField("java.util.List", "ENABLED_REPOS", "java.util.Arrays.asList(\"\")") } else { buildConfigField("java.util.List", "ENABLED_REPOS", "java.util.Arrays.asList(\"androidacy_repo\")",) } } create("fdroid") { dimension = "type" applicationIdSuffix = ".fdroid" // debug http requests. do not set this to true if you care about performance!!!!! buildConfigField("boolean", "DEBUG_HTTP", "false") // Latest commit hash as BuildConfig.COMMIT_HASH buildConfigField("String", "COMMIT_HASH", "\"" + gitCommitHash + "\"") // Get the current branch name as BuildConfig.BRANCH_NAME buildConfigField("String", "BRANCH_NAME", "\"" + gitBranch + "\"") // Get remote url as BuildConfig.REMOTE_URL buildConfigField("String", "REMOTE_URL", "\"" + gitRemote + "\"") // Need to disable auto-updater for F-Droid flavor because their inclusion policy // forbids downloading blobs from third-party websites (and F-Droid APK isn"t signed // with our keys, so the APK wouldn"t install anyways). buildConfigField("boolean", "ENABLE_AUTO_UPDATER", "false") // Disable crash reporting for F-Droid flavor by default buildConfigField("boolean", "DEFAULT_ENABLE_CRASH_REPORTING", "false") buildConfigField("boolean", "DEFAULT_ENABLE_CRASH_REPORTING_PII", "false") buildConfigField("boolean", "DEFAULT_ENABLE_ANALYTICS", "false") val properties = Properties() if (project.rootProject.file("local.properties").exists()) { // grab matomo.url buildConfigField("String", "ANALYTICS_ENDPOINT", properties.getProperty("matomo.url", "https://s-api.androidacy.com/matomo.php")) } else { buildConfigField("String", "ANALYTICS_ENDPOINT", "https://s-api.androidacy.com/matomo.php") } buildConfigField("boolean", "ENABLE_PROTECTION", "true") // Repo with ads or tracking feature are disabled by default for the // F-Droid flavor. at the same time, the alt repo isn"t particularly trustworthy buildConfigField("java.util.List", "ENABLED_REPOS", "java.util.Arrays.asList(\"\")",) // Get the androidacy client ID from the androidacy.properties val propertiesA = Properties() // If androidacy.properties doesn"t exist, use the fdroid client ID which is limited // to 50 requests per minute if (project.rootProject.file("androidacy.properties").exists()) { propertiesA.load(project.rootProject.file("androidacy.properties").inputStream()) buildConfigField("String", "ANDROIDACY_CLIENT_ID", propertiesA.getProperty("client_id", "dQ1p7X8bF14PVJ7wAU6ORVjPB2IeTinsuAZ8Uos6tQiyUdUyIjSyZSmN54QBbaTy")) } else { properties.setProperty("client_id", "dQ1p7X8bF14PVJ7wAU6ORVjPB2IeTinsuAZ8Uos6tQiyUdUyIjSyZSmN54QBbaTy") } versionNameSuffix = "-froid" } } compileOptions { sourceCompatibility = JavaVersion.VERSION_17 targetCompatibility = JavaVersion.VERSION_17 } lint { disable.add("MissingTranslation") } @Suppress("UNUSED_EXPRESSION") fun Packaging.() { jniLibs { useLegacyPackaging = true } } } sentry { includeProguardMapping.set(true) autoUploadProguardMapping.set(hasSentryConfig) experimentalGuardsquareSupport.set(true) uploadNativeSymbols.set(hasSentryConfig) includeNativeSources.set(true) tracingInstrumentation { enabled.set(true) features.set(setOf(InstrumentationFeature.DATABASE, InstrumentationFeature.FILE_IO, InstrumentationFeature.OKHTTP, InstrumentationFeature.COMPOSE)) logcat { enabled.set(true) minLevel.set(LogcatLevel.WARNING) } } autoInstallation { enabled.set(true) sentryVersion.set("6.17.0") } includeDependenciesReport.set(true) } val abiCodes = mapOf("armeabi-v7a" to 1, "x86" to 2, "x86_64" to 3) // For per-density APKs, create a similar map: // val densityCodes = mapOf("mdpi" to 1, "hdpi" to 2, "xhdpi" to 3) // For each APK output variant, override versionCode with a combination of // abiCodes * 1000 + variant.versionCode. In this example, variant.versionCode // is equal to defaultConfig.versionCode. If you configure product flavors that // define their own versionCode, variant.versionCode uses that value instead. androidComponents { onVariants { variant -> // Assigns a different version code for each output APK // other than the universal APK. variant.outputs.forEach { output -> val name = output.filters.find { it.filterType == ABI }?.identifier // Stores the value of abiCodes that is associated with the ABI for this variant. val baseAbiCode = abiCodes[name] // Because abiCodes.get() returns null for ABIs that are not mapped by ext.abiCodes, // the following code doesn't override the version code for universal APKs. // However, because you want universal APKs to have the lowest version code, // this outcome is desirable. if (baseAbiCode != null) { // Assigns the new version code to output.versionCode, which changes the version code // for only the output APK, not for the variant itself. @Suppress("USELESS_CAST") val versioCode = output.versionCode.get() as Int output.versionCode.set(baseAbiCode * 1000 + versioCode) } } } } aboutLibraries { // Specify the additional licenses additionalLicenses = arrayOf("LGPL_3_0_only", "Apache_2_0") } configurations { // Access all imported libraries all { // Exclude all libraries with the following group and module exclude(group = "org.chromium.net", module = "cronet-api") exclude(group = "org.jetbrains", module = "annotations-java5") } } dependencies { // UI implementation("androidx.appcompat:appcompat:1.6.1") implementation("androidx.activity:activity-ktx:1.7.1") implementation("androidx.emoji2:emoji2:1.3.0") implementation("androidx.emoji2:emoji2-views-helper:1.3.0") implementation("androidx.preference:preference-ktx:1.2.0") implementation("androidx.constraintlayout:constraintlayout:2.1.4") implementation("androidx.recyclerview:recyclerview:1.3.0") implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.1.0") implementation("androidx.webkit:webkit:1.6.1") implementation("com.google.android.material:material:1.8.0") implementation("dev.rikka.rikkax.layoutinflater:layoutinflater:1.3.0") implementation("dev.rikka.rikkax.insets:insets:1.3.0") implementation("com.github.KieronQuinn:MonetCompat:0.4.1") implementation("com.github.Fox2Code:FoxCompat:0.2.0") implementation("com.mikepenz:aboutlibraries:10.6.2") // Utils implementation("androidx.work:work-runtime:2.8.1") implementation("com.squareup.okhttp3:okhttp:5.0.0-alpha.10") implementation("com.squareup.okhttp3:okhttp-dnsoverhttps:5.0.0-alpha.10") // logging interceptor implementation("com.squareup.okhttp3:logging-interceptor:5.0.0-alpha.10") // Chromium cronet from androidacy implementation("com.androidacy:cronet-common:112.0.5615.62") implementation("com.androidacy:cronet-native:112.0.5615.62") implementation("com.androidacy:cronet-api:112.0.5615.62") // protobuf - fixes a crash on some devices implementation("com.google.protobuf:protobuf-javalite:3.22.2") implementation("com.github.topjohnwu.libsu:io:5.0.5") implementation("com.github.Fox2Code:RosettaX:1.0.9") implementation("com.github.Fox2Code:AndroidANSI:1.0.1") // sentry implementation("io.sentry:sentry-android:6.17.0") implementation("io.sentry:sentry-android-timber:6.17.0") implementation("io.sentry:sentry-android-fragment:6.17.0") implementation("io.sentry:sentry-android-okhttp:6.17.0") implementation("io.sentry:sentry-kotlin-extensions:6.17.0") implementation("io.sentry:sentry-android-ndk:6.17.0") // Markdown // TODO: switch to an updated implementation implementation("io.noties.markwon:core:4.6.2") implementation("io.noties.markwon:html:4.6.2") implementation("io.noties.markwon:image:4.6.2") implementation("io.noties.markwon:syntax-highlight:4.6.2") implementation("com.google.net.cronet:cronet-okhttp:0.1.0") implementation("com.caverock:androidsvg:1.4") implementation("androidx.core:core-ktx:1.10.0") // timber implementation("com.jakewharton.timber:timber:5.0.1") // ksp implementation("com.google.devtools.ksp:symbol-processing-api:1.8.20-1.0.10") implementation("androidx.security:security-crypto:1.1.0-alpha06") // some utils implementation("commons-io:commons-io:20030203.000550") implementation("org.apache.commons:commons-compress:1.23.0") // analytics implementation("com.github.matomo-org:matomo-sdk-android:HEAD") // annotations implementation("org.jetbrains:annotations-java5:24.0.1") } android { ndkVersion = "25.2.9519653" dependenciesInfo { includeInApk = false includeInBundle = false } buildFeatures { viewBinding = true buildConfig = true } tasks.withType { kotlinOptions { jvmTarget = "1.8" } } //noinspection GrDeprecatedAPIUsage buildToolsVersion = "34.0.0 rc3" } kotlin { jvmToolchain(17) } java { toolchain { languageVersion.set(JavaLanguageVersion.of(17)) } }