plugins { id "com.android.application" id "org.jetbrains.kotlin.android" id "org.jetbrains.kotlin.plugin.compose" id "org.jetbrains.kotlin.plugin.parcelize" id "org.jetbrains.kotlin.plugin.serialization" id "kotlin-kapt" id "com.google.dagger.hilt.android" } android { namespace "com.peachpasswords" compileSdk 35 defaultConfig { applicationId "com.peachpasswords" minSdk 26 targetSdk 35 versionCode 240126 versionName "2.6.2" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" vectorDrawables { useSupportLibrary true } } signingConfigs { release { // Read from local.properties (koh-ignored) so the keystore and its // password never enter version history. Absent on a machine without // the key -> release build stays unsigned rather than failing. def props = new Properties() def f = rootProject.file("local.properties") if (f.exists()) { f.withInputStream { props.load(it) } } if (props.getProperty("peachStoreFile")) { storeFile file(props.getProperty("peachStoreFile")) storePassword props.getProperty("peachStorePassword") keyAlias props.getProperty("peachKeyAlias") keyPassword props.getProperty("peachKeyPassword") } // v3 is the only escape hatch from "this key is forever": it carries a // rotation lineage, so a future key can be proven to descend from this // one instead of forcing every tester to uninstall and lose their // vault. AGP leaves it off unless asked. enableV2Signing true enableV3Signing true } } // ABI splits were tried and removed: the native libraries are ~2.5 MB of a // 24 MB APK, so per-ABI builds saved 8% in exchange for four artifacts and // a "which one do I need?" question at every install. The weight is 62 MB of // DEX, because `minifyEnabled false` below leaves R8 off entirely — that is // the lever worth pulling, and it needs its own pass with real-device // verification (kotlinx.serialization, BouncyCastle, Hilt, Compose). buildTypes { debug { applicationIdSuffix ".debug" versionNameSuffix "-debug" debuggable true } release { signingConfig signingConfigs.release minifyEnabled false proguardFiles getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro" } } compileOptions { sourceCompatibility JavaVersion.VERSION_17 targetCompatibility JavaVersion.VERSION_17 } kotlinOptions { jvmTarget = "17" } buildFeatures { compose true buildConfig true } composeOptions { kotlinCompilerExtensionVersion "1.5.15" } packaging { resources { excludes += [ "/META-INF/{AL2.0,LGPL2.1}", "META-INF/DEPENDENCIES", "META-INF/LICENSE*", "META-INF/NOTICE*", ] } } testOptions { unitTests.all { def coreDir = rootProject.file("../peach-browser/crypto-core") def nativeLibrary = new File( coreDir, "target/release/libpeach_noise_core.dylib", ) if (coreDir.exists()) { dependsOn rootProject.tasks.named("buildRustNoiseHost") systemProperty "peach.noise.library.path", nativeLibrary.absolutePath } } } } dependencies { implementation platform("androidx.compose:compose-bom:2024.06.00") androidTestImplementation platform("androidx.compose:compose-bom:2024.06.00") implementation "androidx.activity:activity-compose:1.9.2" implementation "androidx.autofill:autofill:1.1.0" implementation "androidx.biometric:biometric:1.1.0" implementation "androidx.core:core-splashscreen:1.0.1" implementation "androidx.appcompat:appcompat:1.7.0" implementation "androidx.credentials:credentials:1.5.0" implementation "androidx.credentials:credentials-play-services-auth:1.5.0" implementation "androidx.glance:glance-appwidget:1.1.0" implementation "androidx.glance:glance-material3:1.1.0" implementation "androidx.hilt:hilt-navigation-compose:1.2.0" // In-app updates: a periodic release check that survives Doze without a // service. hilt-work lets the worker take UpdateRepository by injection // rather than reaching for a global. implementation "androidx.hilt:hilt-work:1.2.0" kapt "androidx.hilt:hilt-compiler:1.2.0" implementation "androidx.work:work-runtime-ktx:2.9.1" implementation "androidx.lifecycle:lifecycle-runtime-compose:2.8.4" implementation "androidx.lifecycle:lifecycle-viewmodel-compose:2.8.4" implementation "androidx.lifecycle:lifecycle-process:2.8.4" implementation "androidx.navigation:navigation-compose:2.8.0" // MN-6: androidx.security:security-crypto has no stable 1.1.x release — the only // stable line is 1.0.0 (2021), which lacks the Tink updates and Android 12+ fixes // in the 1.1.0 alphas and is widely superseded in production. Deliberately pinned // to an exact alpha (never a floating range) so the resolved artifact is // reproducible. Revisit if/when 1.1.0 stabilises. Used only for the duress/license // EncryptedSharedPreferences; the vault slots are sealed by VaultCrypto, not this. implementation "androidx.security:security-crypto:1.1.0-alpha06" implementation "androidx.compose.material3:material3" implementation "androidx.compose.ui:ui" implementation "androidx.compose.ui:ui-tooling-preview" implementation "androidx.compose.foundation:foundation" implementation "androidx.compose.material:material-icons-extended" implementation "androidx.core:core-ktx:1.13.1" implementation "com.google.android.material:material:1.12.0" implementation "com.google.dagger:hilt-android:2.51.1" kapt "com.google.dagger:hilt-compiler:2.51.1" implementation "com.google.zxing:core:3.5.3" implementation "androidx.camera:camera-core:1.3.4" implementation "androidx.camera:camera-camera2:1.3.4" implementation "androidx.camera:camera-lifecycle:1.3.4" implementation "androidx.camera:camera-view:1.3.4" implementation "com.squareup.okhttp3:okhttp:4.12.0" implementation "org.bouncycastle:bcprov-jdk18on:1.78.1" // zstd-jni (reference libzstd) — per-section compression for the PeachScript // PCHS binary format (MF-2). Required for cross-platform interop with the // browser's zstd sections. The @aar variant ships the Android jniLibs // (lib//libzstd-jni.so); the plain jar bundles only desktop natives and // would fail with UnsatisfiedLinkError on-device. implementation "com.github.luben:zstd-jni:1.5.6-3@aar" // The @aar ships only Android .so; the plain jar carries the desktop natives // the host JVM unit tests need. testImplementation "com.github.luben:zstd-jni:1.5.6-3" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.8.1" implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.7.1" debugImplementation "androidx.compose.ui:ui-tooling" debugImplementation "androidx.compose.ui:ui-test-manifest" androidTestImplementation "androidx.test.ext:junit:1.2.1" androidTestImplementation "androidx.test.espresso:espresso-core:3.6.1" androidTestImplementation "androidx.compose.ui:ui-test-junit4" testImplementation "junit:junit:4.13.2" // Real org.json on the unit-test classpath; android.jar's is a throwing stub, // so the release-manifest parser would otherwise be untestable off-device. testImplementation "org.json:json:20240303" testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:1.8.1" }