大疆无人机二次开发简介-引入DJI mobile SDK 4.8

基于android studio 3.5

1、引入DJI mobile SDK 4.8和DJI UX SDK 4.8

部分build.gradle如下

apply plugin: 'com.android.application'

android {
    compileSdkVersion 27
    buildToolsVersion "27.0.3"
    defaultConfig {
        multiDexEnabled true
        vectorDrawables.useSupportLibrary = true
        ndk {
            abiFilters 'armeabi-v7a', 'x86', 'arm64-v8a'
        }
    }
    dexOptions {
        preDexLibraries = false
        javaMaxHeapSize "4g"
    }
    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"
        pickFirst 'lib/*/libstlport_shared.so'
        pickFirst 'lib/*/libRoadLineRebuildAPI.so'
        pickFirst 'lib/*/libGNaviUtils.so'
        pickFirst 'lib/*/libGNaviMapex.so'
        pickFirst 'lib/*/libGNaviData.so'
        pickFirst 'lib/*/libGNaviMap.so'
        pickFirst 'lib/*/libGNaviSearch.so'
        exclude 'META-INF/rxjava.properties'
    }
}
dependencies {
    //DJI UI库
    compile 'com.dji:dji-uxsdk:4.8'
    //DJI SDK
    provided 'com.dji:dji-sdk-provided:4.8'
}

2、AndroidManifest配置

 <!-- DJI SDK need permission -->
    <uses-permission android:name="android.permission.BLUETOOTH" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
    <uses-permission android:name="android.permission.VIBRATE" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />

    <uses-feature android:name="android.hardware.camera" />
    <uses-feature android:name="android.hardware.camera.autofocus" />
    <uses-feature
        android:name="android.hardware.usb.host"
        android:required="false" />
    <uses-feature
        android:name="android.hardware.usb.accessory"
        android:required="true" />

    <!-- SDK requirement permission end -->
 <application
        android:name=".YourApplication"
        android:allowBackup="true"
        android:icon="@mipmap/applogo"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme"
        tools:replace="android:icon,android:theme">

        <!-- DJI SDK -->
        <uses-library android:name="com.android.future.usb.accessory" />

        <meta-data
            android:name="com.dji.sdk.API_KEY"
            android:value="Your Key" /> <!-- KEY去大疆开发者网页去申请android mobile SDK -->
        <!-- DJI SDK -->

       
        <activity
            android:name=".UI.StartActivity"
            android:configChanges="orientation|keyboardHidden|screenSize"
            android:label="@string/app_name"
            android:launchMode="standard"
            android:theme="@style/WelcomeTheme">

        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
        <intent-filter>
            <action android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED" />
        </intent-filter>

        <meta-data
            android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED"
            android:resource="@xml/accessory_filter" />
        </activity>  
    </application>

3、注册帮助类,从4.4之后

在Applicatiom中加入如下代码:

 @Override
    protected void attachBaseContext(Context base) {
        super.attachBaseContext(base);
        MultiDex.install(this);
        Helper.install(YourApplication.this);//引入大疆帮助类
    }

4、MainActivity连接飞机

