diff --git a/app/build.gradle b/app/build.gradle deleted file mode 100644 index 642bf14..0000000 --- a/app/build.gradle +++ /dev/null @@ -1,481 +0,0 @@ -import io.sentry.android.gradle.extensions.InstrumentationFeature -import com.android.build.OutputFile - -plugins { - // Gradle doesn't allow conditionally enabling/disabling plugins - id "io.sentry.android.gradle" - 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.2.9519653" - 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 - enableV1Signing = true - enableV2Signing = 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 - enableV1Signing = true - enableV2Signing = true - } - } - - defaultConfig { - applicationId "com.fox2code.mmm" - minSdk 24 - targetSdk 33 - versionCode 65 - versionName "2.0.0" - archivesBaseName = "FoxMMM-v$versionName" - vectorDrawables { - useSupportLibrary true - } - multiDexEnabled 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' - } - } - - 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" - buildConfigField "boolean", "DEFAULT_ENABLE_CRASH_REPORTING_PII", "true" - buildConfigField "boolean", "DEFAULT_ENABLE_ANALYTICS", "true" - Properties propertiesL = new Properties() - if (project.rootProject.file('local.properties').exists()) { - // grab matomo.url - buildConfigField "String", "ANALYTICS_ENDPOINT", '"' + propertiesL.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" - 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" - buildConfigField "boolean", "DEFAULT_ENABLE_CRASH_REPORTING_PII", "false" - buildConfigField "boolean", "DEFAULT_ENABLE_ANALYTICS", "false" - Properties propertiesL = new Properties() - if (project.rootProject.file('local.properties').exists()) { - // grab matomo.url - buildConfigField "String", "ANALYTICS_ENDPOINT", '"' + propertiesL.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" - - 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_17 - targetCompatibility JavaVersion.VERSION_17 - } - - lint { - disable 'MissingTranslation' - } - - packagingOptions { - jniLibs { - useLegacyPackaging = true - } - } -} - -ext.abiCodes = ['armeabi-v7a':1, x86:2, x86_64:3, 'arm64-v8a':4] - -// For per-density APKs, create a similar map: -// ext.densityCodes = ['mdpi': 1, 'hdpi': 2, 'xhdpi': 3] - -// For each APK output variant, override versionCode with a combination of -// ext.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. -android.applicationVariants.all { variant -> - - // Assigns a different version code for each output APK - // other than the universal APK. - variant.outputs.each { output -> - - // Stores the value of ext.abiCodes that is associated with the ABI for this variant. - def baseAbiVersionCode = - // Determines the ABI for this variant and returns the mapped value. - project.ext.abiCodes.get(output.getFilter(OutputFile.ABI)) - - // 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 (baseAbiVersionCode != null) { - - // Assigns the new version code to versionCodeOverride, which changes the - // version code for only the output APK, not for the variant itself. Skipping - // this step causes Gradle to use the value of variant.versionCode for the APK. - output.versionCodeOverride = - baseAbiVersionCode * 1000 + variant.versionCode - } - } -} - -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 { - ignoredFlavors = [] - - // All the symbol upload logic has to be disabled for f-droid flavor, as we don't have a way to provide an auth token to f-droid - - // 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 = true - features = EnumSet.allOf(InstrumentationFeature) - } - - // Enable auto-installation of Sentry components (sentry-android SDK and okhttp, timber and fragment integrations). - autoInstallation { - sentryVersion = sentry_version - } - - // temp fix for gradle bug - includeDependenciesReport = true -} - -configurations { - implementation.exclude group: 'org.jetbrains', module: 'annotations' - // exclude chromium cronet-api - implementation.exclude group: 'org.chromium.net', module: 'cronet-api' -} - -dependencies { - // UI - implementation 'androidx.appcompat:appcompat:1.6.1' - implementation 'androidx.activity:activity-ktx:1.7.0' - 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 platform('io.sentry:sentry-bom:6.17.0') - implementation "io.sentry:sentry-android" - implementation "io.sentry:sentry-android-timber" - implementation "io.sentry:sentry-android-fragment" - implementation "io.sentry:sentry-android-okhttp" - implementation "io.sentry:sentry-kotlin-extensions" - implementation "io.sentry:sentry-android-ndk" - - // 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-alpha05" - - // 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:4.1.4' - -} - -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.2.9519653' - dependenciesInfo { - includeInApk false - includeInBundle false - } - buildFeatures { - viewBinding true - buildConfig true - } - - kotlinOptions { - jvmTarget = JavaVersion.VERSION_17 - } - //noinspection GrDeprecatedAPIUsage - buildToolsVersion '34.0.0 rc3' -} - - -kotlin { - jvmToolchain { - languageVersion.set(JavaLanguageVersion.of(17)) - } -} - -// Safeguard (Do not remove. Or do, i'm just a comment not a cop) -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) - } - } -} diff --git a/app/build.gradle.kts b/app/build.gradle.kts new file mode 100644 index 0000000..06a4377 --- /dev/null +++ b/app/build.gradle.kts @@ -0,0 +1,402 @@ +@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") + "\"") + } 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(\"magisk_alt_repo\")") + } 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")) + } 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)) + } +} \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 7cdcf8e..fa3dec7 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -65,7 +65,6 @@ android:theme="@style/Theme.MagiskModuleManager" android:usesCleartextTraffic="false" android:forceDarkAllowed="false" - android:extractNativeLibs="true" tools:ignore="ManifestResource" tools:replace="android:supportsRtl" tools:targetApi="tiramisu"> diff --git a/app/src/main/java/com/fox2code/mmm/CrashHandler.java b/app/src/main/java/com/fox2code/mmm/CrashHandler.java index 90d077c..6434ee3 100644 --- a/app/src/main/java/com/fox2code/mmm/CrashHandler.java +++ b/app/src/main/java/com/fox2code/mmm/CrashHandler.java @@ -70,7 +70,7 @@ public class CrashHandler extends FoxActivity { } // disable feedback if sentry is disabled //noinspection ConstantConditions - if (crashReportingEnabled && !BuildConfig.SENTRY_TOKEN.equals("") && lastEventId != null) { + if (crashReportingEnabled && lastEventId != null) { // get name, email, and message fields EditText name = findViewById(R.id.feedback_name); EditText email = findViewById(R.id.feedback_email); @@ -89,14 +89,17 @@ public class CrashHandler extends FoxActivity { Throwable sentryException = (Throwable) getIntent().getSerializableExtra("sentryException"); new Thread(() -> { try { - UserFeedback userFeedback = new UserFeedback(Sentry.captureException(sentryException)); - // Setups the JSON body - if (nameString[0].equals("")) nameString[0] = "Anonymous"; - if (emailString[0].equals("")) emailString[0] = "Anonymous"; - userFeedback.setName(nameString[0]); - userFeedback.setEmail(emailString[0]); - userFeedback.setComments(description.getText().toString()); - Sentry.captureUserFeedback(userFeedback); + UserFeedback userFeedback; + if (sentryException != null) { + userFeedback = new UserFeedback(Sentry.captureException(sentryException)); + // Setups the JSON body + if (nameString[0].equals("")) nameString[0] = "Anonymous"; + if (emailString[0].equals("")) emailString[0] = "Anonymous"; + userFeedback.setName(nameString[0]); + userFeedback.setEmail(emailString[0]); + userFeedback.setComments(description.getText().toString()); + Sentry.captureUserFeedback(userFeedback); + } Timber.i("Submitted user feedback: name %s email %s comment %s", nameString[0], emailString[0], description.getText().toString()); runOnUiThread(() -> Toast.makeText(this, R.string.sentry_dialogue_success, Toast.LENGTH_LONG).show()); // Close the activity diff --git a/app/src/main/java/com/fox2code/mmm/MainApplication.java b/app/src/main/java/com/fox2code/mmm/MainApplication.java index ed4d5f4..4f99395 100644 --- a/app/src/main/java/com/fox2code/mmm/MainApplication.java +++ b/app/src/main/java/com/fox2code/mmm/MainApplication.java @@ -405,7 +405,16 @@ public class MainApplication extends FoxApplication implements androidx.work.Con relPackageName = this.getPackageName(); super.onCreate(); SentryMain.initialize(this); - // dirty workaround so timber doesn't bitch at us + // Initialize Timber + /*if (BuildConfig.DEBUG) { + Timber.plant(new Timber.DebugTree()); + } else { + if (isCrashReportingEnabled()) { + Timber.plant(new SentryTimberTree(Sentry.getCurrentHub(), SentryLevel.ERROR, SentryLevel.ERROR)); + } else { + Timber.plant(new ReleaseTree()); + } + }*/ TimberUtils.configTimber(); Timber.i("Starting FoxMMM version %s (%d) - commit %s", BuildConfig.VERSION_NAME, BuildConfig.VERSION_CODE, BuildConfig.COMMIT_HASH); // Update SSL Ciphers if update is possible diff --git a/app/src/main/java/com/fox2code/mmm/utils/TimberUtils.kt b/app/src/main/java/com/fox2code/mmm/utils/TimberUtils.kt index 26e6ba0..074310f 100644 --- a/app/src/main/java/com/fox2code/mmm/utils/TimberUtils.kt +++ b/app/src/main/java/com/fox2code/mmm/utils/TimberUtils.kt @@ -19,7 +19,13 @@ object TimberUtils { plant(Timber.DebugTree()) } else { if (MainApplication.isCrashReportingEnabled()) { - plant(SentryTimberTree(Sentry.getCurrentHub(), SentryLevel.ERROR, SentryLevel.ERROR)) + plant( + SentryTimberTree( + Sentry.getCurrentHub(), + SentryLevel.ERROR, + SentryLevel.ERROR + ) + ) } else { plant(ReleaseTree()) } diff --git a/build.gradle b/build.gradle deleted file mode 100644 index dcd3156..0000000 --- a/build.gradle +++ /dev/null @@ -1,36 +0,0 @@ -// Top-level build file where you can add configuration options common to all sub-projects/modules. -buildscript { - repositories { - google() - mavenCentral() - gradlePluginPortal() - maven { - url 'https://jitpack.io' - } - } - project.ext.latestAboutLibsRelease = "10.6.1" - project.ext.sentryConfigFile = new File(rootDir, "sentry.properties").getAbsoluteFile() - project.ext.hasSentryConfig = sentryConfigFile.exists() - project.ext.sentryCli = [ - logLevel: "debug", - flavorAware: true - ] - project.ext.kotlin_version = "1.8.0" - project.ext.sentry_version = "6.16.0" - dependencies { - //noinspection AndroidGradlePluginVersion - classpath 'com.android.tools.build:gradle:8.0.0' - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.8.20" - classpath "com.mikepenz.aboutlibraries.plugin:aboutlibraries-plugin:${latestAboutLibsRelease}" - - // NOTE: Do not place your application dependencies here; they belong - // in the individual module build.gradle files - //noinspection GradleDependency - classpath "io.realm:realm-gradle-plugin:10.13.3-transformer-api" - classpath 'io.sentry:sentry-android-gradle-plugin:3.4.2' - } -} - -tasks.register('clean') { - delete rootProject.buildDir -} \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 index 0000000..13bf079 --- /dev/null +++ b/build.gradle.kts @@ -0,0 +1,37 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. +buildscript { + repositories { + google() + mavenCentral() + gradlePluginPortal() + maven { + setUrl("https://jitpack.io") + } + } + extra.apply { + set("sentryConfigFile", rootProject.file("sentry.properties")) + set("hasSentryConfig", false) + set("sentryVersion", "6.17.0") + } + dependencies { + classpath("com.android.tools.build:gradle:8.1.0-beta01") + classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.8.20") + classpath("com.mikepenz.aboutlibraries.plugin:aboutlibraries-plugin:10.6.1") + + // NOTE: Do not place your application dependencies here; they belong + // in the individual module build.gradle files + //noinspection GradleDependency + classpath("io.realm:realm-gradle-plugin:10.14.0-transformer-api") + classpath("io.sentry:sentry-android-gradle-plugin:3.5.0") + } +} + +tasks.register("clean", Delete::class) { + delete(rootProject.buildDir) +} +afterEvaluate { + tasks.withType().configureEach { + sourceCompatibility = JavaVersion.VERSION_17.toString() + targetCompatibility = JavaVersion.VERSION_17.toString() + } +} \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index 7abf153..d2508ef 100644 --- a/gradle.properties +++ b/gradle.properties @@ -23,3 +23,4 @@ org.gradle.parallel=true android.enableR8.fullMode=true org.gradle.unsafe.configuration-cache=true android.defaults.buildfeatures.buildconfig=true +kotlin.jvm.target.validation.mode=IGNORE \ No newline at end of file diff --git a/settings.gradle b/settings.gradle.kts similarity index 62% rename from settings.gradle rename to settings.gradle.kts index 865356f..db591fe 100644 --- a/settings.gradle +++ b/settings.gradle.kts @@ -1,12 +1,13 @@ +@file:Suppress("UnstableApiUsage") + dependencyResolutionManagement { repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) repositories { google() mavenCentral() - maven { - url 'https://jitpack.io' - } + // enable jitpack + maven { setUrl("https://jitpack.io") } } } rootProject.name = "MagiskModuleManager" -include ':app' \ No newline at end of file +include(":app") \ No newline at end of file