Files
PilotVault/Fly App/android/app/build.gradle
T
tajniak81andClaude Opus 4.8 58655531f0 Give the Fly App its own identity instead of the DJI sample's
The app still shipped under the identity of the DJI MSDK Flutter sample it
was started from, so every install, log line and crash report named a DJI
sample rather than PilotVault. Rename both namespaces:

  Android  com.dji.flutter.dji_msdk_sample -> com.pilotvault.flyapp
  Dart     dji_msdk_sample                 -> pilotvault_fly

The Kotlin sources move under com/pilotvault/flyapp to match. The manifest's
meta-data name stays com.dji.sdk.API_KEY — that string is fixed by the SDK's
own lookup and is not ours to rename.

A DJI App Key is bound to the application id, so the old key died with the
old id and a new one was registered against com.pilotvault.flyapp. That
forced the key to be touched anyway, so stop committing it: the Gradle
property becomes PILOTVAULT_FLY_API_KEY and now lives in the developer's
~/.gradle/gradle.properties, which Gradle merges into every build.
android/gradle.properties keeps the build flags — gitignoring it wholesale
would have taken useAndroidX and the Flutter migrator flags out of version
control with it — and documents where the key belongs.

A missing key prints a banner rather than silently baking the placeholder
into an APK that cannot register, which otherwise only surfaces as a
registration failure once the tablet is out at the aircraft. That warning
uses println because `flutter build` filters Gradle's warn-level output.

The rename means Android treats this as a new app: uninstall
com.dji.flutter.dji_msdk_sample before installing, or both will sit on the
tablet.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-21 21:11:17 +02:00

182 lines
7.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.pilotvault.flyapp"
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.pilotvault.flyapp"
// 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.
// It is deliberately not stored in the repo — see android/gradle.properties
// for where to put it (~/.gradle/gradle.properties, or -P on the command
// line). Warn loudly when it is missing: the build still succeeds, but the
// resulting APK fails DJI SDK registration once it is on the aircraft.
// println, not logger.warn: `flutter build` filters Gradle's warn-level
// output, so a logger.warn here is never seen by the person building.
def djiAppKey = project.findProperty("PILOTVAULT_FLY_API_KEY")
if (!djiAppKey) {
println(
"\n**************************************************************\n" +
"WARNING: PILOTVAULT_FLY_API_KEY is not set.\n" +
"The APK will build, but DJI SDK registration will FAIL at\n" +
"runtime. Set the key in ~/.gradle/gradle.properties - see\n" +
"android/gradle.properties for details.\n" +
"**************************************************************\n")
}
manifestPlaceholders["PILOTVAULT_FLY_API_KEY"] =
(djiAppKey ?: "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)
}
}