import java.nio.file.Paths import com.android.Version def agpVersion = Version.ANDROID_GRADLE_PLUGIN_VERSION.tokenize('.')[0].toInteger() def androidManifestPath = agpVersion >= 7 ? 'src/main/AndroidManifest.xml' : 'src/hasNamespace/AndroidManifest.xml' buildscript { def kotlin_version = rootProject.ext.has("kotlinVersion") ? rootProject.ext.get("kotlinVersion") : project.properties["VisionCamera_kotlinVersion"] repositories { maven { url "https://plugins.gradle.org/m2/" } mavenCentral() google() } dependencies { classpath "com.android.tools.build:gradle:8.5.2" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } def resolveBuildType() { Gradle gradle = getGradle() String tskReqStr = gradle.getStartParameter().getTaskRequests()["args"].toString() return tskReqStr.contains("Release") ? "release" : "debug" } def isNewArchitectureEnabled() { // To opt-in for the New Architecture, you can either: // - Set `newArchEnabled` to true inside the `gradle.properties` file // - Invoke gradle with `-newArchEnabled=true` // - Set an environment variable `ORG_GRADLE_PROJECT_newArchEnabled=true` return project.hasProperty("newArchEnabled") && project.newArchEnabled == "true" } if (isNewArchitectureEnabled()) { apply plugin: "com.facebook.react" } apply plugin: "com.android.library" apply plugin: "kotlin-android" def safeExtGet(prop, fallback) { rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback } def safeExtGetBool(prop, fallback) { Boolean.parseBoolean("${safeExtGet(prop, fallback)}") } def reactNativeArchitectures() { def value = project.getProperties().get("reactNativeArchitectures") return value ? value.split(",") : ["armeabi-v7a", "x86", "x86_64", "arm64-v8a"] } static def findNodeModules(baseDir) { def basePath = baseDir.toPath().normalize() // Node"s module resolution algorithm searches up to the root directory, // after which the base path will be null while (basePath) { def nodeModulesPath = Paths.get(basePath.toString(), "node_modules") def reactNativePath = Paths.get(nodeModulesPath.toString(), "react-native") if (nodeModulesPath.toFile().exists() && reactNativePath.toFile().exists()) { return nodeModulesPath.toString() } basePath = basePath.getParent() } throw new GradleException("react-native-vision-camera: Failed to find node_modules/ path!") } def nodeModules = findNodeModules(projectDir) def hasWorklets = !safeExtGetBool('VisionCamera_disableFrameProcessors', false) && findProject(":react-native-worklets-core") != null logger.warn("[VisionCamera] react-native-worklets-core ${hasWorklets ? "found" : "not found"}, Frame Processors ${hasWorklets ? "enabled" : "disabled"}!") def enableCodeScanner = safeExtGetBool('VisionCamera_enableCodeScanner', false) repositories { google() mavenCentral() } android { if (agpVersion >= 7) { namespace "com.mrousavy.camera" } // Used to override the NDK path/version on internal CI or by allowing // users to customize the NDK path/version from their root project (e.g. for M1 support) if (rootProject.hasProperty("ndkPath")) { ndkPath rootProject.ext.ndkPath } if (rootProject.hasProperty("ndkVersion")) { ndkVersion rootProject.ext.ndkVersion } buildFeatures { prefab true prefabPublishing true } prefab { VisionCamera { headers "${project.buildDir}/headers/visioncamera/" } } defaultConfig { minSdkVersion safeExtGet("minSdkVersion", 26) compileSdkVersion safeExtGet("compileSdkVersion", 33) targetSdkVersion safeExtGet("targetSdkVersion", 33) versionCode 1 versionName "1.0" buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString() externalNativeBuild { cmake { cppFlags "-O2 -frtti -fexceptions -Wall -Wno-unused-variable -fstack-protector-all" arguments "-DANDROID_STL=c++_shared", "-DNODE_MODULES_DIR=${nodeModules}", "-DENABLE_FRAME_PROCESSORS=${hasWorklets ? "ON" : "OFF"}" abiFilters (*reactNativeArchitectures()) } } } sourceSets { main { manifest.srcFile androidManifestPath } } compileOptions { sourceCompatibility JavaVersion.VERSION_17 targetCompatibility JavaVersion.VERSION_17 } externalNativeBuild { cmake { path "CMakeLists.txt" } } packagingOptions { doNotStrip resolveBuildType() == "debug" ? "**/**/*.so" : "" excludes = [ "META-INF", "META-INF/**", "**/libc++_shared.so", "**/libfbjni.so", "**/libjsi.so", "**/libfolly_json.so", "**/libfolly_runtime.so", "**/libglog.so", "**/libhermes.so", "**/libhermes-executor-debug.so", "**/libhermes_executor.so", "**/libreactnativejni.so", "**/libturbomodulejsijni.so", "**/libreact_nativemodule_core.so", "**/libjscexecutor.so" ] } } dependencies { //noinspection GradleDynamicVersion implementation "com.facebook.react:react-android:+" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3" if (enableCodeScanner) { // User enabled code-scanner, so we bundle the 2.4 MB model in the app. implementation 'com.google.mlkit:barcode-scanning:17.2.0' } else { // Fall-back to just including the code for the CodeScanner to avoid the 2.4 MB bundle in the app. // On devices with Google Play Services, this can also download the CodeScanner model on-demand. implementation "com.google.android.gms:play-services-mlkit-barcode-scanning:18.3.0" } if (hasWorklets) { // Frame Processor integration (optional) implementation project(":react-native-worklets-core") } } task deleteCmakeCache() { doFirst { delete "${projectDir}/.cxx" delete "${nodeModules}/react-native-vision-camera/android/.cxx" delete "${nodeModules}/react-native-vision-camera/android/build" } } task prepareHeaders(type: Copy) { from fileTree('./src/main/cpp').filter { it.isFile() } include "*.h" into "${project.buildDir}/headers/visioncamera/react-native-vision-camera/" includeEmptyDirs = false } preBuild.dependsOn(prepareHeaders) tasks.configureEach { task -> // C++ build if (task.name.contains("configureCMakeDebug")) { rootProject.getTasksByName("packageReactNdkDebugLibs", true).forEach { task.dependsOn(it) } } if (task.name.contains("configureCMakeRel")) { rootProject.getTasksByName("packageReactNdkReleaseLibs", true).forEach { task.dependsOn(it) } } // C++ clean if (task.name.contains("clean")) { task.dependsOn(deleteCmakeCache) } }