plugins { id "com.android.application" id "kotlin-android" // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins. id "dev.flutter.flutter-gradle-plugin" } android { namespace = "com.dji.flutter.dji_msdk_sample" compileSdk = 35 // DJI MSDK V4 ships prebuilt native (.so) libraries; pin a known-good NDK. ndkVersion = flutter.ndkVersion compileOptions { sourceCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8 } kotlinOptions { jvmTarget = JavaVersion.VERSION_1_8 } defaultConfig { applicationId = "com.dji.flutter.dji_msdk_sample" // DJI MSDK V4 requires Android 5.0+ (API 21). minSdkVersion = flutter.minSdkVersion targetSdk = 34 versionCode = flutter.versionCode versionName = flutter.versionName // DJI's SDK + Secneo Helper class loading require MultiDex. multiDexEnabled = true // DJI provides prebuilt .so files only for these ABIs. ndk { abiFilters "armeabi-v7a", "arm64-v8a" } // The DJI App Key is injected into AndroidManifest.xml at build time. // Set DJI_API_KEY in android/gradle.properties (or pass -PDJI_API_KEY=...). manifestPlaceholders["DJI_API_KEY"] = (project.findProperty("DJI_API_KEY") ?: "PASTE_YOUR_DJI_APP_KEY_HERE") } buildTypes { release { // TODO: Add your own signing config for the release build. // Signing with the debug keys for now, so `flutter run --release` works. signingConfig = signingConfigs.debug // DJI requires its ProGuard rules when minify is enabled. proguardFiles getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro" } } // DJI native libraries must not be stripped, and several bundled assets/ // resources collide across the SDK modules and must be de-duplicated. packaging { jniLibs { keepDebugSymbols += [ "**/libdjivideo.so", "**/libSDKRelativeJNI.so", "**/libFlyForbid.so", "**/libduml_vision_bokeh.so", "**/libyuv2.so", "**/libGroudStation.so", "**/libFRCorkscrew.so", "**/libUpgradeVerify.so", "**/libFR.so", "**/libDJIFlySafeCore.so", "**/libdjifs_jni.so", "**/libsfjni.so", "**/libDJICommonJNI.so", "**/libDJICSDKCommon.so", "**/libDJIUpgradeCore.so", "**/libDJIUpgradeJNI.so", "**/libDJIWaypointV2Core.so", "**/libdjiwaypointv2.so", "**/libDJIMOP.so", "**/libDJISDKLOGJNI.so", ] } resources { excludes += [ "META-INF/rxjava.properties", "META-INF/proguard/*", "META-INF/INDEX.LIST", "META-INF/DEPENDENCIES", "assets/location_map_gps_locked.png", "assets/location_map_gps_3d.png", ] pickFirsts += [ "lib/**/libstlport_shared.so", "lib/**/libRoadLineRebuildAPI.so", "lib/**/libGNaviUtils.so", "lib/**/libGNaviMapex.so", "lib/**/libGNaviMap.so", "lib/**/libGNaviSearch.so", ] } } } flutter { source = "../.." } dependencies { // DJI Mobile SDK V4 (core). 'provided' contains compile-time-only stubs. implementation "com.dji:dji-sdk:4.18" compileOnly "com.dji:dji-sdk-provided:4.18" implementation "androidx.multidex:multidex:2.0.1" implementation "androidx.core:core-ktx:1.13.1" // The DJI SDK bundles layouts that reference AppCompat (srcCompat) and // ConstraintLayout attributes, so these must be on the resource classpath. implementation "androidx.appcompat:appcompat:1.6.1" implementation "androidx.constraintlayout:constraintlayout:2.1.4" // DJI's SDK publishes an event bus dependency used internally by some callbacks. implementation "com.squareup:otto:1.3.8" // Required by the FlySafe / GEO modules pulled in by the SDK. implementation "androidx.recyclerview:recyclerview:1.3.2" } // --- Gradle 8 task-validation workaround ------------------------------------ // Flutter's `compileFlutterBuild` task declares an output directory // that overlaps the Android source sets, so Gradle 8's execution-time // validation flags several AGP tasks (mergeShaders, checkAarMetadata, …) as // consuming that output without a declared dependency, failing the build. // Wire the dependency in explicitly. Safe: none of these tasks are inputs to // the Flutter compile task, so no dependency cycle is introduced. afterEvaluate { def flutterTaskFor = { String name -> for (v in ["Debug", "Release", "Profile"]) { if (name.contains(v)) return tasks.findByName("compileFlutterBuild${v}") } return null } // Merge* source-set tasks (shaders / assets / jniLibs) — public AGP type. tasks.withType(com.android.build.gradle.tasks.MergeSourceSetFolders).configureEach { t -> def ft = flutterTaskFor(t.name) if (ft != null) t.dependsOn(ft) } // Other AGP tasks that read the merged inputs. tasks.matching { it.name ==~ /^(check|process|package|bundle|lintVitalAnalyze|lintAnalyze)(Debug|Release|Profile).*/ }.configureEach { t -> def ft = flutterTaskFor(t.name) if (ft != null) t.dependsOn(ft) } }