apply plugin: 'com.android.application' apply plugin: 'kotlin-android' apply plugin: 'kotlin-parcelize' apply plugin: 'com.google.devtools.ksp' android { namespace "com.github.k1rakishou.chan" compileSdk 34 def getCommitHash = { -> def stdout = new ByteArrayOutputStream() exec { commandLine "cmd",'git', 'rev-parse', 'HEAD' standardOutput = stdout } return stdout.toString().trim() } productFlavors.all { ext.apkVersionNameSuffix = null } defaultConfig { minSdkVersion 21 targetSdkVersion 33 // if you change this, also change the AndroidManifest package applicationId "com.github.k1rakishou.chan" // ALL ENDPOINTS SHOULD BE HTTPS // CHANGE THESE TO YOUR GITHUB REPOSITORY // the repo endpoint is also used to calculate the issues endpoint // the resources endpoint is for any static resources; currently this is mostly used for various images used internally, // but using a remote resource works easier with the application architecture than using a local resource/drawable buildConfigField "String", "RELEASE_UPDATE_API_ENDPOINT", "\"https://api.github.com/repos/K1rakishou/Kuroba-Experimental/releases/latest\"" buildConfigField "String", "BETA_UPDATE_API_ENDPOINT", "\"https://api.github.com/repos/K1rakishou/Kuroba-Experimental-beta/releases/latest\"" buildConfigField "String", "GITHUB_ENDPOINT", "\"https://github.com/K1rakishou/Kuroba-Experimental\"" buildConfigField "String", "GITHUB_CHANGELOGS_ENDPOINT", "\"https://raw.githubusercontent.com/K1rakishou/Kuroba-Experimental/develop/fastlane/metadata/android/en-US/changelogs/\"" buildConfigField "String", "GITHUB_REPORTS_ENDPOINT", "\"https://github.com/KurobaExReports/Reports/issues/\"" // this is for checking who's built what in debug logs buildConfigField "String", "RELEASE_SIGNATURE", "\"86242978CF53C34361A8C962D0A57107AEB70E10631AE13EB5B006C0CF673FA9\"" // this is the default dev signing signature, update it if you change the dev keystore buildConfigField "String", "DEBUG_SIGNATURE", "\"DC5195CC40E42B95267D500B6E93E46EC51028C67BDD3D09BBB9C208BF20C8FE\"" // buildConfigField "String", "COMMIT_HASH", "\"" + getCommitHash() + "\"" buildConfigField "String", "COMMIT_HASH", "\"" + "abc" + "\"" // M -> Major version // m -> Minor version // p -> patch // MmmPP versionCode 10335 versionName "v1.3.35" applicationVariants.all { variant -> variant.outputs.all { outputFileName = manifestPlaceholders.get("appName").toString() + ".apk" } } configurations.all { resolutionStrategy { force 'androidx.emoji2:emoji2:1.3.0' } } vectorDrawables.useSupportLibrary = true } flavorDimensions "default" productFlavors { // FLAVOR_TYPE 0 - release (stable) build // FLAVOR_TYPE 1 - beta build // FLAVOR_TYPE 2 - dev build // FLAVOR_TYPE 3 - fdroid build stable { dimension "default" applicationIdSuffix "" apkVersionNameSuffix = "" buildConfigField "int", "FLAVOR_TYPE", "0" buildConfigField "int", "UPDATE_DELAY", "5" // These are manifest placeholders for the application name, icon location and file // provider authority (the file provider authority should differ for different flavors // otherwise the app will not work) manifestPlaceholders = [ appName : "KurobaEx", iconLoc : "@mipmap/ic_launcher_release", fileProviderAuthority: "${defaultConfig.applicationId}${applicationIdSuffix}.fileprovider", appTheme : "@style/Chan.DefaultTheme" ] } beta { dimension "default" // Different app ids for different flavors so that the users are able to install both // of them without deleting anything applicationIdSuffix ".beta" apkVersionNameSuffix = "-beta" buildConfigField "int", "FLAVOR_TYPE", "1" buildConfigField "int", "UPDATE_DELAY", "1" // The same as in stable flavor manifestPlaceholders = [ appName : "KurobaEx-beta", iconLoc : "@mipmap/ic_launcher_beta", fileProviderAuthority: "${defaultConfig.applicationId}${applicationIdSuffix}.fileprovider", appTheme : "@style/Chan.DefaultTheme" ] } dev { dimension "default" // Different app ids for different flavors so that the users are able to install both // of them without deleting anything applicationIdSuffix ".dev" apkVersionNameSuffix = "-dev" buildConfigField "int", "FLAVOR_TYPE", "2" // We never use updater for dev builds buildConfigField "int", "UPDATE_DELAY", "99999999" // The same as in stable flavor manifestPlaceholders = [ appName : "KurobaEx-dev", iconLoc : "@mipmap/ic_launcher_dev", fileProviderAuthority: "${defaultConfig.applicationId}${applicationIdSuffix}.fileprovider", appTheme : "@style/Chan.DebugTheme" ] } fdroid { dimension "default" // Different app ids for different flavors so that the users are able to install both // of them without deleting anything applicationIdSuffix ".fdroid" apkVersionNameSuffix = "-fdroid" buildConfigField "int", "FLAVOR_TYPE", "3" // We never use updater for fdroid builds buildConfigField "int", "UPDATE_DELAY", "99999999" manifestPlaceholders = [ appName : "KurobaEx-fdroid", iconLoc : "@mipmap/ic_launcher_release", fileProviderAuthority: "${defaultConfig.applicationId}${applicationIdSuffix}.fileprovider", appTheme : "@style/Chan.DefaultTheme" ] } } buildTypes { // manifestPlaceholders do not work here for some reason so here is a little hack. // We need to iterate each build variant and for each build variant we need to find it's // flavor then we need to extract the versionNameSuffix from the flavor and update the output // apk name with it. android.applicationVariants.all { variant -> variant.outputs.all { Object flavor = getCurrentFlavor(variant.flavorName) if (flavor == null) { throw new GradleException("Couldn't find flavor by variant.flavorName = ${variant.flavorName}") } outputFileName = "KurobaEx${flavor.apkVersionNameSuffix}.apk" } } release { File propsFile = file('release.properties') if (propsFile.exists()) { Properties props = new Properties() InputStream is = new FileInputStream(propsFile) props.load(is) signingConfigs { release { storeFile file(props['keystoreFile']) storePassword props['keystorePass'] keyAlias props['keyAlias'] keyPassword props['keyPass'] v1SigningEnabled true v2SigningEnabled true } } is.close() signingConfig signingConfigs.release } minifyEnabled true proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard.cfg' debuggable = false } debug { File f = file('debug.properties') if (f.exists()) { Properties props = new Properties() InputStream is = new FileInputStream(f) props.load(is) signingConfigs { debug { storeFile file(props['keystoreFile']) storePassword props['keystorePass'] keyAlias props['keyAlias'] keyPassword props['keyPass'] v1SigningEnabled true v2SigningEnabled true } } is.close() signingConfig signingConfigs.debug } minifyEnabled false debuggable = true } } compileOptions { encoding = 'UTF-8' sourceCompatibility JavaVersion.VERSION_17 targetCompatibility JavaVersion.VERSION_17 } kotlinOptions { jvmTarget = JavaVersion.VERSION_17.toString() freeCompilerArgs = [ "-Xopt-in=kotlin.RequiresOptIn", "-Xopt-in=androidx.compose.foundation.ExperimentalFoundationApi", "-Xopt-in=androidx.compose.foundation.layout.ExperimentalLayoutApi", "-Xopt-in=androidx.compose.animation.graphics.ExperimentalAnimationGraphicsApi", "-Xopt-in=kotlinx.coroutines.ObsoleteCoroutinesApi", "-Xopt-in=kotlinx.coroutines.ExperimentalCoroutinesApi" ] } buildFeatures { compose = true buildConfig = true } composeOptions { kotlinCompilerExtensionVersion = versions.compose_compiler_version } lintOptions { checkReleaseBuilds false abortOnError false } } dependencies { implementation project(':core-logger') implementation project(':core-settings') implementation project(':core-themes') implementation project(':core-spannable') implementation project(':core-common') implementation project(':core-model') implementation project(':core-parser') implementation "androidx.appcompat:appcompat:${versions.appcompat}" implementation "androidx.preference:preference-ktx:${versions.androidx_preferences_ktx}" implementation 'androidx.constraintlayout:constraintlayout:2.1.4' implementation 'androidx.slidingpanelayout:slidingpanelayout:1.2.0' implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0' implementation "androidx.core:core-ktx:${versions.core_ktx}" implementation 'androidx.work:work-runtime-ktx:2.9.0' implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.7.0' implementation "com.google.android.material:material:${versions.material}" implementation "androidx.window:window:1.2.0" implementation("androidx.compose.ui:ui:${versions.compose_version}") implementation("androidx.compose.material:material:${versions.compose_version}") implementation("androidx.compose.ui:ui-tooling:${versions.compose_version}") implementation("androidx.compose.animation:animation-graphics:${versions.compose_version}") implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.7.0") implementation("androidx.activity:activity-compose:1.9.0") implementation "com.google.android.exoplayer:exoplayer-core:${versions.exoplayer}" implementation "com.google.android.exoplayer:exoplayer-ui:${versions.exoplayer}" implementation "com.squareup.okhttp3:okhttp:${versions.okhttp}" implementation "com.squareup.okhttp3:okhttp-dnsoverhttps:${versions.okhttp}" implementation "com.squareup.okhttp3:logging-interceptor:${versions.okhttp}" implementation "org.jsoup:jsoup:${versions.jsoup}" implementation 'pl.droidsonroids.gif:android-gif-drawable:1.2.23' implementation 'com.davemorrissey.labs:subsampling-scale-image-view:3.10.0' implementation 'org.nibor.autolink:autolink:0.10.0' implementation "com.google.code.gson:gson:${versions.gson}" implementation "io.reactivex.rxjava2:rxjava:${versions.rxjava}" implementation "io.reactivex.rxjava2:rxandroid:${versions.rxandroid}" implementation "org.jetbrains.kotlin:kotlin-stdlib:${versions.kotlin_version}" implementation "org.jetbrains.kotlin:kotlin-reflect:${versions.kotlin_version}" implementation 'org.jetbrains.kotlinx:kotlinx-collections-immutable:0.3.5' implementation "joda-time:joda-time:${versions.joda_time}" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:${versions.kotlin_coroutines_version}" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:${versions.kotlin_coroutines_version}" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-rx2:${versions.kotlin_coroutines_version}" implementation "io.coil-kt:coil:${versions.coil}" implementation "io.coil-kt:coil-compose:${versions.coil}" implementation "cafe.adriel.voyager:voyager-core:${versions.voyager}" implementation "cafe.adriel.voyager:voyager-navigator:${versions.voyager}" implementation "cafe.adriel.voyager:voyager-transitions:${versions.voyager}" implementation("ch.acra:acra-http:${versions.acra}") implementation("ch.acra:acra-core:${versions.acra}") // noinspection GradleDependency wants to upgrade to older version implementation "com.github.K1rakishou:Fuck-Storage-Access-Framework:${versions.fsaf}" implementation "androidx.room:room-runtime:${versions.room_version}" testImplementation 'junit:junit:4.13.2' ksp("androidx.room:room-compiler:${versions.room_version}") implementation "com.google.dagger:dagger:${versions.dagger_version}" ksp("com.google.dagger:dagger-compiler:${versions.dagger_version}") implementation("com.squareup.moshi:moshi-kotlin:${versions.moshi}") ksp("com.squareup.moshi:moshi-kotlin-codegen:${versions.moshi}") implementation "com.airbnb.android:epoxy:${versions.epoxy}" ksp("com.airbnb.android:epoxy-processor:${versions.epoxy}") testImplementation "junit:junit:${versions.junit}" testImplementation "org.robolectric:robolectric:${versions.robolectric}" testImplementation "com.squareup.okhttp3:mockwebserver:${versions.okhttp}" testImplementation "org.mockito:mockito-core:${versions.mockito_core}" testImplementation "com.nhaarman.mockitokotlin2:mockito-kotlin:${versions.mockito_kotlin}" testImplementation "org.powermock:powermock-module-junit4:${versions.powermock}" testImplementation "org.powermock:powermock-api-mockito2:${versions.powermock}" testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:${versions.kotlin_coroutines_version}" devImplementation 'com.squareup.leakcanary:leakcanary-android:2.9.1' } //==================================================================== // All of the below functions are being used by the upload_apk script //==================================================================== def getCurrentFlavor(String name) { Object resultFlavor = null android.productFlavors.all { flavor -> if (flavor.name == name) { resultFlavor = flavor } } return resultFlavor }