# 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 and create a new app. - **Package name** must be exactly: `com.dji.flutter.dji_msdk_sample` - SDK: **Mobile SDK** 2. Copy the generated **App Key**. 3. Paste it into [`android/gradle.properties`](android/gradle.properties): ```properties DJI_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`). ## Run ```bash 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).