Files
PilotVault/Fly App
tajniak81andClaude Opus 5.5 e02bb0e5cd Give the Fly App GO 4-style obstacle radar, on-screen sticks, AirSense and fly zones
Vision radar: graded obstacle sectors around the centre of the video,
the nearest distance per side, the obstacle overhead, and BLOCKED on a
side whose sensors cannot see once the motors run. On aircraft with 360°
sensing, sides without their own readings are filled from the
perception ring. The same sectors sit on the attitude ball's rim, turned
by the heading. Settings > Vision gains Display radar chart and the
braking / sensing distances per direction.

On-screen sticks: the rail's STICKS button hands the aircraft to two
stick pads after a slide-to-confirm. The 25 Hz stream runs natively and
sends zeros once Dart's last command is 300 ms old, so a stalled UI
leaves the aircraft hovering. The sticks close when the remote takes
over, on RTH or on landing. They are simulator-only on aircraft with a
remote unless Settings > General > Developer allows real flights; Spark
and Mavic Air on Wi-Fi may fly them for real. Which MSDK axis is forward
in velocity + body mode is coded from DJI's documentation and must be
checked in the simulator first.

AirSense: a banner for manned aircraft at warning level 2 and up, with
distance, direction and ICAO code; the planes on the map; the full list
in a sheet and Settings > Safety; and the aircraft's own avoidance
action with its countdown.

Fly zones: DJI GEO zones around the aircraft (or the phone) on the map
with their height limits, a banner for FlySafe notices and in/near-zone
states, take-off refused in restricted and locked authorization zones,
self-unlock of authorization zones, the aircraft's licences (enable,
sync from the DJI account, remove all; ground only), and the GEO
database version with an update button.

Tested with unit and widget tests and screenshot renders only; nothing
has run on an aircraft or the simulator yet.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 21:14:12 +02:00
..

DJI MSDK Sample (Flutter)

A sample app demonstrating how to drive the DJI Mobile SDK V4 from Flutter.

DJI does not ship an official Flutter SDK — the Mobile SDK is a native Android/iOS library. This project therefore puts a Flutter UI on top of a thin native Android (Kotlin) bridge that talks to the DJI MSDK over platform channels. It covers the core "sample app" flow: SDK registration, product connection, and live telemetry (battery, GPS, flight status).

Android only. The DJI MSDK V4 native libraries here are wired up for Android. iOS would need a parallel Swift/Obj-C bridge (and a Mac to build).

Architecture

┌────────────────────────┐        platform channels        ┌─────────────────────────┐
│ Flutter (Dart)         │  dji_msdk/methods  (MethodChannel)│ Android (Kotlin)        │
│  lib/main.dart         │ ───────────────────────────────▶ │  DjiSdkBridge.kt        │
│  lib/dji_service.dart  │  dji_msdk/events   (EventChannel) │   └─ DJI Mobile SDK V4  │
│                        │ ◀─────────────────────────────── │  DjiApplication.kt      │
└────────────────────────┘                                  └─────────────────────────┘
File Responsibility
lib/dji_service.dart Dart wrapper over the method/event channels
lib/main.dart UI: registration / connection / telemetry cards
android/app/.../DjiApplication.kt Installs the Secneo Helper (required by MSDK V4)
android/app/.../MainActivity.kt Hosts the bridge, requests runtime permissions
android/app/.../DjiSdkBridge.kt Registration, product lifecycle, telemetry callbacks
android/app/build.gradle DJI deps, native-lib packaging, multidex, ABI filters

Prerequisites

  1. Flutter (stable) and Android SDK with a connected Android device (the DJI SDK does not work on emulators).
  2. A DJI drone + remote controller supported by MSDK V4 (Phantom 4, Mavic 2 / Air / Mini 1, Spark, Inspire 2, etc.). The RC connects to the phone over USB.
  3. A DJI App Key (see below).

Set your DJI App Key

SDK registration will fail without a valid App Key bound to this app's application id.

  1. Sign in at https://developer.dji.com/user/apps/ and create a new app.

    • Package name must be exactly: com.pilotvault.flyapp
    • SDK: Mobile SDK
  2. Copy the generated App Key.

  3. Put it in your user-global Gradle properties — not in the repo. Gradle merges this file into every build, so the key stays off version control:

    • Linux/macOS: ~/.gradle/gradle.properties
    • Windows: %USERPROFILE%\.gradle\gradle.properties
    PILOTVAULT_FLY_API_KEY=your_real_app_key_here
    

    For a one-off build you can pass it inline instead:

    flutter build apk --debug -PPILOTVAULT_FLY_API_KEY=your_real_app_key_here
    

    The key is injected into AndroidManifest.xml at build time via a manifestPlaceholder (com.dji.sdk.API_KEY). If it is missing the build still succeeds but prints a warning, and SDK registration fails on the aircraft — so watch for that warning.

Run

flutter pub get
flutter run            # device must be plugged in
# or just build the APK:
flutter build apk --debug

Using the app

  1. Launch it and grant the location / phone / mic permissions it requests.
  2. Tap Register app — needs internet on first run; status turns green on success.
  3. Connect the drone's remote controller to the phone over USB and power on the aircraft. The app auto-starts a connection on successful registration; you can also tap Connect to product.
  4. Once an aircraft connects, the Telemetry card streams battery %, GPS satellite count, flight mode, altitude, and position.

Notes & gotchas

  • MSDK V4 version is pinned to 4.18 (com.dji:dji-sdk / dji-sdk-provided).
  • android.enableJetifier=true is required — the SDK still uses legacy support libraries.
  • The native .so files are kept unstripped and de-duplicated via the packaging { } block in android/app/build.gradle; only armeabi-v7a and arm64-v8a ABIs are bundled (the only ABIs DJI provides).
  • This sample uses the core SDK, not the DJI UX SDK (its native UI widgets don't embed cleanly in Flutter).