Mobile Application Development for Drone Control
Most B2B and B2C drones provide mobile SDK: DJI Mobile SDK (iOS/Android), Parrot Ground SDK, Autel SDK, Skydio. Building app from scratch without SDK — implementing MAVLink over UDP/TCP directly to drone, makes sense for custom platforms on ArduPilot or PX4. We'll cover both approaches because architecture requirements differ fundamentally.
DJI SDK: Where Time Is Lost
App Registration and Offline Mode
DJI Mobile SDK requires AppKey registration on DJI server on first launch. Without internet SDK doesn't initialize fully. Means: app cannot control drone in area without connection until passing online registration at least once. For industrial use (pipeline inspection, working in canyons) — hard limitation. DJI provides OfflineActivation via Enterprise license, separate contract with price starting several thousand dollars yearly.
ProductKey Lifecycle and Connection
DJI SDK 5.x connection algorithm:
-
SDKManager.getInstance().init()inApplication.onCreate() -
SDKManager.getInstance().registerApp()— async, callback inISDKManagerCallback - Only after
onRegisterSuccessstart listening toKeyedStoreorFlightController
Typical error: developer calls FlightController.getState() before registration complete, gets null, doesn't handle it, app crashes with NPE on first real flight. In SDK 4.x was especially unclear — some methods "worked" on DJI simulator but failed on real device.
Video Feed and Latency
DJI SDK decodes H.264/H.265 stream from drone via own VideoFeeder. Streaming latency on SurfaceView — 80–150 ms normally. If trying to process frames via ML (object detection) on main thread — latency grows to 500+ ms and control becomes unsafe. Correct scheme: decoded frames via MediaCodec with BUFFER_FLAG_END_OF_STREAM handling, ML inference in separate coroutine dispatcher with Dispatchers.Default, result displayed with next frame.
MAVLink on ArduPilot/PX4: Architecture Decisions
For custom platforms use dronefleet/mavlink (Java/Android) or MAVLink.swift (iOS). Protocol — binary, specific message IDs for control: SET_POSITION_TARGET_LOCAL_NED, COMMAND_LONG with MAV_CMD_NAV_TAKEOFF / MAV_CMD_NAV_LAND.
Connection: drone's Wi-Fi access point → UDP socket port 14550. On Android — DatagramSocket in CoroutineScope(Dispatchers.IO), heartbeat every 1000 ms via HEARTBEAT message. If heartbeat not received from drone 3 seconds — trigger emergency state in UI, block all control commands.
Critical detail: MAVLink packets go via UDP without delivery guarantee. For commands with acknowledgment (COMMAND_LONG) drone responds COMMAND_ACK. If ACK doesn't arrive in 500 ms — retry, max 3 attempts, then failure state. Must implement manually — no automatic retry in protocol.
UI for Control: Latency and Safety
Virtual joystick — most common control method. Implementation: MotionEvent on View, normalize coordinates to [-1, 1] range, send command at 20 Hz (every 50 ms). Below 10 Hz — drone starts "floating", above 30 Hz — unnecessary channel load without control improvement.
Mandatory UI safety elements:
- Return-to-Home button with confirmation (two taps or hold 2 sec)
- Battery level indicator with color coding (red at <20%)
- RC/Wi-Fi signal strength display
- Command lock on takeoff at GPS < 6 satellites (for GPS Hold modes)
Testing Without Drone
DJI provides Simulator in DJISDK — flight emulator with telemetry. For MAVLink — ArduPilot SITL (Software In The Loop) with physics simulation. Both allow automated flight scenario tests. UI tests via Espresso/XCUITest with mock telemetry repository.
Process and Timeframes
App with DJI SDK, basic control and video stream — 4–8 weeks. Custom MAVLink solution with extended UI, autonomous missions and analytics — 3–6 months. Estimate after drone platform, functionality requirements and certification study (if needed for app store with drone in dangerous device category).







