plugins { alias(libs.plugins.android.application) alias(libs.plugins.kotlin.android) alias(libs.plugins.kotlin.compose) } // Version control for camswapper def majorVersion = 1 def minorVersion = 0 def patchVersion = 1 def versionCodeOffset = 0 // Offset to maintain compatibility with older versions def getGitCommitHash = { -> try { return 'git rev-parse --short HEAD'.execute().text.trim() } catch (Exception ignored) { return "unknown" } } def getGitCommitCount = { -> try { def count = 'git rev-list --count HEAD'.execute().text.trim() return count.isEmpty() ? 1 : count.toInteger() } catch (Exception ignored) { return 1 } } def gitCommitHash = getGitCommitHash() def gitCommitCount = getGitCommitCount() def startTasks = gradle.startParameter.taskNames def isExplicitNativeBuild = startTasks.any { it.contains("buildNative") } android { flavorDimensions.add("api") productFlavors { create("legacy") { dimension = "api" } create("modern") { dimension = "api" } } namespace 'com.nothing.camera2magic' compileSdk { version = release(36) } ndkVersion = "27.0.12077973" defaultConfig { applicationId "com.nothing.camera2magic" minSdk 29 targetSdk 36 // versionCode = offset + Git commit count, ensures newer than old versions versionCode versionCodeOffset + gitCommitCount versionName "${majorVersion}.${minorVersion}.${patchVersion}" // externalNativeBuild disabled - native code not ready yet // externalNativeBuild { // cmake { // cppFlags += "" // arguments "-DANDROID_PLATFORM=android-29" // } // } ndk { abiFilters.add("arm64-v8a") // abiFilters.add("armeabi-v7a") // can't support android 32-bit } testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } signingConfigs { debug { storeFile file("${System.getProperty('user.home')}/.config/.android/debug.keystore") keyAlias 'androiddebugkey' keyPassword 'android' storePassword 'android' } release { storeFile file("${System.getProperty('user.home')}/.config/.android/debug.keystore") keyAlias 'androiddebugkey' keyPassword 'android' storePassword 'android' } } buildTypes { debug { signingConfig signingConfigs.debug } release { minifyEnabled true shrinkResources true signingConfig signingConfigs.release proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } // Custom generated APK filename applicationVariants.all { variant -> variant.outputs.all { output -> def flavor = variant.flavorName def fileName = "CamSwapper-${majorVersion}.${minorVersion}.${patchVersion}-${flavor}-api.apk" output.outputFileName = fileName } } compileOptions { sourceCompatibility JavaVersion.VERSION_11 targetCompatibility JavaVersion.VERSION_11 } kotlinOptions { jvmTarget = '11' } kotlin { jvmToolchain(17) } // externalNativeBuild disabled - native code not ready yet // externalNativeBuild { // cmake { // path file("src/main/cpp/CMakeLists.txt") // version = "3.22.1" // } // } buildFeatures { compose true } sourceSets { main { jniLibs { srcDirs += ["src/main/jniLibs"] } } } packaging { jniLibs.pickFirsts.add("**/libcamera3.so") } } afterEvaluate { if (!isExplicitNativeBuild) { def jniLibTree = fileTree(dir: "src/main/jniLibs", include: "**/libcamera3.so") if (jniLibTree.isEmpty()) { println ">>> [WARN] jniLibs files not found, cannot perform quick build <<<" return } println ">>> Mode: Quick build (C++ compilation disabled, using jniLibs) <<<" // 1. Disable CMake and Strip tasks tasks.matching { task -> (task.name.startsWith("buildCMake") || task.name.startsWith("externalNativeBuild")) && !task.name.contains("generateJsonModel") }.configureEach { task -> task.enabled = false } } } tasks.register("buildNative", Copy) { group = "native" description = "Build C++ artifacts and sync to jniLibs (based on Modern Release)" def targetVariant = "modernRelease" def stripTaskName = "stripModernReleaseDebugSymbols" dependsOn stripTaskName outputs.upToDateWhen { false } duplicatesStrategy = DuplicatesStrategy.INCLUDE doFirst { delete("src/main/jniLibs") delete("release/") delete(".cxx") println ">>> Cleaned old jniLibs directory and C++ cache <<<" println ">>> Mode: Native build (compiling C++ based on ${targetVariant} and updating jniLibs) <<<" } def startDir = layout.buildDirectory.dir("intermediates/stripped_native_libs/${targetVariant}/${stripTaskName}/out/lib") from(startDir) { include("**/libcamera3.so") } includeEmptyDirs = false into("src/main/jniLibs") } dependencies { implementation "androidx.lifecycle:lifecycle-viewmodel-compose:2.10.0" implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.10.0" implementation "com.google.accompanist:accompanist-permissions:0.37.3" implementation "androidx.media3:media3-exoplayer:1.5.1" implementation "androidx.media3:media3-common:1.5.1" implementation libs.androidx.compose.foundation implementation libs.androidx.compose.adaptive implementation libs.androidx.material3 implementation libs.androidx.core.ktx implementation libs.androidx.lifecycle.runtime.ktx implementation libs.androidx.activity.compose implementation platform(libs.androidx.compose.bom) implementation libs.androidx.compose.ui implementation libs.androidx.compose.ui.graphics implementation libs.androidx.compose.ui.tooling.preview implementation libs.androidx.compose.material3 testImplementation libs.junit androidTestImplementation libs.androidx.junit androidTestImplementation libs.androidx.espresso.core androidTestImplementation platform(libs.androidx.compose.bom) androidTestImplementation libs.androidx.compose.ui.test.junit4 debugImplementation libs.androidx.compose.ui.tooling debugImplementation libs.androidx.compose.ui.test.manifest }