FlightController mFlightController = null;
FlightController.OnboardSDKDeviceDataCallback receiveCallback;
    private AtomicBoolean isRegistrationInProgress = new AtomicBoolean(false);
    private DJISDKManager.SDKManagerCallback registrationCallback = new DJISDKManager.SDKManagerCallback() {

        @Override
        public void onRegister(DJIError error) {
            isRegistrationInProgress.set(false);
            if (error == DJISDKError.REGISTRATION_SUCCESS) {
                DJISDKManager.getInstance().setCallbackRunInUIThread(true);
                DJISDKManager.getInstance().startConnectionToProduct();
                //Toast.makeText(getApplicationContext(), "SDK registration succeeded!", Toast.LENGTH_LONG).show();
                myHandler.sendEmptyMessage(3);//检查登陆
            } else {

                Toast.makeText(getApplicationContext(),
                        //"SDK registration failed, check network and retry!",
                        "DJI SDK 注册失败, 请检查网络后重试!",
                        Toast.LENGTH_LONG).show();
            }
        }


        @Override
        public void onProductChange(BaseProduct baseProduct, BaseProduct baseProduct1) {
            Log.v(TAG, String.format("onProductChanged oldProduct:%s, newProduct:%s", baseProduct, baseProduct1));
            mProduct = baseProduct1;
            if (mProduct != null) {
                mProduct.setBaseProductListener(mDJIBaseProductListener);
            }

            notifyStatusChange();
        }

        private BaseProduct.BaseProductListener mDJIBaseProductListener = new BaseProduct.BaseProductListener() {

            @Override
            public void onComponentChange(BaseProduct.ComponentKey key, BaseComponent oldComponent, BaseComponent newComponent) {

                if (newComponent != null) {
                    newComponent.setComponentListener(mDJIComponentListener);
                }
                Log.v(TAG, String.format("onComponentChange key:%s, oldComponent:%s, newComponent:%s", key, oldComponent, newComponent));

                notifyStatusChange();
            }

            @Override
            public void onConnectivityChange(boolean b) {
                Log.v(TAG, "onProductConnectivityChanged: " + b);
                notifyStatusChange();
            }
        };

        private BaseComponent.ComponentListener mDJIComponentListener = new BaseComponent.ComponentListener() {

            @Override
            public void onConnectivityChange(boolean b) {
                notifyStatusChange();
            }

        };

        private void notifyStatusChange() {
            myHandler.sendEmptyMessage(2);
        }

    };
    private static final String[] REQUIRED_PERMISSION_LIST = new String[]{
            Manifest.permission.VIBRATE,
            Manifest.permission.INTERNET,
            Manifest.permission.ACCESS_WIFI_STATE,
            Manifest.permission.WAKE_LOCK,
            Manifest.permission.ACCESS_COARSE_LOCATION,
            Manifest.permission.ACCESS_NETWORK_STATE,
            Manifest.permission.ACCESS_FINE_LOCATION,
            Manifest.permission.CHANGE_WIFI_STATE,
            Manifest.permission.WRITE_EXTERNAL_STORAGE,
            Manifest.permission.BLUETOOTH,
            Manifest.permission.BLUETOOTH_ADMIN,
            Manifest.permission.READ_EXTERNAL_STORAGE,
            Manifest.permission.READ_PHONE_STATE,
    };
    private static final int REQUEST_PERMISSION_CODE = 12345;
    private List<String> missingPermission = new ArrayList<>();

    /**
     * Checks if there is any missing permissions, and
     * requests runtime permission if needed.
     */
    private void checkAndRequestPermissions() {
        // Check for permissions
        for (String eachPermission : REQUIRED_PERMISSION_LIST) {
            if (ContextCompat.checkSelfPermission(this, eachPermission) != PackageManager.PERMISSION_GRANTED) {
                missingPermission.add(eachPermission);
            }
        }
        // Request for missing permissions
        if (missingPermission.isEmpty()) {
            startSDKRegistration();
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            ActivityCompat.requestPermissions(this,
                    missingPermission.toArray(new String[missingPermission.size()]),
                    REQUEST_PERMISSION_CODE);
        }
    }

    /**
     * Result of runtime permission request
     */
    @Override
    public void onRequestPermissionsResult(int requestCode,
                                           @NonNull String[] permissions,
                                           @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        // Check for granted permission and remove from missing list
        if (requestCode == REQUEST_PERMISSION_CODE) {
            for (int i = grantResults.length - 1; i >= 0; i--) {
                if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
                    missingPermission.remove(permissions[i]);
                }
            }
        }
        // If there is enough permission, we will start the registration
        if (missingPermission.isEmpty()) {
            startSDKRegistration();
        } else {
            //Toast.makeText(getApplicationContext(), "Missing permissions!!!", Toast.LENGTH_LONG).show();
        }
    }

    private void startSDKRegistration() {
        if (isRegistrationInProgress.compareAndSet(false, true)) {
            AsyncTask.execute(new Runnable() {
                @Override
                public void run() {
                    DJISDKManager.getInstance()
                            .registerApp(MainActivity.this, registrationCallback);
                }
            });
        }
    }

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

