apply plugin: 'com.android.application' def keystorePropertiesFile = rootProject.file("key.properties") def keystoreProperties = new Properties() if (keystorePropertiesFile.exists()) { keystoreProperties.load(new FileInputStream(keystorePropertiesFile)) } android { namespace = "spot.agora.app" compileSdk = rootProject.ext.compileSdkVersion defaultConfig { applicationId "spot.agora.app" minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion versionCode 1 versionName "2.9.1" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" // The arti-mobile AAR bundles large native Rust libraries for every // ABI (~45 MB total). Restrict to the ABIs we actually ship/test: // arm64-v8a + armeabi-v7a (real devices) and x86_64 (emulators). // Drop x86_64 here if you only ever test on physical devices. ndk { abiFilters 'arm64-v8a', 'armeabi-v7a', 'x86_64' } aaptOptions { // Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps. // Default: https://android.googlesource.com/platform/frameworks/base/+/282e181b58cf72b6ca770dc7ca5f91f135444502/tools/aapt/AaptAssets.cpp#61 ignoreAssetsPattern = '!.svn:!.git:!.ds_store:!*.scc:.*:!CVS:!thumbs.db:!picasa.ini:!*~' } } signingConfigs { release { if (keystorePropertiesFile.exists()) { keyAlias keystoreProperties['keyAlias'] keyPassword keystoreProperties['keyPassword'] storeFile file(keystoreProperties['storeFile']) storePassword keystoreProperties['storePassword'] } } } buildTypes { release { signingConfig signingConfigs.release minifyEnabled true shrinkResources true proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } } repositories { flatDir{ dirs '../capacitor-cordova-android-plugins/src/main/libs', 'libs' } } dependencies { implementation fileTree(include: ['*.jar'], dir: 'libs') implementation "androidx.appcompat:appcompat:$androidxAppCompatVersion" implementation "androidx.core:core:$androidxCoreVersion" implementation "androidx.coordinatorlayout:coordinatorlayout:$androidxCoordinatorLayoutVersion" implementation "androidx.core:core-splashscreen:$coreSplashScreenVersion" implementation project(':capacitor-android') implementation 'com.squareup.okhttp3:okhttp:4.12.0' // Tor in Rust (arti) — prebuilt AAR from Guardian Project's gpmaven repo // (source pinned to an immutable commit in the root build.gradle). // Provides org.torproject.arti.ArtiProxy used by TorController. // The resolved AAR is checksum-verified below (verifyArtiChecksum). implementation 'org.torproject:arti-mobile:1.7.0.1' // arti pulls androidx.webkit in transitively but only at runtime; we // compile against ProxyController/WebViewFeature in TorController, so // declare it explicitly on the app's compile classpath. implementation "androidx.webkit:webkit:$androidxWebkitVersion" testImplementation "junit:junit:$junitVersion" androidTestImplementation "androidx.test.ext:junit:$androidxJunitVersion" androidTestImplementation "androidx.test.espresso:espresso-core:$androidxEspressoCoreVersion" implementation project(':capacitor-cordova-android-plugins') } apply from: 'capacitor.build.gradle' // Supply-chain pin for the arti-mobile AAR. It carries a native library with // network-proxy privileges and is sourced from Guardian Project's gpmaven repo, // so we verify the resolved artifact's SHA-256 against a value pinned here. // A mismatch fails the build before any APK is assembled. To bump arti, update // the version + repo commit (root build.gradle) and replace this checksum after // re-verifying a fresh download. ext.artiMobileSha256 = 'cbdb34ce3cdb32f755f25f6dd05a2d1eb9a44025a17ec9202729816e2a3af05b' task verifyArtiChecksum { doLast { def artifact = configurations.releaseRuntimeClasspath .resolvedConfiguration .resolvedArtifacts .find { it.moduleVersion.id.group == 'org.torproject' && it.moduleVersion.id.name == 'arti-mobile' } if (artifact == null) { throw new GradleException("arti-mobile artifact not found on the runtime classpath; cannot verify Tor native library.") } def actual = java.security.MessageDigest.getInstance("SHA-256") .digest(artifact.file.bytes) .collect { String.format('%02x', it) } .join('') if (actual != project.ext.artiMobileSha256) { throw new GradleException( "arti-mobile AAR checksum mismatch!\n" + " expected: ${project.ext.artiMobileSha256}\n" + " actual: ${actual}\n" + " file: ${artifact.file}\n" + "Refusing to build a Tor proxy from an unverified native artifact." ) } logger.lifecycle("Verified arti-mobile AAR checksum (${actual}).") } } afterEvaluate { tasks.matching { it.name.startsWith('assemble') || it.name.startsWith('bundle') }.configureEach { dependsOn verifyArtiChecksum } } try { def servicesJSON = file('google-services.json') if (servicesJSON.text) { apply plugin: 'com.google.gms.google-services' } } catch(Exception e) { logger.info("google-services.json not found, google-services plugin not applied. Push Notifications won't work") }