DJI Mobile SDK for Android

repository·master·Indexed 22 days ago

https://github.com/dji-sdk/mobile-sdk-android

A development kit for automating DJI products, providing control over flight, cameras, gimbals, and other subsystems. It includes the Keyed Interface system for state monitoring via DJIKey and KeyManager, a mission system managed by MissionControl and specialized Mission Operators (such as WaypointMission), and a Timeline mechanism for custom workflows. Version 4.18 supports integration via Maven or Gradle.

Tokens
3.3K
Snippets
6
Records
11
Agent score
78%

What's inside DJI Mobile SDK for Android

  1. How Keyed Interfaces work in DJI SDK

    master

    Introduced in SDK 4.0, Keyed Interfaces provide a modern way to access and monitor the state of a connected DJI product. Instead of using traditional component-based interfaces (e.g., getProduct().getCamera()), you use DJIKey objects as "addresses" to specific pieces of state and interact with them via the KeyManager.

    Core Workflow

    1. Identify the Key: Use a specific DJIKey subclass (like CameraKey or FlightControllerKey) to create a key representing the state you want to access.
    2. Access State: Use KeyManager.getValue() to retrieve the current value or KeyManager.setValue() to change it.
    3. Listen for Changes: Use KeyManager.addListener() to receive updates only when the specific state actually changes.

    Key Advantages over Existing Interfaces

    • Multiple Listeners: Unlike traditional state callbacks which often allow only one listener at a time, you can attach multiple KeyListener instances to the same DJIKey.
    • Reduced Noise: Traditional callbacks often fire at high frequencies regardless of whether the specific value changed. Keyed interface listeners are only triggered when the value actually changes.
    • Performance: The SDK uses an in-memory cache for keyed interfaces, reducing latency by avoiding unnecessary roundtrip calls to the hardware when a valid cached value exists.
    • UI Integration: The mechanism is optimized for UI layers; the DJI UI Library is built entirely on this interface.
    // Example: Accessing ISO via Keyed Interface
    DJIKey isoKey = CameraKey.create(CameraKey.ISO);
    DJISDKManager.getInstance().getKeyManager().getValue(isoKey, new GetCallback() {
        @Override public void onSuccess(@NonNull Object value) {
            if (value instanceof SettingsDefinitions.ISO) {
                SettingsDefinitions.ISO iso = (SettingsDefinitions.ISO) value;
                // Use ISO value
            }
        }
    
        @Override public void onFailure(@NonNull DJIError error) {
            // Handle error
        }
    });
  2. How Mission Operators and Mission Control work together

    master

    In SDK 4.0+, the mission system is managed through a centralized MissionControl singleton. Instead of a unified MissionManager, DJI uses specialized Mission Operators.

    • Mission Control: Acts as a conduit to access various mission operators. You access specific operators as properties of the MissionControl instance.
    • Mission Operators: Singletons that specialize in a single mission type (e.g., Waypoint missions). They use a Finite State Machine (FSM) to manage the mission lifecycle and provide listeners to notify your application of state changes.
    • Lifecycle Management: Operators provide interfaces to start, pause, resume, and stop missions, and handle uploading/downloading mission plans to the aircraft.
  3. Use Timeline Missions for custom workflows

    master

    The Timeline mechanism replaces the deprecated DJICustomMission and DJICustomMissionStep. It allows you to schedule and execute customized mission workflows in sequential order.

    • Elements: A timeline consists of elements. The SDK provides pre-built elements that correspond to the previously deprecated custom mission steps.
    • Triggers: The timeline supports mission triggers to add dynamic behavior during execution (note: no prebuilt triggers are currently included in the SDK).
    • Control: Like other missions, a timeline can be started, paused, resumed, and stopped.
  4. Use KeyManager to listen for state changes

    master

    To react to changes in product state (like altitude or battery level) without the overhead of high-frequency polling, use KeyManager.addListener(). This method allows you to register a KeyListener that triggers only when the value associated with a specific DJIKey changes.

    Implementation Steps

    1. Create the DJIKey for the property you want to monitor.
    2. Call DJISDKManager.getInstance().getKeyManager().addListener(key, listener).
    3. Implement onValueChange(Object oldValue, Object newValue) to handle the update.

    Example: Monitoring Aircraft Altitude

    // 1. Create the Flightcontroller altitude key object
    DJIKey altitudeKey = FlightControllerKey.create(FlightControllerKey.ALTITUDE);
    
    // 2. Add a listener for altitude changes
    DJISDKManager.getInstance().getKeyManager().addListener(altitudeKey, new KeyListener() {
        @Override public void onValueChange(@Nullable Object oldValue, @Nullable Object newValue) {
            if (newValue instanceof Float) {
                final float altitude = (Float) newValue;
                // Handle altitude change
            }
        }
    });
    // Create Flightcontroller altitude key object
    DJIKey altitudeKey = FlightControllerKey.create(FlightControllerKey.ALTITUDE);
    
    // Add a listener with KeyListener callback for altitude key. NOTE: You can add multiple listeners for the same key
    DJISDKManager.getInstance().getKeyManager().addListener(altitudeKey, new KeyListener() {
        @Override public void onValueChange(@Nullable Object oldValue, @Nullable Object newValue) {
            if (newValue instanceof Float) {
                final float altitude = (Float) newValue;
                // Do something with altitude value
            }
        }
    });
  5. Understand the DJI Mobile SDK Development Workflow

    master

    The development process for a DJI Mobile SDK application follows these standard steps:

    1. Prerequisites: Ensure your environment meets the requirements.
    2. Register as DJI Developer & Download SDK: Obtain your credentials and the SDK files.
    3. Integrate SDK into Application: Add the dependencies to your Android project.
    4. Run Application: Deploy to a device.
    5. Testing, Profiling & Debugging: Validate your implementation.
    6. Deploy: Release your application.
  6. Execute a Waypoint Mission

    master

    To create and run a waypoint mission, follow this workflow using the WaypointMission builder and the WaypointMissionOperator:

    1. Build: Create an instance of WaypointMission using its builder interface. Add waypoints, actions, and custom settings. Once built, the WaypointMission object is immutable.
    2. Validate Locally: Call checkParameters() to ensure the internal state of the mission plan is valid.
    3. Load: Call loadMission() on the operator to load the mission for validation by the product.
    4. Upload: Call uploadMission() to transfer the mission plan to the aircraft.
    5. Start: Once the upload is complete, call startMission() to begin execution.
  7. Integrate DJI Mobile SDK V4 for Android

    master

    To integrate the DJI Mobile SDK V4 into your Android project, declare the following dependencies in your build configuration. You can use either Maven or Gradle.

    Note: You must include both dji-sdk and dji-sdk-provided to ensure full functionality.

    ### Maven
    <dependency>
        <groupId>com.dji</groupId>
        <artifactId>dji-sdk</artifactId>
        <version>4.18</version>
    </dependency>
    
    <dependency>
        <groupId>com.dji</groupId>
        <artifactId>dji-sdk-provided</artifactId>
        <version>4.18</version>
    </dependency>
    
    ### Gradle
    compile 'com.dji:dji-sdk:4.18'
    provided 'com.dji:dji-sdk-provided:4.18'
  8. Configure ProGuard for DJI Android SDK

    master

    If you are using ProGuard for code shrinking and optimization, you must add specific rules to your proguard.cfg file depending on which version of the SDK you downloaded from the DJI Developer Website.

    There are two types of SDK distributions:

    1. AAR file
    2. API Library folder
    ### For AAR file
    "-libraryjars ./PATH_TO_THIS_FILE/dji_android_sdk.aar"
    
    ### For API Library folder
    Refer to the rules in the `proguard-rules.pro` file located in the Sample Code directory.
  9. Explore DJI SDK Sample Projects and Tutorials

    master

    DJI provides several tutorials and sample projects to demonstrate specific features of the Mobile SDK:

    • Application Activation and Aircraft Binding: Managing device connection and activation.
    • Getting Started with UX SDK: Using the DJI Mobile UX SDK suite.
    • Camera Application: Implementing FPV and camera controls.
    • MapView and Waypoint Application: Using GaodeMap or GoogleMap for waypoint missions.
    • TapFly and ActiveTrack Application: Implementing automated flight tracking.
    • Simulator Application: Testing logic without a physical aircraft.
    • GEO System Application: Handling geographic constraints.
  10. Create a DJIKey to address product state

    master

    A DJIKey acts as a unique address for a specific piece of state information. Each component (Camera, FlightController, Battery, etc.) has its own dedicated DJIKey subclass.

    To create a key, use the .create(String paramKey) method of the appropriate subclass. You can find available parameter keys in the class files or the component's existing interface documentation.

    Common Patterns

    • Single Component: CameraKey.create(CameraKey.ISO)
    • Indexed Components: For products with multiple components of the same type (like multiple batteries on a Matrice 600), pass an index to the create method.

    Examples

    // Access camera shooting mode
    DJIKey cameraShootPhotoModeKey = CameraKey.create(CameraKey.SHOOT_PHOTO_MODE);
        
    // Address a specific battery (e.g., battery index 2)
    DJIKey chargeRemainingOfBattery2Key = BatteryKey.create(BatteryKey.CHARGE_REMAINING, 2);
    
    // Access flight controller status
    DJIKey isFlyingKey = FlightControllerKey.create(FlightControllerKey.IS_FLYING);
    // Examples of DJIKey constructor methods
    DJIKey cameraShootPhotoModeKey = CameraKey.create(CameraKey.SHOOT_PHOTO_MODE);
        
    // Addresses specific battery if the product has multiple batteries (eg. Matrice 600)
    DJIKey chargeRemainingOfBattery2Key = BatteryKey.create(BatteryKey.CHARGE_REMAINING, 2);
    
    DJIKey isFlyingKey = FlightControllerKey.create(FlightControllerKey.IS_FLYING);
  11. Use Device Health Information for Diagnostics

    master

    For certain components (specifically Matrice 300 RTK and Zenmuse H20 series), you can use the hms.json and hms_match_sdkerror.json files to retrieve detailed error descriptions for device components. It is recommended to use this health information instead of older diagnostics for the flight controller and RTK.

    Note on Duplicated Errors: Some component errors (gimbal, battery, perception module) may appear duplicated on the Matrice 300 RTK. Use the following mapping to resolve them:

    | DJIDiagnosticsError | Enum Value | AlarmId |
    |:------------- |:---------------:| -------------:|
    | `BATTERY_DISCHARGE_OVER_CURRENT`  | 3001 | 0x110B0001|
    | `BATTERY_DISCHARGE_OVER_HEAT` | 3002 | 0x110B0002|
    | `BATTERY_LOW_TEMPERATURE` | 3003 | 0x110B0003|
    | `BATTERY_CELL_BROKEN` | 3004 | 0x110B0006 |
    | `GIMBAL_CONNECT_TO_FC_ERROR` | 2005 | 0x1D030001 |
    | `GIMBAL_GYROSCOPE_ERROR` | 2001 | 0x1D040002 |
    | `GIMBAL_PITCH_ERROR` | 2002 | 0x1D040004 |
    | `GIMBAL_ROLL_ERROR` | 2003 | 0x1D040003 |
    | `GIMBAL_YAW_ERROR` | 2004 | 0x1D040005 |