Files
AndroidJetpack/rethink-app/app/build.gradle
T
coco 723ce1af5c a
2026-07-03 15:12:48 +08:00

327 lines
12 KiB
Groovy

plugins {
id 'com.android.application'
id 'com.google.devtools.ksp'
// to download blocklists for the headless variant
id "de.undercouch.download" version "5.3.0"
id 'kotlin-android'
id 'com.google.gms.google-services'
id 'com.google.firebase.crashlytics'
}
def keystorePropertiesFile = rootProject.file("keystore.properties")
def keystoreProperties = new Properties()
// https://github.com/celzero/rethink-app/issues/1032
// https://docs.gradle.org/8.2/userguide/configuration_cache.html#config_cache:requirements:external_processes
// get the git version from the command line
def gitVersion = providers.exec {
commandLine("git", "describe", "--tags", "--always")
}.standardOutput.asText.get().toString().trim()
// for github builds, the version code is set in the github action via env
// for local builds, the version code is set in gradle.properties
def getVersionCode = {
def code = 0
try {
// parseInt throws NumberFormatException if the string does not contain a parsable integer
// but "as Integer" is a wrapper class, which silently returns null
code = Integer.parseInt(System.getenv("VERSION_CODE"))
logger.info("env version code: $code")
} catch (NumberFormatException ex) {
logger.info("missing env version code: $ex.message")
}
if (code == 0) {
code = project.properties['VERSION_CODE'] as Integer
logger.info("project properties version code: $code")
}
return code
}
try {
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
} catch (Exception ex) {
logger.info("missing keystore prop: $ex.message")
keystoreProperties['keyAlias'] = ''
keystoreProperties['keyPassword'] = ''
keystoreProperties['storeFile'] = '/dev/null'
keystoreProperties['storePassword'] = ''
}
android {
compileSdk 34
// https://developer.android.com/studio/build/configure-app-module
namespace 'com.celzero.bravedns'
defaultConfig {
applicationId "com.celzero.bravedns"
minSdkVersion 23
targetSdkVersion 34
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
signingConfigs {
config {
keyAlias keystoreProperties['keyAlias']
keyPassword keystoreProperties['keyPassword']
storeFile file(keystoreProperties['storeFile'])
storePassword keystoreProperties['storePassword']
}
// archive.is/wlwD8
alpha {
keyAlias System.getenv("ALPHA_KS_ALIAS") // rdnsAlpha
keyPassword System.getenv("ALPHA_KS_PASSPHRASE")
// https://stackoverflow.com/a/34640602
storeFile file(String.valueOf(System.getenv("ALPHA_KS_FILE"))) // rdnsAlpha.jks in app/
storePassword System.getenv("ALPHA_KS_STORE_PASSPHRASE")
}
}
buildTypes {
release {
// modified as part of #352, now webview is removed from app, flipping back
// the setting to true
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
leakCanary {
matchingFallbacks = ['debug']
initWith buildTypes.debug
}
alpha {
// archive.is/y8uCB
applicationIdSuffix ".alpha"
minifyEnabled true
shrinkResources true
signingConfig signingConfigs.alpha
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
buildFeatures {
viewBinding true
buildConfig true
}
compileOptions {
coreLibraryDesugaringEnabled true
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}
packagingOptions {
jniLibs {
keepDebugSymbols += ['**/*.so']
}
}
variantFilter { variant ->
def releaseChannel = variant.getFlavors().get(0).name
def releaseType = variant.getFlavors().get(1).name
if (releaseType == 'headless' && releaseChannel != 'fdroid') {
variant.setIgnore(true)
}
}
flavorDimensions = ["releaseChannel", "releaseType"]
productFlavors {
play {
dimension "releaseChannel"
}
fdroid {
dimension "releaseChannel"
}
website {
dimension "releaseChannel"
}
headless {
dimension "releaseType"
minSdkVersion 31
// stackoverflow.com/a/60560178
// buildConfigField 'string', 'timestamp', '1662384683026'
}
full {
dimension "releaseType"
// getPackageInfo().versionCode not returning the correct value (in prod builds) when
// value is set in AndroidManifest.xml so setting it here
// for buildtype alpha, versionCode is set in env overriding gradle.properties
versionCode = getVersionCode()
versionName = gitVersion
vectorDrawables.useSupportLibrary = true
}
}
lint {
abortOnError false
}
tasks.configureEach { task ->
if (task.name.toLowerCase().contains('headless')) {
task.dependsOn downloadBlocklists
if (task.name.endsWith("BuildConfig")) {
task.enabled false
}
}
}
}
configurations {
download {
transitive false
}
}
dependencies {
implementation 'com.google.firebase:firebase-crashlytics-ktx:19.0.0'
androidTestImplementation 'androidx.test:rules:1.5.0'
def room_version = "2.6.1"
def paging_version = "3.2.1"
implementation 'com.google.guava:guava:32.1.1-android'
// https://developer.android.com/studio/write/java8-support
// included to fix issues with Android 6 support, issue#563
coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.0.4")
fullImplementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.9.21'
fullImplementation 'androidx.appcompat:appcompat:1.6.1'
fullImplementation 'androidx.core:core-ktx:1.12.0'
implementation 'androidx.preference:preference-ktx:1.2.1'
fullImplementation 'androidx.constraintlayout:constraintlayout:2.1.4'
fullImplementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'
fullImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3'
fullImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3'
// LiveData
implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.7.0'
implementation 'com.google.code.gson:gson:2.10.1'
implementation "androidx.room:room-runtime:$room_version"
ksp "androidx.room:room-compiler:$room_version"
implementation "androidx.room:room-ktx:$room_version"
implementation "androidx.room:room-paging:$room_version"
fullImplementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
fullImplementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.7.0'
fullImplementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.7.0'
// Pagers Views
implementation "androidx.paging:paging-runtime-ktx:$paging_version"
fullImplementation 'androidx.fragment:fragment-ktx:1.6.2'
implementation 'com.google.android.material:material:1.11.0'
fullImplementation 'androidx.viewpager2:viewpager2:1.0.0'
fullImplementation 'com.squareup.okhttp3:okhttp:4.12.0'
fullImplementation 'com.squareup.okhttp3:okhttp-dnsoverhttps:4.12.0'
fullImplementation 'com.squareup.retrofit2:retrofit:2.9.0'
fullImplementation 'com.squareup.retrofit2:converter-gson:2.9.0'
implementation 'com.squareup.okio:okio-jvm:3.9.0'
// Glide
fullImplementation('com.github.bumptech.glide:glide:4.16.0') {
exclude group: 'glide-parent'
}
fullImplementation('com.github.bumptech.glide:okhttp3-integration:4.16.0') {
exclude group: 'glide-parent'
}
// Ref: https://stackoverflow.com/a/46638213
kspFull 'com.github.bumptech.glide:compiler:4.16.0'
// Swipe button animation
fullImplementation 'com.facebook.shimmer:shimmer:0.5.0'
// Koin core
download 'io.insert-koin:koin-core:3.5.6'
implementation 'io.insert-koin:koin-core:3.5.6'
// Koin main (Scope, ViewModel ...)
download 'io.insert-koin:koin-android:3.5.6'
implementation 'io.insert-koin:koin-android:3.5.6'
download 'hu.autsoft:krate:2.0.0'
implementation 'hu.autsoft:krate:2.0.0'
// viewBinding without reflection
fullImplementation 'com.github.kirich1409:viewbindingpropertydelegate:1.5.9'
fullImplementation 'com.github.kirich1409:viewbindingpropertydelegate-noreflection:1.5.9'
// from: https://jitpack.io/#celzero/firestack
download 'com.github.celzero:firestack:d92f398622@aar'
implementation 'com.github.celzero:firestack:d92f398622@aar'
// Work manager
implementation('androidx.work:work-runtime-ktx:2.9.0') {
modules {
module("com.google.guava:listenablefuture") {
replacedBy("com.google.guava:guava", "listenablefuture is part of guava")
}
}
}
// for handling IP addresses and subnets, both IPv4 and IPv6
// https://seancfoley.github.io/IPAddress/ipaddress.html
download 'com.github.seancfoley:ipaddress:5.4.0'
implementation 'com.github.seancfoley:ipaddress:5.4.0'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
leakCanaryImplementation 'com.squareup.leakcanary:leakcanary-android:2.14'
fullImplementation 'androidx.navigation:navigation-fragment-ktx:2.7.7'
fullImplementation 'androidx.navigation:navigation-ui-ktx:2.7.7'
fullImplementation 'androidx.biometric:biometric:1.1.0'
playImplementation 'com.google.android.play:app-update:2.1.0'
playImplementation 'com.google.android.play:app-update-ktx:2.1.0'
// for encrypting wireguard configuration files
implementation("androidx.security:security-crypto:1.1.0-alpha06")
implementation("androidx.security:security-app-authenticator:1.0.0-alpha03")
androidTestImplementation("androidx.security:security-app-authenticator:1.0.0-alpha03")
// barcode scanner for wireguard
fullImplementation 'com.journeyapps:zxing-android-embedded:4.3.0'
playImplementation 'com.google.firebase:firebase-crashlytics:19.0.0'
playImplementation 'com.google.firebase:firebase-crashlytics-ndk:19.0.0'
}
// github.com/michel-kraemer/gradle-download-task/issues/131#issuecomment-464476903
tasks.register('downloadBlocklists', Download) {
// def assetsDir = new File(projectDir, 'src/main/assets'
def assetsDir = android.sourceSets.headless.assets.srcDirs[0]
// the filenames are ignored by dl, but acts as a hint for the output
// filename for the download-plugin, which does not respect the
// content-disposition http header, but rather guesses dest file names
// from the final segment of url's path
// github.com/michel-kraemer/gradle-download-task/blob/64d1ce32/src/main/java/de/undercouch/gradle/tasks/download/DownloadAction.java#L731
def sources = [
'https://dl.rethinkdns.com/blocklists/filetag.json',
'https://dl.rethinkdns.com/basicconfig/basicconfig.json',
'https://dl.rethinkdns.com/rank/rd.txt',
'https://dl.rethinkdns.com/trie/td.txt',
]
src(sources)
dest assetsDir
// download files only if last-modified of the local file is less than
// the last-modified http header returned by the server
onlyIfModified true
// or if etag mismatches
useETag true
// overwrite older files as determined by last-modified, always
overwrite true
}
tasks.register('downloadDependencies', Copy) {
dependsOn downloadBlocklists
from configurations.download
into "libs"
}