大疆无人机 Mobile SDK Android应用程序搭建

  • 大疆官方开发文档目前没有提供中文的api,所以看起来可能会比较麻烦,尤其对于一些专业名词,基于官方的sdk我们能开发出什么呢?我们基于sdk可以开发出跟DJI go 4一模一样的功能
  • 目前的项目就是先把大疆官方支持的功能全部实现一遍
  • 然后在此基础上实现自己的功能,无论是全自动执行任务,还是远程控制都没有问题。我会在后面的篇章教大家如何基于大疆的sdk开发出一个完整的应用。
  • 不再做过多的解释直接上代码,代码中有相应的注解

在app下的build.gradle中的dependencies下导包

图片.png
plugins {
    id 'com.android.application'
}

android {
    compileSdkVersion 30

    defaultConfig {
        applicationId ""
        minSdkVersion 21
        targetSdkVersion 30
        versionCode 1
        versionName "1.0"
        multiDexEnabled true//这一行加上,否则会运行错误

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

    packagingOptions {
        doNotStrip "*/*/libdjivideo.so"
        doNotStrip "*/*/libSDKRelativeJNI.so"
        doNotStrip "*/*/libFlyForbid.so"
        doNotStrip "*/*/libduml_vision_bokeh.so"
        doNotStrip "*/*/libyuv2.so"
        doNotStrip "*/*/libGroudStation.so"
        doNotStrip "*/*/libFRCorkscrew.so"
        doNotStrip "*/*/libUpgradeVerify.so"
        doNotStrip "*/*/libFR.so"
        doNotStrip "*/*/libDJIFlySafeCore.so"
        doNotStrip "*/*/libdjifs_jni.so"
        doNotStrip "*/*/libsfjni.so"
        doNotStrip "*/*/libDJICommonJNI.so"
        doNotStrip "*/*/libDJICSDKCommon.so"
        doNotStrip "*/*/libDJIUpgradeCore.so"
        doNotStrip "*/*/libDJIUpgradeJNI.so"
        doNotStrip "*/*/libDJIWaypointV2Core.so"
        doNotStrip "*/*/libAMapSDK_MAP_v6_9_2.so"
        doNotStrip "*/*/libDJIMOP.so"
        doNotStrip "*/*/libDJISDKLOGJNI.so"
        exclude 'META-INF/rxjava.properties'
    }

}

dependencies {

    implementation 'androidx.appcompat:appcompat:1.2.0'
    implementation 'com.google.android.material:material:1.2.1'
    implementation 'androidx.constraintlayout:constraintlayout:2.0.1'
    testImplementation 'junit:junit:4.+'
    androidTestImplementation 'androidx.test.ext:junit:1.1.2'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'

    implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
    implementation('com.dji:dji-sdk:4.15.1', {
        /**
         * 如果您的应用程序不需要Mavic 2 Pro和Mavic 2 Zoom的反失真功能,请取消对“库反失真”的注释。
         * 如果您需要发布数据库,请取消对“飞行安全数据库”的注释,否则我们将在DJISDKManager.getInstance().registerApp时下载它
         * 被称为。
         * 两者都将大大减小APK的大小。
         */
        exclude module: 'library-anti-distortion'
        exclude module: 'fly-safe-database'
    })
    compileOnly 'com.dji:dji-sdk-provided:4.15.1'

}

在AndroidManifest.xml文件下添加对应的权限和配置




    
    
    
    
    
    
    
    
    
    
    
    
    
    
    

    
    


    

        

        

        
        

        
            
                
            
            

        

        


        
            
                

                
            
        


    


在Application中初始化类库

public class DroneApplication extends Application {

    @Override
    protected void attachBaseContext(Context base) {
        super.attachBaseContext(base);
        Helper.install(DroneApplication.this);
    }
}

MainActivity的代码如下

import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

import com.okq.flydemo.R;

import java.util.ArrayList;
import java.util.List;

import dji.common.error.DJIError;
import dji.common.error.DJISDKError;
import dji.common.realname.AircraftBindingState;
import dji.common.realname.AppActivationState;
import dji.common.useraccount.UserAccountState;
import dji.common.util.CommonCallbacks;
import dji.sdk.base.BaseComponent;
import dji.sdk.base.BaseProduct;
import dji.sdk.realname.AppActivationManager;
import dji.sdk.sdkmanager.DJISDKInitEvent;
import dji.sdk.sdkmanager.DJISDKManager;
import dji.sdk.useraccount.UserAccountManager;
import dji.thirdparty.afinal.core.AsyncTask;

public class MainActivity extends AppCompatActivity {

    private static final String[] PERMISSION_LIST = new String[]{
            Manifest.permission.VIBRATE, // 程序震动
            Manifest.permission.INTERNET, // 访问互联网
            Manifest.permission.ACCESS_WIFI_STATE, // 获取 WIFI 状态和 wifi 接入点信息
            Manifest.permission.WAKE_LOCK,//关闭屏幕时后台进程仍然进行
            Manifest.permission.ACCESS_COARSE_LOCATION, // 获得模糊定位信息
            Manifest.permission.ACCESS_NETWORK_STATE, // 获取网络状态信息
            Manifest.permission.ACCESS_FINE_LOCATION, // 获取精准定位信息
            Manifest.permission.CHANGE_WIFI_STATE, // 改变wifi连接状态
            Manifest.permission.WRITE_EXTERNAL_STORAGE, // 写入外部存储信息
            Manifest.permission.BLUETOOTH, // 配对蓝牙设备
            Manifest.permission.BLUETOOTH_ADMIN, // 配对蓝牙设备(不通知用户)
            Manifest.permission.READ_EXTERNAL_STORAGE, // 读取外部存储信息
            Manifest.permission.READ_PHONE_STATE, // 访问电话状态
            Manifest.permission.RECORD_AUDIO // 录音权限
    };

    //缺失的用户权限
    public static List missingPermission = new ArrayList<>();


    private Button btn_login,btn_logout,btn_status_appactivation,btn_status_aircraftbinding;

    private TextView tv_status_appactivation,tv_status_aircraftbinding;

    //应用程序激活状态监听
    private AppActivationState.AppActivationStateListener appActivationStateListener;
    //无人机绑定状态监听
    private AircraftBindingState.AircraftBindingStateListener aircraftBindingStateListener;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //检查用户权限
        if (!checkPermissions()) {
            requestPermissions();
        }
        if (checkPermissions()) {
            //注册应用程序
            registerAppLication();
        }

        initView();

        initListener();
    }

    private void initListener() {

        appActivationStateListener = new AppActivationState.AppActivationStateListener() {
            @Override
            public void onUpdate(AppActivationState appActivationState) {
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        tv_status_appactivation.setText("当前应用激活状态:"+appActivationState.name());
                    }
                });
            }
        };

        aircraftBindingStateListener = new AircraftBindingState.AircraftBindingStateListener() {
            @Override
            public void onUpdate(AircraftBindingState aircraftBindingState) {
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        tv_status_aircraftbinding.setText("当前无人机绑定状态:"+aircraftBindingState.name());
                    }
                });
            }
        };

        //添加应用程序激活监听
        AppActivationManager.getInstance().addAppActivationStateListener(appActivationStateListener);
        //添加无人机绑定监听
        AppActivationManager.getInstance().addAircraftBindingStateListener(aircraftBindingStateListener);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        //移除应用程序激活监听
        AppActivationManager.getInstance().removeAppActivationStateListener(appActivationStateListener);
        //移除无人机绑定监听
        AppActivationManager.getInstance().removeAircraftBindingStateListener(aircraftBindingStateListener);
    }

    private void initView() {
        tv_status_appactivation = (TextView) findViewById(R.id.tv_status_appactivation);
        tv_status_aircraftbinding = (TextView) findViewById(R.id.tv_status_aircraftbinding);

        //登录dji账号
        btn_login = (Button)findViewById(R.id.btn_login);
        btn_login.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                UserAccountManager.getInstance().logIntoDJIUserAccount(MainActivity.this, new CommonCallbacks.CompletionCallbackWith() {
                    @Override
                    public void onSuccess(UserAccountState userAccountState) {
                        ShowToas("登录成功");
                    }

                    @Override
                    public void onFailure(DJIError djiError) {
                        ShowToas("登录失败:"+djiError.getDescription());
                    }
                });
            }
        });

        //退出账号
        btn_logout = (Button)findViewById(R.id.btn_logout);
        btn_logout.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                UserAccountManager.getInstance().logoutOfDJIUserAccount(new CommonCallbacks.CompletionCallback() {
                    @Override
                    public void onResult(DJIError djiError) {
                        if (djiError == null){
                            ShowToas("退出成功");
                        }else {
                            ShowToas("退出失败:"+djiError.getDescription());
                        }
                    }
                });
            }
        });

        //获取应用激活状态
        btn_status_appactivation = (Button)findViewById(R.id.btn_status_appactivation);
        btn_status_appactivation.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                AppActivationManager appActivationManager = DJISDKManager.getInstance().getAppActivationManager();
                AppActivationState appActivationState = appActivationManager.getAppActivationState();
                ShowToas("激活状态:"+appActivationState);
                if (!(""+appActivationState).equals("ACTIVATED")){
                    Intent launchIntentForPackage = getPackageManager().getLaunchIntentForPackage("dji.go.v4");
                    if (launchIntentForPackage != null){
                        startActivity(launchIntentForPackage);
                    }else {
                        ShowToas("未安装 DJI Go");
                    }
                }

            }
        });

        //获取无人机绑定状态
        btn_status_aircraftbinding = (Button)findViewById(R.id.btn_status_aircraftbinding);
        btn_status_aircraftbinding.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                AppActivationManager appActivationManager = DJISDKManager.getInstance().getAppActivationManager();
                AircraftBindingState aircraftBindingState = appActivationManager.getAircraftBindingState();
                ShowToas("绑定状态:"+aircraftBindingState);
                if (!(""+aircraftBindingState).equals("BOUND")){
                    Intent launchIntentForPackage = getPackageManager().getLaunchIntentForPackage("dji.go.v4");
                    if (launchIntentForPackage != null){
                        startActivity(launchIntentForPackage);
                    }else {
                        ShowToas("未安装 DJI Go 4");
                    }
                }
            }
        });



    }


    //注册程序
    private void registerAppLication() {

        AsyncTask.execute(new Runnable() {
            @Override
            public void run() {
                DJISDKManager.getInstance().registerApp(MainActivity.this.getApplicationContext(), new DJISDKManager.SDKManagerCallback() {
                    @Override
                    public void onRegister(DJIError djiError) {//注册应用程序回调方法
                        if (djiError == DJISDKError.REGISTRATION_SUCCESS) {
                            ShowToas("onRegister--->应用注册成功:" + djiError.getDescription());
                            DJISDKManager.getInstance().enableBridgeModeWithBridgeAppIP("192.168.1.189");
                        } else {
                            ShowToas("onRegister--->应用注册失败:" + djiError.getDescription());
                        }
                    }

                    @Override
                    public void onProductDisconnect() {//无人机失去连接回调
                        ShowToas("onProductDisconnect--->设备断开连接");
                    }

                    @Override
                    public void onProductConnect(BaseProduct baseProduct) {//无人机连接回调
                        if (baseProduct.getModel() == null){
                            return;
                        }
                        ShowToas("onProductConnect--->设备连接"+baseProduct.getModel().getDisplayName());
                    }

                    @Override
                    public void onProductChanged(BaseProduct baseProduct) {//无人机连接变化回调
                        if (baseProduct == null){
                            return;
                        }
                        ShowToas("onProductChanged--->设备连接"+baseProduct.getModel().getDisplayName());
                    }

                    //无人机组件 变化变化回调
                    @Override
                    public void onComponentChange(BaseProduct.ComponentKey componentKey, BaseComponent baseComponent, BaseComponent baseComponent1) {
                        ShowToas("onComponentChange--->"+String.format("组件变化 键:%s,旧组件:%s,新组件:%s",componentKey,baseComponent,baseComponent1));
                    }

                    @Override
                    public void onInitProcess(DJISDKInitEvent djisdkInitEvent, int i) {//初始化进程回调
                        ShowToas("onInitProcess--->"+djisdkInitEvent.getInitializationState().toString() + "进度:" + i + "%");
                    }

                    @Override
                    public void onDatabaseDownloadProgress(long l, long l1) {//限飞数据库下载进度回调
//                        ShowToas("onDatabaseDownloadProgress--->已下载: "+l+"字节,总共:"+l1+"字节");
                        Log.i("TAG", "onDatabaseDownloadProgress--->已下载: "+l+"字节,总共:"+l1+"字节");
                    }
                });
            }
        });

    }

    private void ShowToas(String msg){

        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                Toast.makeText(MainActivity.this, msg, Toast.LENGTH_SHORT).show();
            }
        });

    }


    public boolean checkPermissions() {
        //判断应用程序编辑的SDK版本是否大于22
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            for (String string : PERMISSION_LIST) {
                if (ContextCompat.checkSelfPermission(MainActivity.this, string) != PackageManager.PERMISSION_GRANTED) {
                    //没有赋予的权限添加到集合中
                    missingPermission.add(string);
                }
            }
            return missingPermission.isEmpty();
        } else {
            return false;
        }
    }

    public void requestPermissions() {
        //申请所有没有被赋予的权限
        ActivityCompat.requestPermissions(MainActivity.this, missingPermission.toArray(new String[missingPermission.size()]), 1009);
    }

}

activity_main.xml布局文件如下




    

    

    

    
  • 至此就能获取对应的设备状态和账号登录等状态,我使用的御2无人机


    图片.png

DJI Go 4下载地址(https://www.dji.com/cn/downloads/djiapp/dji-go-4)

  • 参考资料《大疆无人机二次开发教程》

你可能感兴趣的:(大疆无人机 Mobile SDK Android应用程序搭建)