private void refreshSDKRelativeUI() {//此方法sendEmptyMessege 2的调用
    mProduct = SearchApplication.getProductInstance();
    if (null != mProduct && mProduct.isConnected()) {        
        if (mFlightController == null) {
            Aircraft mAircraft1 = (Aircraft) DJISDKManager.getInstance().getProduct();
            if (mAircraft1 != null)
                mFlightController = mAircraft1.getFlightController();//获取飞控类
        }
        if (mFlightController != null) {
            if (mFlightController.isOnboardSDKDeviceAvailable() && bFirst && actimer == null)//检查板载SDK
        }
        imgproduct.setImageResource(R.mipmap.v2_m600_pro_connect_icon);
        String str = mProduct instanceof Aircraft ? "DJIAircraft" : "DJIHandHeld";
        mTextConnectionStatus.setText("状态: " + str + " 连接成功");
        if (null != mProduct.getModel()) {
            mTextProduct.setText("" + mProduct.getModel().getDisplayName());
        } else {
            mTextProduct.setText(R.string.product_information);
        }

        if (receiveCallback == null) {
            receiveCallback = new FlightController.OnboardSDKDeviceDataCallback() {//板载SDK回复的数据,如果要用到的话
                @Override
                public void onReceive(byte[] bytes) {
                
                }
            };
            mFlightController.setOnboardSDKDeviceDataCallback(receiveCallback);
        }
    }
}

5、高版本SDK必须要登录帐号,如果版本过低或者未登录帐号,飞机则会限高限远,下面是检查登录和登录操作

private void loginAccount() {//检查登录

        UserAccountState userAccountState = UserAccountManager.getInstance().getUserAccountState();
        //如果用户 NOT_LOGGED_IN TOKEN_OUT_OF_DATE INVALID_TOKEN UNKNOWN 则弹出对话框重新登陆
        if (userAccountState == UserAccountState.NOT_LOGGED_IN ||
                userAccountState == UserAccountState.TOKEN_OUT_OF_DATE ||
                userAccountState == UserAccountState.INVALID_TOKEN ||
                userAccountState == UserAccountState.UNKNOWN) {
            login();
        } else {//否则显示用户名
            UserAccountManager.getInstance().getLoggedInDJIUserAccountName(new CommonCallbacks.CompletionCallbackWith<String>() {
                @Override
                public void onSuccess(String s) {
                    csUser = s;
                    myHandler.sendEmptyMessage(0);
                }

                @Override
                public void onFailure(DJIError djiError) {
                    login();
                }
            });
        }
    }
  private void login() {
        if (UserAccountManager.getInstance() == null)
            return;
        UserAccountManager.getInstance().logIntoDJIUserAccount(MainActivity.this,
                new CommonCallbacks.CompletionCallbackWith<UserAccountState>() {
                    @Override
                    public void onSuccess(final UserAccountState userAccountState) {
                        if (userAccountState == UserAccountState.NOT_AUTHORIZED ||
                                userAccountState == UserAccountState.AUTHORIZED) {
                            Toast.makeText(MainActivity.this, "登陆成功", Toast.LENGTH_LONG).show();
                            UserAccountManager.getInstance().getLoggedInDJIUserAccountName(new CommonCallbacks.CompletionCallbackWith<String>() {
                                @Override
                                public void onSuccess(String s) {
                                    csUser = s;
                                    myHandler.sendEmptyMessage(0);
                                }

                                @Override
                                public void onFailure(DJIError djiError) {

                                }
                            });
                        }
                    }

                    @Override
                    public void onFailure(DJIError error) {
                        Toast.makeText(MainActivity.this, "登陆错误:" + error.getDescription(), Toast.LENGTH_LONG).show();
                    }
                });
    }

6、可以FlightController 获取飞控信息,或者直接用UI库里面的控件会自动刷新飞行器信息

猜你喜欢

转载自blog.csdn.net/woshileihuanji/article/details/79245329
4.8