plugins { // Gradle doesn't allow conditionally enabling/disabling plugins id "io.sentry.android.gradle" version "3.4.0" id 'com.android.application' id 'com.mikepenz.aboutlibraries.plugin' id 'org.jetbrains.kotlin.android' id 'org.jetbrains.kotlin.kapt' } apply plugin: "realm-android" android { namespace "com.fox2code.mmm" compileSdk 33 ndkVersion "25.1.8937393" signingConfigs { release { // Everything comes from local.properties Properties properties = new Properties() if (project.rootProject.file('local.properties').exists()) { properties.load(project.rootProject.file('local.properties').newDataInputStream()) // java.lang.IllegalArgumentException: path may not be null or empty string. path='null' if (properties.getProperty('keystore.file') != null) { // FFS DO NOT CHANGE THIS, IT WILL BREAK THE BUILD storeFile file(properties.getProperty('keystore.file')) storePassword properties.getProperty('keystore.password') keyAlias 'key0' keyPassword properties.getProperty('keystore.password') } } enableV3Signing = true enableV4Signing = true } debug { // Everything comes from local.properties Properties properties = new Properties() if (project.rootProject.file('local.properties').exists()) { properties.load(project.rootProject.file('local.properties').newDataInputStream()) // java.lang.IllegalArgumentException: path may not be null or empty string. path='null' if (properties.getProperty('keystore.file') != null) { // FFS DO NOT CHANGE THIS, IT WILL BREAK THE BUILD storeFile file(properties.getProperty('keystore.file')) storePassword properties.getProperty('keystore.password') keyAlias 'key0' keyPassword properties.getProperty('keystore.password') } } enableV3Signing = true enableV4Signing = true } } defaultConfig { applicationId "com.fox2code.mmm" minSdk 24 targetSdk 33 versionCode 64 versionName "2.0.0-beta.1" archivesBaseName = "FoxMMM-v$versionName" vectorDrawables { useSupportLibrary true } } splits { // Configures multiple APKs based on ABI. abi { // Enables building multiple APKs per ABI. enable true // 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 "x86", "x86_64", "armeabi-v7a", "arm64-v8a" // Specifies that we do not want to also generate a universal APK that includes all ABIs. universalApk true } } buildTypes { release { minifyEnabled true shrinkResources true proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' signingConfig signingConfigs.release } debug { applicationIdSuffix '.debug' debuggable true signingConfig signingConfigs.debug // ONLY FOR TESTING SENTRY // minifyEnabled true // shrinkResources true // proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'),'proguard-rules.pro' } } //noinspection GrDeprecatedAPIUsage flavorDimensions "type" productFlavors { "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 def gitCommitHash = 'git rev-parse --short HEAD'.execute([], project.rootDir).text.trim() buildConfigField "String", "COMMIT_HASH", "\"${gitCommitHash}\"" // Get the current branch name as BuildConfig.BRANCH_NAME def gitBranchName = 'git rev-parse --abbrev-ref HEAD'.execute([], project.rootDir).text.trim() buildConfigField "String", "BRANCH_NAME", "\"${gitBranchName}\"" // Get remote url as BuildConfig.REMOTE_URL def gitRemoteUrl = 'git config --get remote.origin.url'.execute([], project.rootDir).text.trim() buildConfigField "String", "REMOTE_URL", "\"${gitRemoteUrl}\"" dimension "type" buildConfigField "boolean", "ENABLE_AUTO_UPDATER", "true" buildConfigField "boolean", "DEFAULT_ENABLE_CRASH_REPORTING", "true" if (hasSentryConfig) { Properties properties = new Properties() try (FileInputStream fis = new FileInputStream(sentryConfigFile)) { properties.load(fis) } buildConfigField "String", "SENTRY_TOKEN", '"' + properties.getProperty("auth." + "token") + '"' } else { buildConfigField "String", "SENTRY_TOKEN", '""' } // Get the androidacy client ID from the androidacy.properties Properties properties = new 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()) { properties.load(project.rootProject.file('androidacy.properties').newDataInputStream()) } else { properties.setProperty('client_id', '"5KYccdYxWB2RxMq5FTbkWisXi2dS6yFN9R7RVlFCG98FRdz6Mf5ojY2fyJCUlXJZ"') } buildConfigField("String", "ANDROIDACY_CLIENT_ID", properties.getProperty('client_id')) // If client ID is empty, disable androidacy if (properties.getProperty('client_id').isEmpty()) { buildConfigField("java.util.List", "ENABLED_REPOS", "java.util.Arrays.asList(\"magisk_alt_repo\")") } else { buildConfigField("java.util.List", "ENABLED_REPOS", "java.util.Arrays.asList(\"androidacy_repo\")",) } } 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 def gitCommitHash = 'git rev-parse --short HEAD'.execute([], project.rootDir).text.trim() buildConfigField "String", "COMMIT_HASH", "\"${gitCommitHash}\"" // Get the current branch name as BuildConfig.BRANCH_NAME def gitBranchName = 'git rev-parse --abbrev-ref HEAD'.execute([], project.rootDir).text.trim() buildConfigField "String", "BRANCH_NAME", "\"${gitBranchName}\"" // Get remote url as BuildConfig.REMOTE_URL def gitRemoteUrl = 'git config --get remote.origin.url'.execute([], project.rootDir).text.trim() buildConfigField "String", "REMOTE_URL", "\"${gitRemoteUrl}\"" // 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" if (hasSentryConfig) { Properties properties = new Properties() try (FileInputStream fis = new FileInputStream(sentryConfigFile)) { properties.load(fis) } buildConfigField "String", "SENTRY_TOKEN", '"' + properties.getProperty("auth." + "token") + '"' } else { buildConfigField "String", "SENTRY_TOKEN", '""' } // 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 Properties properties = new 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()) { properties.load(project.rootProject.file('androidacy.properties').newDataInputStream()) } else { properties.setProperty('client_id', '"dQ1p7X8bF14PVJ7wAU6ORVjPB2IeTinsuAZ8Uos6tQiyUdUyIjSyZSmN54QBbaTy"') } buildConfigField("String", "ANDROIDACY_CLIENT_ID", properties.getProperty('client_id')) versionNameSuffix '-froid' } } compileOptions { sourceCompatibility JavaVersion.VERSION_11 targetCompatibility JavaVersion.VERSION_11 } lint { disable 'MissingTranslation' disable 'TypographyEllipsis' } } aboutLibraries { additionalLicenses = ["LGPL_3_0_only", "Apache_2_0"] } configurations { // Access all imported libraries compileOnly.extendsFrom(runtimeOnly) } // "true" is not allowed inside this block, use "hasSentryConfig" instead. // This is because gradle doesn't allow to enable/disable plugins conditionally sentry { // Disable sentry on F-Droid flavor ignoredFlavors = [] // Disables or enables the handling of Proguard mapping for Sentry. // If enabled the plugin will generate a UUID and will take care of // uploading the mapping to Sentry. If disabled, all the logic // related to proguard mapping will be excluded. // Default is enabled. includeProguardMapping = hasSentryConfig // Whether the plugin should attempt to auto-upload the mapping file to Sentry or not. // If disabled the plugin will run a dry-run and just generate a UUID. // The mapping file has to be uploaded manually via sentry-cli in this case. // Default is enabled. autoUploadProguardMapping = hasSentryConfig // Experimental flag to turn on support for GuardSquare's tools integration (Dexguard and External Proguard). // If enabled, the plugin will try to consume and upload the mapping file produced by Dexguard and External Proguard. // Default is disabled. experimentalGuardsquareSupport = hasSentryConfig // Disables or enables the automatic configuration of Native Symbols // for Sentry. This executes sentry-cli automatically so // you don't need to do it manually. // Default is disabled. uploadNativeSymbols = hasSentryConfig // Does or doesn't include the source code of native code for Sentry. // This executes sentry-cli with the --include-sources param. automatically so // you don't need to do it manually. // Default is disabled. includeNativeSources = hasSentryConfig // Enable or disable the tracing instrumentation. // Does auto instrumentation for specified features through bytecode manipulation. // Default is enabled. tracingInstrumentation { enabled = hasSentryConfig } // Enable auto-installation of Sentry components (sentry-android SDK and okhttp, timber and fragment integrations). autoInstallation { sentryVersion = '6.12.1' } // temp fix for gradle bug includeDependenciesReport = false } configurations { implementation.exclude group: 'org.jetbrains', module: 'annotations' } dependencies { // UI implementation 'androidx.appcompat:appcompat:1.6.0' implementation "androidx.activity:activity-ktx:1.7.0-alpha04" implementation 'androidx.emoji2:emoji2:1.2.0' implementation 'androidx.emoji2:emoji2-views-helper:1.2.0' implementation 'androidx.preference:preference-ktx:1.2.0' implementation 'androidx.constraintlayout:constraintlayout:2.1.4' implementation 'androidx.recyclerview:recyclerview:1.2.1' implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0' implementation 'androidx.webkit:webkit:1.6.0' implementation 'com.google.android.material:material:1.8.0' implementation "dev.rikka.rikkax.layoutinflater:layoutinflater:1.2.0" implementation "dev.rikka.rikkax.insets:insets:1.3.0" implementation 'com.github.Dimezis:BlurView:version-2.0.2' implementation 'com.github.KieronQuinn:MonetCompat:0.4.1' implementation 'com.github.Fox2Code:FoxCompat:0.2.0' // Update the version code in the root build.gradle implementation "com.mikepenz:aboutlibraries:${latestAboutLibsRelease}" // Utils implementation 'androidx.work:work-runtime:2.7.1' implementation 'com.squareup.okhttp3:okhttp:5.0.0-alpha.10' implementation 'com.squareup.okhttp3:okhttp-dnsoverhttps:5.0.0-alpha.10' // Chromium cronet from androidacy implementation 'com.androidacy:cronet-common:109.0.5414.75' implementation 'com.androidacy:cronet-native:109.0.5414.75' // Force prefer our own version of Cronet implementation 'com.github.topjohnwu.libsu:io:5.0.1' implementation 'com.github.Fox2Code:RosettaX:1.0.9' implementation 'com.github.Fox2Code:AndroidANSI:1.0.1' // sentry implementation "io.sentry:sentry-android:$sentry_version" implementation "io.sentry:sentry-android-timber:$sentry_version" implementation "io.sentry:sentry-android-fragment:$sentry_version" implementation "io.sentry:sentry-android-okhttp:$sentry_version" // Markdown 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" // Icons // implementation "com.mikepenz:iconics-core:3.2.5" //implementation "androidx.appcompat:appcompat:${versions.appCompat}" implementation 'androidx.core:core-ktx:1.9.0' implementation "io.sentry:sentry-kotlin-extensions:$sentry_version" // timber implementation 'com.jakewharton.timber:timber:5.0.1' // ksp implementation "com.google.devtools.ksp:symbol-processing-api:1.8.0-1.0.8" implementation "androidx.security:security-crypto:1.1.0-alpha04" implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.5.1' implementation 'androidx.activity:activity-compose:1.6.1' implementation platform('androidx.compose:compose-bom:2022.10.00') implementation 'androidx.compose.ui:ui' implementation 'androidx.compose.ui:ui-graphics' implementation 'androidx.compose.ui:ui-tooling-preview' implementation 'androidx.compose.material3:material3' androidTestImplementation platform('androidx.compose:compose-bom:2022.10.00') androidTestImplementation 'androidx.compose.ui:ui-test-junit4' debugImplementation 'androidx.compose.ui:ui-tooling' debugImplementation 'androidx.compose.ui:ui-test-manifest' } if (hasSentryConfig) { Properties properties = new Properties() try (FileInputStream fis = new FileInputStream(sentryConfigFile)) { properties.load(fis) } tasks.withType(Exec).configureEach { environment "SENTRY_PROJECT", properties.getProperty("defaults.project") environment "SENTRY_ORG", properties.getProperty("defaults.org") environment "SENTRY_URL", properties.getProperty("defaults.url") environment "SENTRY_AUTH_TOKEN", properties.getProperty("auth.token") } } android { ndkVersion '25.1.8937393' dependenciesInfo { includeInApk true includeInBundle true } buildFeatures { viewBinding true compose true } kotlinOptions { jvmTarget= '1.8' } //noinspection GrDeprecatedAPIUsage buildToolsVersion '33.0.1' composeOptions { kotlinCompilerExtensionVersion '1.3.2' } packagingOptions { resources { excludes += '/META-INF/{AL2.0,LGPL2.1}' } } } kotlin { jvmToolchain { languageVersion.set(JavaLanguageVersion.of(11)) // "8" } } // Safeguard (Do not remove) final File res = new File(projectDir, "src/main/res") for (String name : res.list()) { // Character.isDigit is required to make sure // we don't confuse "values-vi" as "values-v69" if (name.startsWith("values-v") && Character.isDigit(name.charAt(8))) { final String ext = name + "/strings.xml" if (new File(res, ext).exists()) { final String errMessage = "String should not be defined in " + ext + " use values/strings.xml instead" println(errMessage) throw new GradleException(errMessage) } } }