Files
PilotVault/Fly App/android/app/build.gradle
T
tajniak81andClaude Opus 4.8 a4a2709456 Rebuild Fly App to design v2 with full DJI SDK integration
Rebuild the Flutter/DJI-MSDK-V4 Fly App to the v2 UI kit and wire the
full SDK surface behind it.

Native (Kotlin): split DjiSdkBridge into a method/event router delegating
to per-subsystem SubBridge helpers sharing a BridgeCtx — FlightController
(takeoff/land/RTH + rich telemetry), Camera (mode/record/photo/exposure),
Gimbal, Mission (Waypoint + ActiveTrack; QuickShots via ActiveTrack
QUICK_SHOT), Media (MediaManager list/thumbnail/download), and optional
DJI account login. Manifest gains scoped media permissions.

Flutter: ten screens under lib/ui/ (Flight HUD, capture modes, camera
settings, settings menu, map+waypoints, home, album, academy, profile,
routes/flight logs), driven by an expanded FlightModel. New PVIcon renders
the kit's SVG paths via flutter_svg; map uses flutter_map + latlong2.

Pin transitive androidx.core/browser down to SDK-35-compatible versions
so the newer plugins don't force AGP 8.9.1 onto the DJI toolchain.

Verified with `flutter build apk --debug` (compiles Dart + all Kotlin);
runtime behaviour is untested here — it needs a physical DJI-connected
device.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 16:51:08 +02:00

167 lines
6.4 KiB
Groovy

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"
}
// --- Keep transitive AndroidX on the AGP-8.6 / compileSdk-35 track -----------
// The newer Flutter plugins (url_launcher / path_provider / flutter_svg) pull
// androidx.core 1.17 and androidx.browser 1.9, whose aar metadata demands AGP
// 8.9.1 + compileSdk 36. The DJI MSDK V4 toolchain is pinned to AGP 8.6 / SDK 35
// (bumping it risks the fragile native build), so force these artifacts back to
// versions that build against SDK 35. Their APIs used by the plugins are stable
// across this range.
configurations.all {
resolutionStrategy {
force "androidx.core:core:1.13.1"
force "androidx.core:core-ktx:1.13.1"
force "androidx.browser:browser:1.8.0"
}
}
// --- Gradle 8 task-validation workaround ------------------------------------
// Flutter's `compileFlutterBuild<Variant>` 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)
}
}