新闻  |   论坛  |   博客  |   在线研讨会
基于Mobile SDK V4版固件开发大疆无人机手机端遥控器(2)
美男子玩编程 | 2023-06-09 09:57:57    阅读:340   发布文章

上一篇文章(基于Mobile SDK V4版固件开发大疆无人机手机端遥控器(1))因为时间原因介绍了一部分内容,如果已经完成上一篇内容的操作就可以进行下面功能方面的制作了。自己开发的APP功能不是很多,但是已经将大疆无人机的常用功能进行了结合,同大家一起进行学习~

1

应用程序激活与绑定

如果在中国使用DJI飞行器固件,则需要使用该用户的DJI帐户激活控制DJI飞行器的移动应用程序。这将确保大疆能根据飞行器的地理位置和用户个人资料,为飞行器配置正确的地理空间信息和飞行功能集。激活系统的主要是:

  • 中国用户必须在每三个月至少登录一次DJI帐户以遍激活应用程序。

  • 激活信息将存储在应用程序中,直到用户注销为止。

  • 登录DJI帐号需要连接互联网。

  • 在中国境外,SDK会自动激活应用程序,无需用户登录。

  • 另外,中国用户必须将飞机绑定到DJI官方app中的用户帐户。这仅需要一次。如果未激活应用程序,未绑定飞机(如果需要)或使用旧版SDK(<4.1),则会禁用相机视频流,并且飞行限制在直径100m和高度30m的区域中,以确保飞机停留在视线范围内。

2

为应用程序创建UI

编写MApplication、ReceiverApplication和RegistrationActivity文件(此处粘贴部分代码)。

public class MApplication extends MultiDexApplication {
    private ReceiverApplication receiverApplication;
    @Override
    protected void attachBaseContext(Context paramContext) {
        super.attachBaseContext(paramContext);
        CrashHandler.getInstance().init(this);
        Helper.install(MApplication.this);
        if (receiverApplication == null) {
            receiverApplication = new ReceiverApplication();
            receiverApplication.setContext(this);
        }
    }
    @Override
    public void onCreate() {
        super.onCreate();
        receiverApplication.onCreate();
    }
}

上面的代码实现了绑定当前APP,将后续需要用到的类函数封装到ReceiverApplication 中,在ReceiverApplication 中也能够进行账户登录的操作。

public class ReceiverApplication extends MultiDexApplication {
    public static final String FLAG_CONNECTION_CHANGE = "activation_connection_change";
    private static BaseProduct mProduct;
    public Handler mHandler;
    private Application instance;
    public void setContext(Application application) {
        instance = application;
    }
    @Override
    protected void attachBaseContext(Context base) {
        super.attachBaseContext(base);
        Helper.install(this);
    }
    @Override
    public Context getApplicationContext() {
        return instance;
    }
    public ReceiverApplication() {
    }
    /**
     * This function is used to get the instance of DJIBaseProduct.
     * If no product is connected, it returns null.
     */

    public static synchronized BaseProduct getProductInstance() {
        if (null == mProduct) {
            mProduct = DJISDKManager.getInstance().getProduct();
        }
        return mProduct;
    }
    public static synchronized Aircraft getAircraftInstance() {
        if (!isAircraftConnected()) return null;
        return (Aircraft) getProductInstance();
    }
    public static synchronized Camera getCameraInstance() {
        if (getProductInstance() == nullreturn null;
        Camera camera = null;
        if (getProductInstance() instanceof Aircraft){
            camera = ((Aircraft) getProductInstance()).getCamera();
        } else if (getProductInstance() instanceof HandHeld) {
            camera = ((HandHeld) getProductInstance()).getCamera();
        }
        return camera;
    }
    public static boolean isAircraftConnected() {
        return getProductInstance() != null && getProductInstance() instanceof Aircraft;
    }
    public static boolean isHandHeldConnected() {
        return getProductInstance() != null && getProductInstance() instanceof HandHeld;
    }
    public static boolean isProductModuleAvailable() {
        return (null != ReceiverApplication.getProductInstance());
    }
    public static boolean isCameraModuleAvailable() {
        return isProductModuleAvailable() &&
                (null != ReceiverApplication.getProductInstance().getCamera());
    }
    public static boolean isPlaybackAvailable() {
        return isCameraModuleAvailable() &&
                (null != ReceiverApplication.getProductInstance().getCamera().getPlaybackManager());
    }
    @Override
    public void onCreate() {
        super.onCreate();
        mHandler = new Handler(Looper.getMainLooper());
        /**
         * When starting SDK services, an instance of interface DJISDKManager.DJISDKManagerCallback will be used to listen to
         * the SDK Registration result and the product changing.
         */

        //Listens to the SDK registration result
        DJISDKManager.SDKManagerCallback mDJISDKManagerCallback = new DJISDKManager.SDKManagerCallback() {
            //Listens to the SDK registration result
            @Override
            public void onRegister(DJIError error) {
                if (error == DJISDKError.REGISTRATION_SUCCESS) {
                    Handler handler = new Handler(Looper.getMainLooper());
                    handler.post(new Runnable() {
                        @Override
                        public void run() {
//                            ToastUtils.showToast(getApplicationContext(), "注册成功");
//                            Toast.makeText(getApplicationContext(), "注册成功", Toast.LENGTH_LONG).show();
//                            loginAccount();
                        }
                    });
                    DJISDKManager.getInstance().startConnectionToProduct();
                } else {
                    Handler handler = new Handler(Looper.getMainLooper());
                    handler.post(new Runnable() {
                        @Override
                        public void run() {
//                            ToastUtils.showToast(getApplicationContext(), "注册sdk失败,请检查网络是否可用");
//                            Toast.makeText(getApplicationContext(), "注册sdk失败,请检查网络是否可用", Toast.LENGTH_LONG).show();
                        }
                    });
                }
                Log.e("TAG", error.toString());
            }
            @Override
            public void onProductDisconnect() {
                Log.d("TAG""设备连接");
                notifyStatusChange();
            }
            @Override
            public void onProductConnect(BaseProduct baseProduct) {
                Log.d("TAG", String.format("新设备连接:%s", baseProduct));
                notifyStatusChange();
            }
            @Override
            public void onProductChanged(BaseProduct baseProduct) {
            }
            @Override
            public void onComponentChange(BaseProduct.ComponentKey componentKey, BaseComponent oldComponent,
                                          BaseComponent newComponent)
 
{
                if (newComponent != null) {
                    newComponent.setComponentListener(new BaseComponent.ComponentListener() {
                        @Override
                        public void onConnectivityChange(boolean isConnected) {
                            Log.d("TAG""设备连接已更改: " + isConnected);
                            notifyStatusChange();
                        }
                    });
                }
                Log.d("TAG",
                        String.format("设备改变 key:%s, 旧设备:%s, 新设备:%s",
                                componentKey,
                                oldComponent,
                                newComponent));
            }
            @Override
            public void onInitProcess(DJISDKInitEvent djisdkInitEvent, int i) {
            }
            @Override
            public void onDatabaseDownloadProgress(long l, long l1) {
            }
        };
        //Check the permissions before registering the application for android system 6.0 above.
        int permissionCheck = ContextCompat.checkSelfPermission(getApplicationContext(), android.Manifest.permission.WRITE_EXTERNAL_STORAGE);
        int permissionCheck2 = ContextCompat.checkSelfPermission(getApplicationContext(), android.Manifest.permission.READ_PHONE_STATE);
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M || (permissionCheck == 0 && permissionCheck2 == 0)) {
            //This is used to start SDK services and initiate SDK.
            DJISDKManager.getInstance().registerApp(getApplicationContext(), mDJISDKManagerCallback);
//            ToastUtils.showToast(getApplicationContext(), "正在注册,请等待...");
//            Toast.makeText(getApplicationContext(), "正在注册,请等待...", Toast.LENGTH_LONG).show();
        } else {
//            ToastUtils.showToast(getApplicationContext(), "请检查是否授予了权限");
//            Toast.makeText(getApplicationContext(), "请检查是否授予了权限。", Toast.LENGTH_LONG).show();
        }
    }
    private void notifyStatusChange() {
        mHandler.removeCallbacks(updateRunnable);
        mHandler.postDelayed(updateRunnable, 500);
    }
    private Runnable updateRunnable = new Runnable() {
        @Override
        public void run() {
            Intent intent = new Intent(FLAG_CONNECTION_CHANGE);
            getApplicationContext().sendBroadcast(intent);
        }
    };
}

上面的代码是对BaseProduct、Aircraft和Camera类进行实例化,在后续使用中不用再去进行重复的实例化工作,减少内存的消耗。

@Layout(R.layout.activity_registration)
public class RegistrationActivity extends BaseActivity implements View.OnClickListener{
    private static final String TAG = RegistrationActivity.class.getName();
    private AtomicBoolean isRegistrationInProgress = new AtomicBoolean(false);
    private static final String[] permissions = new String[]{
            Manifest.permission.BLUETOOTH,
            Manifest.permission.BLUETOOTH_ADMIN,
            Manifest.permission.VIBRATE,
            Manifest.permission.INTERNET,
            Manifest.permission.ACCESS_WIFI_STATE,
            Manifest.permission.ACCESS_COARSE_LOCATION,
            Manifest.permission.ACCESS_NETWORK_STATE,
            Manifest.permission.ACCESS_FINE_LOCATION,
            Manifest.permission.CHANGE_WIFI_STATE,
            Manifest.permission.RECORD_AUDIO,
            Manifest.permission.WRITE_EXTERNAL_STORAGE,
            Manifest.permission.READ_EXTERNAL_STORAGE,
            Manifest.permission.READ_PHONE_STATE,
    };
    @Override
    public void initViews() {
        isPermission();
        IntentFilter filter = new IntentFilter();
        filter.addAction(ReceiverApplication.FLAG_CONNECTION_CHANGE);
        registerReceiver(mReceiver, filter);
    }
    @Override
    public void initDatas() {
        startSDKRegistration();
    }
    @Override
    protected void requestData() {
        
    }
    @Override
    protected void onResume() {
        super.onResume();
    }
    private void isPermission() {
        requestRunTimePermission(permissions, new IPermission() {
            @Override
            public void onGranted() {
            }
            @Override
            public void onDenied(List<String> deniedPermissions) {
            }
        });
    }
  
    //无人机首次注册
        private void startSDKRegistration() {
            if (isRegistrationInProgress.compareAndSet(falsetrue)) {
                AsyncTask.execute(new Runnable() {
                    @Override
                    public void run() {
//                      showToasts("注册中,请等待...");
                        DJISDKManager.getInstance().registerApp(getApplicationContext(), new DJISDKManager.SDKManagerCallback() {
                            @Override
                            public void onRegister(DJIError djiError) {
                                if (djiError == DJISDKError.REGISTRATION_SUCCESS) {
                                    DJILog.e("App 注册", DJISDKError.REGISTRATION_SUCCESS.getDescription());
                                    DJISDKManager.getInstance().startConnectionToProduct();
    //                                showToasts("注册成功");
                                    loginAccount();
                                } else {
                                    showToasts("注册sdk失败,请检查网络是否可用");
                                }
                                Log.v(TAG, djiError.getDescription());
                            }
                            @Override
                            public void onProductDisconnect() {
                                Log.d(TAG, "产品断开连接");
    //                            showToasts("产品断开连接");
                            }
                            @Override
                            public void onProductConnect(BaseProduct baseProduct) {
                                Log.d(TAG, String.format("新产品连接:%s", baseProduct));
    //                            showToasts("产品连接");
                            }
                            @Override
                            public void onProductChanged(BaseProduct baseProduct) {
                            }
                            @Override
                            public void onComponentChange(BaseProduct.ComponentKey componentKey, BaseComponent oldComponent,
                                                          BaseComponent newComponent)
 
{
                                if (newComponent != null) {
                                    newComponent.setComponentListener(new BaseComponent.ComponentListener() {
                                        @Override
                                        public void onConnectivityChange(boolean isConnected) {
                                            Log.d(TAG, "组件连接已更改: " + isConnected);
                                        }
                                    });
                                }
                                Log.d(TAG, String.format("改变设备Key:%s, " + "旧设备:%s, " + "新设备:%s",
                                        componentKey, oldComponent, newComponent));
                            }
                            @Override
                            public void onInitProcess(DJISDKInitEvent djisdkInitEvent, int i) {
                            }
                            @Override
                            public void onDatabaseDownloadProgress(long l, long l1) {
                            }
                        });
                    }
                });
            }
        }
    protected BroadcastReceiver mReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            refreshSDKRelativeUI();
        }
    };
    private void refreshSDKRelativeUI() {
        BaseProduct mProduct = ReceiverApplication.getProductInstance();
        if (null != mProduct && mProduct.isConnected()) {
            Log.v(TAG, "刷新SDK: True");
            mButtonFlightTask.setEnabled(true);
            mButtonSettingRoute.setEnabled(true);
            mButtonFileManagement.setEnabled(true);
        } else {
            Log.v(TAG, "刷新SDK: False");
//            mButtonOpen.setEnabled(false);
//            mButtonSettingRoute.setEnabled(false);
//            mButtonFileManagement.setEnabled(false);
//            startSDKRegistration();
        }
    }
    protected long exitTime;   //记录第一次点击时的时间
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK
                && event.getAction() == KeyEvent.ACTION_DOWN) {
            if ((System.currentTimeMillis() - exitTime) > 2000) {
                showToast("再按一次退出程序");
                exitTime = System.currentTimeMillis();
            } else {
                RegistrationActivity.this.finish();
                System.exit(0);
            }
            return true;
        }
        return super.onKeyDown(keyCode, event);
    }
        private void loginAccount() {
            UserAccountManager.getInstance().logIntoDJIUserAccount(thisnew CommonCallbacks.CompletionCallbackWith<UserAccountState>() {
                @Override
                public void onSuccess(UserAccountState userAccountState) {
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            mButtonFlightTask.setEnabled(true);
                            mButtonSettingRoute.setEnabled(true);
                            mButtonFileManagement.setEnabled(true);
                        }
                    });
                }
                @Override
                public void onFailure(DJIError djiError) {
                }
            });
        }
}

上面的代码就要进行第一次注册登录了,当然你不需要自己去设计登录注册页面,大疆会调取自己的登录注册页面供你使用。


图片

安装提示注册登录即可。


上面的这些做完后,恭喜你!现在,您的移动应用程序和飞机可以在中国使用而没有任何问题。换句话说,您的应用程序现在可以看到飞机的视频流,并且飞行将不仅限于直径为100m和高度为30m的圆柱体区域。

3

飞行界面使用

虽然说可以正常飞行了,但是飞行需要设计飞行界面。那么创建一下飞行界面的UI及逻辑处理文件。逻辑处理文件中包含了获取飞机的实时姿态信息,代码中有注释内容,描述的内容就不多说了。

导入UX SDK依赖

上一节有说过集成部分,其中内容有导入UxSDk 的操作,这里再顺便提一下。再build.gradle文件中加入implementation "com.dji:dji-uxsdk:4.16"依赖,等待安装即可。

设计界面UI

创建MainActivity文件及activity_main.xml。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:custom="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/background_blue"
    android:id="@+id/root_view"
    tools:context=".ui.MainActivity">

    <!-- Widget to see first person view (FPV) -->
    <RelativeLayout
        android:id="@+id/fpv_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <dji.ux.widget.FPVWidget
            android:id="@+id/fpv_widget"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_centerInParent="true"
            custom:sourceCameraNameVisibility="false" />

    </RelativeLayout>
    <dji.ux.widget.FPVOverlayWidget
        android:id="@+id/fpv_overlay_widget"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginBottom="40dp"
        android:layout_toRightOf="@+id/TakeOffReturnPanel"
        android:layout_toLeftOf="@+id/CameraCapturePanel"
        android:layout_below="@+id/camera"
        tools:ignore="RtlHardcoded">

        <dji.ux.widget.RadarWidget
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"/>

    </RelativeLayout>
    <!--Take off and return home buttons on left -->
    <LinearLayout
        android:id="@+id/TakeOffReturnPanel"
        android:layout_width="40dp"
        android:layout_height="wrap_content"
        android:layout_marginLeft="12dp"
        android:layout_marginBottom="4dp"
        android:layout_marginTop="50dp"
        android:orientation="vertical"
        android:gravity="center">

        <ImageView
            android:id="@+id/img_show_back"
            android:layout_width="match_parent"
            android:layout_height="38dp"
            android:src="@mipmap/ic_back_36dp"
            android:layout_marginBottom="10dp"></ImageView>

        <dji.ux.widget.TakeOffWidget
            android:layout_width="40dp"
            android:layout_height="40dp"
            android:layout_marginBottom="5dp" />

        <dji.ux.widget.ReturnHomeWidget
            android:layout_width="40dp"
            android:layout_height="40dp"
            android:layout_marginTop="5dp"
            android:layout_marginBottom="5dp"/>

        <ImageView
            android:id="@+id/img_live"
            android:layout_width="35dp"
            android:layout_height="35dp"
            android:layout_marginTop="5dp"
            android:layout_marginBottom="5dp"
            android:src="@mipmap/ic_live_write_36dp"></ImageView>

    </LinearLayout>
    <FrameLayout
        android:layout_width="150dp"
        android:layout_height="100dp"
        android:id="@+id/secondary_video_view"
        android:layout_marginLeft="12dp"
        android:layout_marginBottom="7dp"
        android:layout_marginTop="50dp"
        android:layout_alignParentLeft="true"
        android:layout_below="@+id/TakeOffReturnPanel"
        android:background="@color/black">

        <dji.ux.widget.FPVWidget
            android:id="@+id/secondary_fpv_widget"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            custom:sourceCameraNameVisibility="false"
            custom:videoSource="secondary"/>

    </FrameLayout>
    <dji.ux.workflow.CompassCalibratingWorkFlow
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

    <dji.ux.workflow.CameraSensorCleaningWorkFlow
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

    <dji.ux.widget.RemainingFlightTimeWidget
        android:layout_alignParentTop="true"
        android:layout_marginTop="18dp"
        android:layout_width="match_parent"
        android:id="@+id/remaining_flight_time"
        android:background="@color/transparent"
        android:layout_height="20dp"/>

    <LinearLayout
        android:id="@+id/camera"
        android:layout_alignParentRight="true"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/signal"
        android:layout_marginTop="15dp"
        android:background="@color/dark_gray"
        android:orientation="horizontal">

        <dji.ux.widget.config.CameraConfigISOAndEIWidget
            android:layout_width="50dp"
            android:layout_height="25dp"/>

        <dji.ux.widget.config.CameraConfigShutterWidget
            android:layout_width="50dp"
            android:layout_height="25dp"/>

        <dji.ux.widget.config.CameraConfigApertureWidget
            android:layout_width="50dp"
            android:layout_height="25dp"/>

        <dji.ux.widget.config.CameraConfigEVWidget
            android:layout_width="50dp"
            android:layout_height="25dp"/>

        <dji.ux.widget.config.CameraConfigWBWidget
            android:layout_width="60dp"
            android:layout_height="25dp"/>

        <dji.ux.widget.config.CameraConfigStorageWidget
            android:layout_width="108dp"
            android:layout_height="25dp"/>

        <dji.ux.widget.config.CameraConfigSSDWidget
            android:layout_width="125dp"
            android:layout_height="25dp"/>

    </LinearLayout>
    <LinearLayout
        android:id="@+id/camera2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="5dp"
        android:layout_below="@id/camera"
        android:layout_toLeftOf="@+id/CameraCapturePanel"
        android:background="@color/dark_gray"
        android:orientation="horizontal">

        <dji.ux.widget.SpeakerWidget
            android:layout_width="35dp"
            android:layout_height="35dp"/>

        <dji.ux.widget.AutoExposureLockWidget
            android:layout_width="35dp"
            android:layout_height="35dp"/>

        <dji.ux.widget.FocusModeWidget
            android:layout_width="35dp"
            android:layout_height="35dp"/>

        <dji.ux.widget.FocusExposureSwitchWidget
            android:layout_width="35dp"
            android:layout_height="35dp"/>

        <dji.ux.widget.BeaconWidget
            android:layout_width="35dp"
            android:layout_height="35dp"/>

        <dji.ux.widget.SpotlightWidget
            android:layout_width="35dp"
            android:layout_height="35dp"/>

        <dji.ux.widget.AccessLockerWidget
            android:layout_width="35dp"
            android:layout_height="35dp"/>

    </LinearLayout>
    <dji.ux.widget.ManualFocusWidget
        android:layout_alignTop="@+id/camera2"
        android:layout_toLeftOf="@+id/camera2"
        android:layout_width="50dp"
        android:layout_height="210dp"
        tools:ignore="RtlHardcoded"/>

    <dji.ux.widget.MapWidget
        android:id="@+id/map_widget"
        android:layout_width="150dp"
        android:layout_height="100dp"
        android:layout_marginRight="12dp"
        android:layout_marginBottom="12dp"
        android:layout_alignParentRight="true"
        android:layout_alignParentBottom="true"/>

    <!-- Everything below this line will appear on top of the full-screen map widget -->
    <dji.ux.widget.controls.CameraControlsWidget
        android:id="@+id/CameraCapturePanel"
        android:layout_alignParentRight="true"
        android:layout_below="@id/camera"
        android:layout_width="50dp"
        android:layout_height="213dp"
        android:layout_marginTop="5dp"
        tools:ignore="RtlHardcoded"/>

    <!-- Widgets in top status bar -->
    <LinearLayout
        android:id="@+id/signal"
        android:layout_width="match_parent"
        android:layout_height="25dp"
        android:background="@color/dark_gray"
        android:orientation="horizontal">

        <dji.ux.widget.PreFlightStatusWidget
            android:layout_width="180dp"
            android:layout_height="25dp"/>

        <dji.ux.widget.FlightModeWidget
            android:layout_width="103dp"
            android:layout_height="22dp"/>

        <dji.ux.widget.GPSSignalWidget
            android:layout_width="44dp"
            android:layout_height="22dp"/>

        <dji.ux.widget.VisionWidget
            android:layout_width="22dp"
            android:layout_height="22dp"/>

        <dji.ux.widget.RemoteControlSignalWidget
            android:layout_width="38dp"
            android:layout_height="22dp"/>

        <dji.ux.widget.VideoSignalWidget
            android:layout_width="38dp"
            android:layout_height="22dp"/>

        <dji.ux.widget.WiFiSignalWidget
            android:layout_width="32dp"
            android:layout_height="25dp"/>

        <dji.ux.widget.BatteryWidget
            android:layout_width="96dp"
            android:layout_height="22dp"
            custom:excludeView="singleVoltage"/>

        <dji.ux.widget.ConnectionWidget
            android:layout_marginTop="3dp"
            android:layout_width="18dp"
            android:layout_height="18dp"/>

    </LinearLayout>
    <LinearLayout
        android:id="@+id/dashboard_widget"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:orientation="horizontal"
        android:padding="12dp">

        <dji.ux.widget.dashboard.DashboardWidget
            android:id="@+id/Compass"
            android:layout_width="405dp"
            android:layout_height="91dp"
            android:layout_marginRight="12dp"
            tools:ignore="RtlHardcoded" />

    </LinearLayout>
    <!-- Panels -->
    <dji.ux.widget.HistogramWidget
        android:layout_width="150dp"
        android:layout_height="75dp"
        android:layout_centerVertical="true"
        android:layout_toRightOf="@+id/TakeOffReturnPanel"
        tools:ignore="RtlHardcoded" />

    <dji.ux.panel.CameraSettingExposurePanel
        android:layout_width="180dp"
        android:layout_below="@id/camera"
        android:layout_toLeftOf="@+id/CameraCapturePanel"
        android:gravity="center"
        android:layout_height="263dp"
        android:visibility="gone"
        tools:ignore="RtlHardcoded"/>

    <dji.ux.panel.CameraSettingAdvancedPanel
        android:layout_width="180dp"
        android:layout_height="263dp"
        android:layout_below="@id/camera"
        android:layout_toLeftOf="@+id/CameraCapturePanel"
        android:gravity="center"
        android:visibility="gone"
        tools:ignore="RtlHardcoded"/>

    <dji.ux.panel.RTKStatusPanel
        android:id="@+id/rtk_panel"
        android:layout_width="500dp"
        android:layout_height="350dp"
        android:layout_below="@id/signal"
        android:gravity="center"
        android:layout_centerInParent="true"
        android:visibility="gone"/>

    <dji.ux.widget.ColorWaveformWidget
        android:layout_width="394dp"
        android:layout_height="300dp"
        android:layout_below="@+id/camera"
        android:gravity="center"
        android:layout_centerInParent="true"
        android:visibility="gone"/>

    <!-- Pre-flight checklist panel -->
    <dji.ux.panel.PreFlightCheckListPanel
        android:id="@+id/pre_flight_check_list"
        android:layout_width="400dp"
        android:layout_height="wrap_content"
        android:layout_below="@id/signal"
        custom:excludeItem="ESCStatus"
        android:visibility="gone"/>

    <dji.ux.panel.SpotlightPanel
        android:id="@+id/spotlight_panel"
        android:layout_width="300dp"
        android:layout_height="wrap_content"
        android:layout_below="@id/camera2"
        android:layout_alignRight="@+id/camera2"
        android:visibility="gone"
        android:gravity="center" />

    <dji.ux.panel.SpeakerPanel
        android:id="@+id/speaker_panel"
        android:layout_width="300dp"
        android:layout_height="match_parent"
        android:layout_alignParentLeft="true"
        android:layout_below="@+id/signal"
        android:visibility="gone"
        android:gravity="center" />

</RelativeLayout>
@Layout(R.layout.activity_main)
public class MainActivity extends BaseActivity implements View.OnClickListener {
    @BindView(R.id.img_live)
    ImageView mImageViewLive;
    private MapWidget mapWidget;
    private DJIMap aMap;
    private ViewGroup parentView;
    private FPVWidget fpvWidget;
    private FPVWidget secondaryFPVWidget;
    private RelativeLayout primaryVideoView;
    private FrameLayout secondaryVideoView;
    private boolean isMapMini = true;
    private String liveShowUrl = "";
    private int height;
    private int width;
    private int margin;
    private int deviceWidth;
    private int deviceHeight;
    private SharedPreUtils mSharedPreUtils;
    //unix时间戳
    private String dateStr = "";
    //飞行器管理器
    private FlightController controller;
    //经纬度
    private double lat = 0, lon = 0;
    //高度
    private float high = 0;
    //飞机的姿态
    private Attitude attitude;
    //俯仰角、滚转、偏航值
    private double pitch = 0, roll = 0, yaw = 0;
    //飞机的速度
    private float velocity_X = 0, velocity_Y = 0, velocity_Z = 0;
    //飞机/控制器电池管理器
    private Battery battery;
    //电池电量、温度
    private int power = 0;
    private float temperature = 0;
    //云台管理器
    private Gimbal gimbal;
    //云台的姿态
    private dji.common.gimbal.Attitude g_attitude;
    //俯仰角、滚转、偏航值
    private double g_pitch = 0, g_roll = 0, g_yaw = 0;
    private Camera camera;
    private List<Lens> lens = new ArrayList<>();
    private List<DJILatLng> djiList = new ArrayList<>();
    //手柄控制器
    private HandheldController handheldController;
    //手柄电量
    private int h_power = 0;
    private static List<DeviceInfo> list = new ArrayList<>();
    private static List<String> getList = new ArrayList<>();
    private MediaManager mMediaManager;
    private MediaManager.FileListState currentFileListState = MediaManager.FileListState.UNKNOWN;
    private List<MediaFile> arrayList = new ArrayList<>();
    private List<String> startList = new ArrayList<>();
    private List<String> endList = new ArrayList<>();
    private boolean isStartLive = false;
    private boolean isFlying = false;
    private boolean start = false;
    private BaseProduct mProduct;
    private String posName = "";
    //webSocket
    private JWebSocketClient client;
    private Map<String,String> params = new HashMap<>();
    Map<String,String> mapData = new HashMap<>();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        height = ToolKit.dip2px(this100);
        width = ToolKit.dip2px(this150);
        margin = ToolKit.dip2px(this12);
        WindowManager windowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
        final Display display = windowManager.getDefaultDisplay();
        Point outPoint = new Point();
        display.getRealSize(outPoint);
        deviceHeight = outPoint.y;
        deviceWidth = outPoint.x;
        parentView = (ViewGroup) findViewById(R.id.root_view);
        fpvWidget = findViewById(R.id.fpv_widget);
        fpvWidget.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                onViewClick(fpvWidget);
            }
        });
        primaryVideoView = (RelativeLayout) findViewById(R.id.fpv_container);
        secondaryVideoView = (FrameLayout) findViewById(R.id.secondary_video_view);
        secondaryFPVWidget = findViewById(R.id.secondary_fpv_widget);
        secondaryFPVWidget.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                swapVideoSource();
            }
        });
        if (VideoFeeder.getInstance() != null) {
            //If secondary video feed is already initialized, get video source
            updateSecondaryVideoVisibility(VideoFeeder.getInstance().getSecondaryVideoFeed().getVideoSource() != PhysicalSource.UNKNOWN);
            //If secondary video feed is not yet initialized, wait for active status
            VideoFeeder.getInstance().getSecondaryVideoFeed()
                    .addVideoActiveStatusListener(isActive ->
                            runOnUiThread(() -> updateSecondaryVideoVisibility(isActive)));
        }
        mSharedPreUtils = SharedPreUtils.getInStance(this);
        this.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
        mapWidget = findViewById(R.id.map_widget);
        mapWidget.setFlightPathColor(Color.parseColor("#2fa8e7"));
        mapWidget.setFlightPathWidth(15);
        mapWidget.setDirectionToHomeVisible(false);
        mapWidget.initAMap(new MapWidget.OnMapReadyListener() {
            @Override
            public void onMapReady(@NonNull DJIMap djiMap) {
                djiMap.setOnMapClickListener(new DJIMap.OnMapClickListener() {
                    @Override
                    public void onMapClick(DJILatLng latLng) {
                        onViewClick(mapWidget);
                    }
                });
                djiMap.getUiSettings().setZoomControlsEnabled(false);
            }
        });
        if (aMap == null) {
            aMap = mapWidget.getMap();
        }
        mapWidget.onCreate(savedInstanceState);
        mProduct = ReceiverApplication.getProductInstance();
        if (null != mProduct && mProduct.isConnected()) {
            flyInformation(mProduct);
            batteryInformation(mProduct);
            cameraInformation(mProduct);
            camera(mProduct);
        }
        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                Message msg = new Message();
                if (isFlying && !start) {
                    start = true;
                    
            
                }
                if (!isFlying && start) {
                    start = false;
              
                }
                if (isFlying && high >= 0) {
                    msg.what = 1;
                }
                mHandler.sendMessage(msg);
            }
        }, 200200);
    }
    Handler mHandler = new Handler() {
        @RequiresApi(api = Build.VERSION_CODES.O)
        @Override
        public void handleMessage(@NonNull Message msg) {
            switch (msg.what) {
                case 1:
                    Long time = System.currentTimeMillis();
//                    MyLog.d("时间:"+time);
                    RecordModule module = new RecordModule(String.valueOf(projectId), String.valueOf(planeId),
                            trajectoryId, time, String.valueOf(lon), String.valueOf(lat),
                            String.valueOf(high), String.valueOf(yaw), String.valueOf(pitch), String.valueOf(roll),
                            String.valueOf(""), String.valueOf(velocity_X), String.valueOf(velocity_Y),
                            String.valueOf(velocity_Z), String.valueOf(g_yaw), String.valueOf(g_roll), String.valueOf(g_pitch));
                    http.getHttp(INSERT_DATA, GsonUtil.GsonString(module));
                    break;
                case 2:
                    MyLog.d("飞机移动的数据:"+msg.obj.toString());
                    ControlModule control = GsonUtil.GsonToBean(msg.obj.toString(),ControlModule.class);
                    if (controller!=null&&isFlying){
                        if (control.getContent().isBack()){
                            controller.sendVirtualStickFlightControlData(new FlightControlData(-10,0,0,0),null);
                        }
                        if (control.getContent().isFront()){
                            controller.sendVirtualStickFlightControlData(new FlightControlData(10,0,0,0),null);
                        }
                        if (control.getContent().isDown()){
                            controller.sendVirtualStickFlightControlData(new FlightControlData(0,0,0,-4),null);
                        }
                        if (control.getContent().isUp()){
                            controller.sendVirtualStickFlightControlData(new FlightControlData(0,0,0,4),null);
                        }
                        if (control.getContent().isLeft()){
                            controller.sendVirtualStickFlightControlData(new FlightControlData(0,-10,0,0),null);
                        }
                        if (control.getContent().isRight()){
                            controller.sendVirtualStickFlightControlData(new FlightControlData(0,10,0,0),null);
                        }
                    }else {
                        MyLog.d("controller控制器为空");
                    }
                    break;
            }
        }
    };
    @Override
    public void initViews() {
        mMediaManager = ReceiverApplication.getCameraInstance().getMediaManager();
        getFileList("start");
    }
    @Override
    public void onComplete(String url, String jsonStr) {
        super.onComplete(url, jsonStr);
     
    }
    @Override
    public void initDatas() {
    }
    private void onViewClick(View view) {
        if (view == fpvWidget && !isMapMini) {
            resizeFPVWidget(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT, 00);
            reorderCameraCapturePanel();
            ResizeAnimation mapViewAnimation = new ResizeAnimation(mapWidget, deviceWidth, deviceHeight, width, height, margin);
            mapWidget.startAnimation(mapViewAnimation);
            isMapMini = true;
        } else if (view == mapWidget && isMapMini) {
            hidePanels();
            resizeFPVWidget(width, height, margin, 12);
            reorderCameraCapturePanel();
            ResizeAnimation mapViewAnimation = new ResizeAnimation(mapWidget, width, height, deviceWidth, deviceHeight, 0);
            mapWidget.startAnimation(mapViewAnimation);
            isMapMini = false;
        }
    }
    private void resizeFPVWidget(int width, int height, int margin, int fpvInsertPosition) {
        RelativeLayout.LayoutParams fpvParams = (RelativeLayout.LayoutParams) primaryVideoView.getLayoutParams();
        fpvParams.height = height;
        fpvParams.width = width;
        fpvParams.rightMargin = margin;
        fpvParams.bottomMargin = margin;
        if (isMapMini) {
            fpvParams.addRule(RelativeLayout.CENTER_IN_PARENT, 0);
            fpvParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT, RelativeLayout.TRUE);
            fpvParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, RelativeLayout.TRUE);
        } else {
            fpvParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT, 0);
            fpvParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, 0);
            fpvParams.addRule(RelativeLayout.CENTER_IN_PARENT, RelativeLayout.TRUE);
        }
        primaryVideoView.setLayoutParams(fpvParams);
        parentView.removeView(primaryVideoView);
        parentView.addView(primaryVideoView, fpvInsertPosition);
    }
    private void reorderCameraCapturePanel() {
        View cameraCapturePanel = findViewById(R.id.CameraCapturePanel);
        parentView.removeView(cameraCapturePanel);
        parentView.addView(cameraCapturePanel, isMapMini ? 9 : 13);
    }
    private void swapVideoSource() {
        if (secondaryFPVWidget.getVideoSource() == FPVWidget.VideoSource.SECONDARY) {
            fpvWidget.setVideoSource(FPVWidget.VideoSource.SECONDARY);
            secondaryFPVWidget.setVideoSource(FPVWidget.VideoSource.PRIMARY);
        } else {
            fpvWidget.setVideoSource(FPVWidget.VideoSource.PRIMARY);
            secondaryFPVWidget.setVideoSource(FPVWidget.VideoSource.SECONDARY);
        }
    }
    private void updateSecondaryVideoVisibility(boolean isActive) {
        if (isActive) {
            secondaryVideoView.setVisibility(View.VISIBLE);
        } else {
            secondaryVideoView.setVisibility(View.GONE);
        }
    }
    private void hidePanels() {
        //These panels appear based on keys from the drone itself.
        if (KeyManager.getInstance() != null) {
            KeyManager.getInstance().setValue(CameraKey.create(CameraKey.HISTOGRAM_ENABLED), falsenull);
            KeyManager.getInstance().setValue(CameraKey.create(CameraKey.COLOR_WAVEFORM_ENABLED), falsenull);
        }
        //These panels have buttons that toggle them, so call the methods to make sure the button state is correct.
        CameraControlsWidget controlsWidget = findViewById(R.id.CameraCapturePanel);
        controlsWidget.setAdvancedPanelVisibility(false);
        controlsWidget.setExposurePanelVisibility(false);
        //These panels don't have a button state, so we can just hide them.
        findViewById(R.id.pre_flight_check_list).setVisibility(View.GONE);
        findViewById(R.id.rtk_panel).setVisibility(View.GONE);
        findViewById(R.id.spotlight_panel).setVisibility(View.GONE);
        findViewById(R.id.speaker_panel).setVisibility(View.GONE);
    }
    @Override
    protected void onResume() {
        super.onResume();
        // Hide both the navigation bar and the status bar.
        View decorView = getWindow().getDecorView();
        decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                | View.SYSTEM_UI_FLAG_FULLSCREEN
                | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
        mapWidget.onResume();
        if (client == null) {
            MyLog.e("``````````````````````onResume");
//            initWebSocket();
        } else if (!client.isOpen()) {
            reconnectWs();//进入页面发现断开开启重连
        }
    }
    @Override
    protected void onStop() {
        super.onStop();
        MyLog.e("``````````````````````````````onStop");
    }
    @Override
    protected void onPause() {
        mapWidget.onPause();
        super.onPause();
    }
    @Override
    protected void onDestroy() {
        mapWidget.onDestroy();
        super.onDestroy();
        MyLog.e( "`````````````````````````onDestroy");
        closeConnect();
    }
    @Override
    protected void requestData() {
    }
    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        mapWidget.onSaveInstanceState(outState);
    }
    @Override
    public void onLowMemory() {
        super.onLowMemory();
        mapWidget.onLowMemory();
    }
    private class ResizeAnimation extends Animation {
        private View mView;
        private int mToHeight;
        private int mFromHeight;
        private int mToWidth;
        private int mFromWidth;
        private int mMargin;
        private ResizeAnimation(View v, int fromWidth, int fromHeight, int toWidth, int toHeight, int margin) {
            mToHeight = toHeight;
            mToWidth = toWidth;
            mFromHeight = fromHeight;
            mFromWidth = fromWidth;
            mView = v;
            mMargin = margin;
            setDuration(300);
        }
        @Override
        protected void applyTransformation(float interpolatedTime, Transformation t) {
            float height = (mToHeight - mFromHeight) * interpolatedTime + mFromHeight;
            float width = (mToWidth - mFromWidth) * interpolatedTime + mFromWidth;
            RelativeLayout.LayoutParams p = (RelativeLayout.LayoutParams) mView.getLayoutParams();
            p.height = (int) height;
            p.width = (int) width;
            p.rightMargin = mMargin;
            p.bottomMargin = mMargin;
            mView.requestLayout();
        }
    }
    //直播流推送
    @RequiresApi(api = Build.VERSION_CODES.O)
    @OnClick({R.id.img_live, R.id.img_show_back})
    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.img_live:
                params.clear();
                mapData.clear();
                if (!isStartLive) {
                    if (!TextUtils.isEmpty(mSharedPreUtils.getStringSharePre("rtmp_url"))) {
                        liveShowUrl = mSharedPreUtils.getStringSharePre("rtmp_url") + trajectoryId;
//                        LiveModule module = new LiveModule("liveStreamStateChanged","plane",planeId,true,trajectoryId+"");
                        MyLog.d("地址:"+liveShowUrl);
                        startLiveShow();
                        isStartLive = true;
                        showToast("开始推流");
                    } else {
                        showToast("请先进行系统设置(RTMP)。");
                    }
                } else {
                    stopLiveShow();
                    isStartLive = false;
                }
                break;
            case R.id.img_show_back:
//                controller = null;
                closeConnect();
                MainActivity.this.finish();
                break;
        }
    }
    private boolean isLiveStreamManagerOn() {
        if (DJISDKManager.getInstance().getLiveStreamManager() == null) {
            return false;
        }
        return true;
    }
    private void startLiveShow() {
        if (!isLiveStreamManagerOn()) {
            return;
        }
        if (DJISDKManager.getInstance().getLiveStreamManager().isStreaming()) {
            return;
        }
        new Thread() {
            @Override
            public void run() {
                DJISDKManager.getInstance().getLiveStreamManager().setLiveUrl(liveShowUrl);
                DJISDKManager.getInstance().getLiveStreamManager().setAudioStreamingEnabled(true);
                int result = DJISDKManager.getInstance().getLiveStreamManager().startStream();
                DJISDKManager.getInstance().getLiveStreamManager().setStartTime();
            }
        }.start();
    }
    private void stopLiveShow() {
        AlertDialog.Builder Builder = new AlertDialog.Builder(MainActivity.this);
        Builder.setTitle("提示");
        Builder.setMessage("是否结束推流?");
        Builder.setIcon(android.R.drawable.ic_dialog_alert);
        Builder.setPositiveButton("确定"new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                if (!isLiveStreamManagerOn()) {
                    return;
                }
                DJISDKManager.getInstance().getLiveStreamManager().stopStream();
                showToast("结束推流");
            }
        });
        Builder.setNegativeButton("取消"null);
        Builder.show();
    }
    //获取飞机信息、云台信息
    protected BroadcastReceiver mReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            BaseProduct mProduct = ReceiverApplication.getProductInstance();
            if (null != mProduct && mProduct.isConnected()) {
                flyInformation(mProduct);
                batteryInformation(mProduct);
                cameraInformation(mProduct);
                camera(mProduct);
//                MobileRemote(mProduct);
            }
        }
    };
//    private void MobileRemote(BaseProduct mProduct) {
//        if (null != mProduct && mProduct.isConnected()) {
//            mobileController = ((Aircraft) mProduct).getMobileRemoteController();
//        }
//    }
    //获取飞机信息
    private void flyInformation(BaseProduct mProduct) {
        if (null != mProduct && mProduct.isConnected()) {
            controller = ((Aircraft) mProduct).getFlightController();
        }
        if (controller != null) {
            controller.setStateCallback(new FlightControllerState.Callback() {
                @RequiresApi(api = Build.VERSION_CODES.O)
                @Override
                public void onUpdate(@NonNull FlightControllerState flightControllerState) {
                    //纬度、经度、高度、俯仰角、滚转、偏航值、速度
                    lat = flightControllerState.getAircraftLocation().getLatitude();
                    lon = flightControllerState.getAircraftLocation().getLongitude();
                    high = flightControllerState.getAircraftLocation().getAltitude();
                    attitude = flightControllerState.getAttitude();
                    pitch = attitude.pitch;
                    roll = attitude.roll;
                    yaw = attitude.yaw;
                    velocity_X = flightControllerState.getVelocityX();
                    velocity_Y = flightControllerState.getVelocityY();
                    velocity_Z = flightControllerState.getVelocityZ();
                    isFlying = flightControllerState.isFlying();
                    //                    MyLog.d("经度:" + lat + ",纬度:" + lon + ",高度:" + high + ",角度:" + pitch + ",速度:" + velocity_X + "," + velocity_Y + "," + velocity_Z);
                }
            });
            controller.setVirtualStickAdvancedModeEnabled(true);
            controller.setRollPitchCoordinateSystem(FlightCoordinateSystem.BODY);
            controller.setVerticalControlMode(VerticalControlMode.VELOCITY);
            controller.setRollPitchControlMode(RollPitchControlMode.VELOCITY);
            controller.setYawControlMode(YawControlMode.ANGULAR_VELOCITY);
//            controller.setTerrainFollowModeEnabled(false, new CommonCallbacks.CompletionCallback() {
//                @Override
//                public void onResult(DJIError djiError) {
//                    MyLog.d(djiError.getDescription());
//                }
//            });
//            controller.setTripodModeEnabled(false, new CommonCallbacks.CompletionCallback() {
//                @Override
//                public void onResult(DJIError djiError) {
//                    MyLog.d(djiError.getDescription());
//                }
//            });
//            controller.setFlightOrientationMode(FlightOrientationMode.AIRCRAFT_HEADING, new CommonCallbacks.CompletionCallback() {
//                @Override
//                public void onResult(DJIError djiError) {
//                    MyLog.d(djiError.getDescription());
//                    if (djiError==null){
//                        if (controller.isVirtualStickControlModeAvailable()){
//
//                        }else {
//                            MyLog.d("虚拟摇杆模式不可用");
//                        }
//                    }
//                }
//            });
        }
    }
    //电池信息
    private void batteryInformation(BaseProduct mProduct) {
        if (null != mProduct && mProduct.isConnected()) {
            battery = ((Aircraft) mProduct).getBattery();
        }
        if (battery != null) {
            battery.setStateCallback(new BatteryState.Callback() {
                @Override
                public void onUpdate(BatteryState batteryState) {
                    //电池电量
                    power = batteryState.getChargeRemainingInPercent();
                    //电池温度
                    temperature = batteryState.getTemperature();
                }
            });
        }
    }
    //云台信息
    private void cameraInformation(BaseProduct mProduct) {
        if (null != mProduct && mProduct.isConnected()) {
            gimbal = ((Aircraft) mProduct).getGimbal();
        }
        if (gimbal != null) {
            gimbal.setMode(GimbalMode.YAW_FOLLOW, null);
            gimbal.setStateCallback(new GimbalState.Callback() {
                @Override
                public void onUpdate(@NonNull GimbalState gimbalState) {
                    //俯仰角、滚转、偏航值
                    g_attitude = gimbalState.getAttitudeInDegrees();
                    g_pitch = g_attitude.getPitch();
                    g_roll = g_attitude.getRoll();
                    g_yaw = g_attitude.getYaw();
                }
            });
        }
    }
    private void camera(BaseProduct mProduct) {
        if (null != mProduct && mProduct.isConnected()) {
            camera = ((Aircraft) mProduct).getCamera();
        }
        if (camera != null) {
            //            camera.setVideoCaptionEnabled(true, new CommonCallbacks.CompletionCallback() {
            //                @Override
            //                public void onResult(DJIError djiError) {
            //                    MyLog.d("VideoCaptionEnabled"+djiError.toString());
            //                }
            //            });
            //            camera.setMediaFileCustomInformation(projectId +","+trajectoryId, new CommonCallbacks.CompletionCallback() {
            //                @Override
            //                public void onResult(DJIError djiError) {
            //                    MyLog.d("自定义信息:"+djiError.toString());
            //                }
            //            });
            camera.setSystemStateCallback(new SystemState.Callback() {
                @RequiresApi(api = Build.VERSION_CODES.O)
                @Override
                public void onUpdate(@NonNull SystemState systemState) {
                    if (systemState.getMode().equals(SettingsDefinitions.CameraMode.SHOOT_PHOTO)) {
                        if (systemState.isStoringPhoto()) {
                            dateStr = Long.toString(System.currentTimeMillis());
                            list.add(new DeviceInfo(dateStr, lat, lon, high, pitch, roll, yaw, velocity_X, velocity_Y, velocity_Z, g_yaw, g_roll, g_pitch));
                            CsvWriter.getInstance(",""UTF-8").writeDataToFile(list, FileUtil.checkDirPath(FLY_FILE_PATH + "/照片数据") + "/" + DateUtils.getCurrentDates() + ".csv");
                            list.clear();
                            return;
                        }
                    } else if (systemState.getMode().equals(SettingsDefinitions.CameraMode.RECORD_VIDEO)) {
                        if (systemState.isRecording()) {
                            try {
                                dateStr = Long.toString(System.currentTimeMillis());
                                list.add(new DeviceInfo(dateStr, lat, lon, high, pitch, roll, yaw, velocity_X, velocity_Y, velocity_Z, g_yaw, g_roll, g_pitch));
                                getList.add(dateStr);
                                Thread.sleep(100);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        } else {
                            if (list.size() > 1) {
                                posName = DateUtils.getCurrentDates() + ".csv";
                                CsvWriter.getInstance(",""UTF-8").writeDataToFile(list, FileUtil.checkDirPath(FLY_FILE_PATH + "/视频数据") + "/" + posName);
                                list.clear();
                                runOnUiThread(new Runnable() {
                                    @Override
                                    public void run() {
                                        getFileList("end");
                                    }
                                });
                            }
                        }
                    }
                }
            });
        }
    }
    //遥控器信息
    private void handheldInforamation(BaseProduct mProduct) {
        if (null != mProduct && mProduct.isConnected()) {
            handheldController = ((HandHeld) mProduct).getHandHeldController();
        }
        if (handheldController != null) {
            handheldController.setPowerModeCallback(new PowerMode.Callback() {
                @Override
                public void onUpdate(PowerMode powerMode) {
                    switch (powerMode) {
                        case ON:
                            Battery battery = ((HandHeld) mProduct).getBattery();
                            battery.setStateCallback(new BatteryState.Callback() {
                                @Override
                                public void onUpdate(BatteryState batteryState) {
                                    h_power = batteryState.getChargeRemainingInPercent();
                                }
                            });
                            break;
                    }
                }
            });
        }
    }
   
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK
                && event.getAction() == KeyEvent.ACTION_DOWN) {
//                        closeConnect();
            MainActivity.this.finish();
        }
        return super.onKeyDown(keyCode, event);
    }
}

完成后界面如下所示:

图片


上面的工作完成后就可以在无人且宽阔的地方进行无人机飞行了。

4

多媒体资源的操作

多媒体文件操作,主要为多媒体文件的获取、查看、删除、下载的操作 同样创建多媒体功能文件FileManagementActivity及activity_file_management.xml

activity_file_management.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:custom="http://schemas.android.com/apk/res-auto"
    tools:context=".ui.FileManagementActivity"
    android:orientation="vertical"
    android:background="@drawable/shape_corner_eight">

    <include layout="@layout/activity_toolbar"
        android:id="@+id/layout_file"></include>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="horizontal">

        <LinearLayout
            android:layout_width="250dp"
            android:layout_height="match_parent"
            android:orientation="vertical"
            android:layout_marginLeft="15dp"
            android:layout_marginRight="15dp">

            <RadioGroup
                android:id="@+id/rg_file_management"
                android:layout_width="match_parent"
                android:layout_height="40dp"
                android:orientation="horizontal"
                android:background="#2B3141"
                android:gravity="center">

                <RadioButton
                    android:id="@+id/rb_file_all"
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="1"
                    android:button="@null"
                    android:checked="true"
                    android:gravity="center"
                    android:text="全部"
                    android:textColor="@drawable/nav_item_color_selector"
                    android:textSize="18sp"
                    tools:ignore="TouchTargetSizeCheck"></RadioButton>

                <RadioButton
                    android:id="@+id/rb_file_photo"
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="1"
                    android:button="@null"
                    android:gravity="center"
                    android:text="照片"
                    android:textColor="@drawable/nav_item_color_selector"
                    android:textSize="18sp"
                    tools:ignore="TouchTargetSizeCheck"></RadioButton>

                <RadioButton
                    android:id="@+id/rb_file_video"
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="1"
                    android:button="@null"
                    android:gravity="center"
                    android:text="视频"
                    android:textColor="@drawable/nav_item_color_selector"
                    android:textSize="18sp"
                    tools:ignore="TouchTargetSizeCheck"></RadioButton>

            </RadioGroup>
            <androidx.recyclerview.widget.RecyclerView
                android:id="@+id/rv_file_management"
                android:layout_width="match_parent"
                android:layout_height="0dp"
                android:layout_weight="1"
                android:layout_marginTop="10dp"></androidx.recyclerview.widget.RecyclerView>

        </LinearLayout>
        <RelativeLayout
            android:layout_width="0dp"
            android:layout_weight="2"
            android:layout_height="match_parent">

            <RelativeLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent">

                <dji.ux.widget.FPVWidget
                    android:id="@+id/FPVWidget"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:layout_centerInParent="true"
                    custom:sourceCameraNameVisibility="false" />

            </RelativeLayout>
            <ImageView
                android:id="@+id/img_show"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:scaleType="fitXY"
                android:visibility="invisible"></ImageView>

            <LinearLayout
                android:id="@+id/ll_video_btn"
                android:layout_width="match_parent"
                android:layout_height="50dp"
                android:orientation="horizontal"
                android:gravity="center"
                android:layout_marginBottom="15dp"
                android:layout_alignParentBottom="true"
                android:visibility="gone">

                <ImageView
                    android:id="@+id/img_video_pause"
                    android:layout_width="35dp"
                    android:layout_height="35dp"
                    android:src="@drawable/background_stop_selector"></ImageView>

                <ImageView
                    android:id="@+id/img_video_play"
                    android:layout_width="45dp"
                    android:layout_height="45dp"
                    android:layout_marginLeft="20dp"
                    android:src="@drawable/background_palyer_selector"></ImageView>

                <ImageView
                    android:id="@+id/img_video_stop"
                    android:layout_width="35dp"
                    android:layout_height="35dp"
                    android:layout_marginLeft="20dp"
                    android:src="@mipmap/ic_reset_36dp"></ImageView>

            </LinearLayout>
        </RelativeLayout>
    </LinearLayout>
</LinearLayout>

FileManagementActivity

@Layout(R.layout.activity_file_management)
public class FileManagementActivity extends BaseActivity implements View.OnClickListener {
    private static final String TAG = FileManagementActivity.class.getName();
    @BindView(R.id.layout_file)
    View mViewLayoutToolbar;
    @BindView(R.id.tv_toolbar_title)
    TextView mTextViewToolbarTitle;
    @BindView(R.id.ll_file)
    LinearLayout mLinearLayout;
    @BindView(R.id.rg_file_management)
    RadioGroup mRadioGroup;
    @BindView(R.id.rv_file_management)
    RecyclerView mRecyclerView;
    @BindView(R.id.img_show)
    ImageView mImageView;
    @BindView(R.id.ll_video_btn)
    LinearLayout mLinearLayoutVideo;
    @BindView(R.id.img_video_play)
    ImageView mImageViewVideoPlay;
    @BindView(R.id.img_video_pause)
    ImageView mImageViewVideoPause;
    private FileListAdapter mListAdapter;
    private List<MediaFile> List = new ArrayList<MediaFile>();
    private List<MediaFile> mediaFileList = new ArrayList<MediaFile>();
    private MediaManager mMediaManager;
    private MediaManager.FileListState currentFileListState = MediaManager.FileListState.UNKNOWN;
    private MediaManager.VideoPlaybackState state;
    private ProgressDialog mLoadingDialog;
    private ProgressDialog mDownloadDialog;
    private FetchMediaTaskScheduler scheduler;
    private int lastClickViewIndex = -1;
    private int currentProgress = -1;
    private String SavePath = "";
    private View lastClickView;
    private boolean isResume = false;
    private SFTPUtils sftp;
    private SettingsDefinitions.StorageLocation storageLocation;
    @Override
    public void initViews() {
        mLinearLayout.setVisibility(View.VISIBLE);
        mTextViewToolbarTitle.setText("文件管理");
        mImageViewVideoPlay.setEnabled(true);
        mImageViewVideoPause.setEnabled(false);
        mRadioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(RadioGroup group, int checkedId) {
                List.clear();
                mediaFileList.clear();
                switch (checkedId) {
                    case R.id.rb_file_all:
                        getFileList(0);
                        mListAdapter.notifyDataSetChanged();
                        break;
                    case R.id.rb_file_photo:
                        getFileList(1);
                        mListAdapter.notifyDataSetChanged();
                        break;
                    case R.id.rb_file_video:
                        getFileList(2);
                        mListAdapter.notifyDataSetChanged();
                        break;
                }
            }
        });
        LinearLayoutManager layoutManager = new LinearLayoutManager(FileManagementActivity.this, RecyclerView.VERTICAL, false);
        mRecyclerView.setLayoutManager(layoutManager);
        //Init FileListAdapter
        mListAdapter = new FileListAdapter();
        mRecyclerView.setAdapter(mListAdapter);
        //Init Loading Dialog
        mLoadingDialog = new ProgressDialog(FileManagementActivity.this);
        mLoadingDialog.setMessage("请等待...");
        mLoadingDialog.setCanceledOnTouchOutside(false);
        mLoadingDialog.setCancelable(false);
        //Init Download Dialog
        mDownloadDialog = new ProgressDialog(FileManagementActivity.this);
        mDownloadDialog.setTitle("下载中...");
        mDownloadDialog.setIcon(android.R.drawable.ic_dialog_info);
        mDownloadDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
        mDownloadDialog.setCanceledOnTouchOutside(false);
        mDownloadDialog.setCancelable(true);
        mDownloadDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
            @Override
            public void onCancel(DialogInterface dialog) {
                if (mMediaManager != null) {
                    mMediaManager.exitMediaDownloading();
                }
            }
        });
        sftp = new SFTPUtils("49.4.79.249","uav","uavHHch@YREC.cn");
        ReceiverApplication.getAircraftInstance().getCamera().setStorageStateCallBack(new StorageState.Callback() {
            @Override
            public void onUpdate(@NonNull @NotNull StorageState storageState) {
                if(storageState.isInserted()) {
                    storageLocation = SettingsDefinitions.StorageLocation.SDCARD;
                    ReceiverApplication.getAircraftInstance().getCamera().setStorageLocation(SettingsDefinitions.StorageLocation.SDCARD, new CommonCallbacks.CompletionCallback() {
                        @Override
                        public void onResult(DJIError djiError) {
                        }
                    });
                } else {
                    storageLocation = SettingsDefinitions.StorageLocation.INTERNAL_STORAGE;
                    ReceiverApplication.getAircraftInstance().getCamera().setStorageLocation(SettingsDefinitions.StorageLocation.INTERNAL_STORAGE, new CommonCallbacks.CompletionCallback() {
                        @Override
                        public void onResult(DJIError djiError) {
                        }
                    });
                }
            }
        });
    }
    @Override
    public void initDatas() {
    }
    @Override
    protected void requestData() {
    }
    @Override
    public void onComplete(String url, String jsonStr) {
        super.onComplete(url, jsonStr);
        switch (url){
            case POST_VIDEO_INFO:
                break;
            default:
                getVideoJson(jsonStr);
                break;
        }
    }
    private void getVideoJson(String jsonStr) {
        VideoModule module = GsonUtil.GsonToBean(jsonStr,VideoModule.class);
        if (module.getCode() == 200 && module.getRows().size() == 1){
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    UpdateFileModule fileModule = new UpdateFileModule(module.getRows().get(0).getId(),"/mnt/uavFtpFolder/"+module.getRows().get(0).getFileName());
                    http.getHttp(POST_VIDEO_INFO,"PUT",GsonUtil.GsonString(fileModule));
                }
            });
        }
    }
    @Override
    protected void onResume() {
        super.onResume();
        initMediaManager();
    }
    @Override
    protected void onPause() {
        super.onPause();
    }
    @Override
    protected void onStop() {
        super.onStop();
    }
    @Override
    protected void onDestroy() {
        lastClickView = null;
        if (mMediaManager != null) {
            mMediaManager.stop(null);
            mMediaManager.removeFileListStateCallback(this.updateFileListStateListener);
            mMediaManager.exitMediaDownloading();
            if (scheduler != null) {
                scheduler.removeAllTasks();
            }
        }
        if (isMavicAir2() || isM300()) {
            if (ReceiverApplication.getCameraInstance() != null) {
                ReceiverApplication.getCameraInstance().exitPlayback(djiError -> {
                    if (djiError != null) {
                        ReceiverApplication.getCameraInstance().setFlatMode(SettingsDefinitions.FlatCameraMode.PHOTO_SINGLE, djiError1 -> {
                            if (djiError1 != null) {
                                showToasts("设置单张拍照模式失败. " + djiError1.getDescription());
                            }
                        });
                    }
                });
            } else {
                ReceiverApplication.getCameraInstance().setMode(SettingsDefinitions.CameraMode.SHOOT_PHOTO, djiError -> {
                    if (djiError != null) {
                        showToasts("设置拍照模式失败. " + djiError.getDescription());
                    }
                });
            }
        }
        if (mediaFileList != null) {
            //            List.clear();
            mediaFileList.clear();
        }
        super.onDestroy();
    }
    private void showProgressDialogs() {
        runOnUiThread(new Runnable() {
            public void run() {
                if (mLoadingDialog != null) {
                    mLoadingDialog.show();
                }
            }
        });
    }
    private void hideProgressDialog() {
        runOnUiThread(new Runnable() {
            public void run() {
                if (null != mLoadingDialog && mLoadingDialog.isShowing()) {
                    mLoadingDialog.dismiss();
                }
            }
        });
    }
    private void ShowDownloadProgressDialog() {
        if (mDownloadDialog != null) {
            runOnUiThread(new Runnable() {
                public void run() {
                    mDownloadDialog.incrementProgressBy(-mDownloadDialog.getProgress());
                    mDownloadDialog.show();
                }
            });
        }
    }
    private void HideDownloadProgressDialog() {
        if (null != mDownloadDialog && mDownloadDialog.isShowing()) {
            runOnUiThread(new Runnable() {
                public void run() {
                    mDownloadDialog.dismiss();
                }
            });
        }
    }
    private void initMediaManager() {
        if (ReceiverApplication.getProductInstance() == null) {
            mediaFileList.clear();
            mListAdapter.notifyDataSetChanged();
            DJILog.e(TAG, "设备已断开");
            return;
        } else {
            if (null != ReceiverApplication.getCameraInstance() && ReceiverApplication.getCameraInstance().isMediaDownloadModeSupported()) {
                mMediaManager = ReceiverApplication.getCameraInstance().getMediaManager();
                if (null != mMediaManager) {
                    mMediaManager.addUpdateFileListStateListener(this.updateFileListStateListener);
                    mMediaManager.addMediaUpdatedVideoPlaybackStateListener(new MediaManager.VideoPlaybackStateListener() {
                        @Override
                        public void onUpdate(MediaManager.VideoPlaybackState videoPlaybackState) {
                            state = videoPlaybackState;
                            if (videoPlaybackState.getPlaybackStatus() == MediaFile.VideoPlaybackStatus.STOPPED){
                                runOnUiThread(new Runnable() {
                                    @Override
                                    public void run() {
//                                        mImageViewVideoPlay.setEnabled(true);
//                                        mImageViewVideoPause.setEnabled(false);
                                    }
                                });
                            }
                        }
                    });
                    if (isMavicAir2() || isM300()) {
                        ReceiverApplication.getCameraInstance().enterPlayback(djiError -> {
                            if (djiError == null) {
                                DJILog.e(TAG, "设置cameraMode成功");
                                showProgressDialogs();
                                getFileList(0);
                            } else {
                                showToasts("设置cameraMode失败");
                            }
                        });
                    } else {
                        ReceiverApplication.getCameraInstance().setMode(SettingsDefinitions.CameraMode.MEDIA_DOWNLOAD, error -> {
                            if (error == null) {
                                DJILog.e(TAG, "设置cameraMode成功");
                                showProgressDialogs();
                                getFileList(0);
                            } else {
                                showToasts("设置cameraMode失败");
                            }
                        });
                    }
                    if (mMediaManager.isVideoPlaybackSupported()) {
                        DJILog.e(TAG, "摄像头支持视频播放!");
                    } else {
                        showToasts("摄像头不支持视频播放!");
                    }
                    scheduler = mMediaManager.getScheduler();
                }
            } else if (null != ReceiverApplication.getCameraInstance()
                    && !ReceiverApplication.getCameraInstance().isMediaDownloadModeSupported()) {
                showToasts("不支持媒体下载模式");
            }
        }
        return;
    }
    private void getFileList(int index) {
        mMediaManager = ReceiverApplication.getCameraInstance().getMediaManager();
        if (mMediaManager != null) {
            if ((currentFileListState == MediaManager.FileListState.SYNCING) || (currentFileListState == MediaManager.FileListState.DELETING)) {
                DJILog.e(TAG, "媒体管理器正忙.");
            } else {
                mMediaManager.refreshFileListOfStorageLocation(storageLocation, djiError -> {
//                mMediaManager.refreshFileListOfStorageLocation(SettingsDefinitions.StorageLocation.SDCARD, djiError -> {
                    if (null == djiError) {
                        hideProgressDialog();
                        //Reset data
                        if (currentFileListState != MediaManager.FileListState.INCOMPLETE) {
                            List.clear();
                            mediaFileList.clear();
                            lastClickViewIndex = -1;
                        }
//                        List = mMediaManager.getSDCardFileListSnapshot();
//                        List = mMediaManager.getInternalStorageFileListSnapshot();
                        if (storageLocation == SettingsDefinitions.StorageLocation.SDCARD) {
                            List = mMediaManager.getSDCardFileListSnapshot();
                        } else {
                            List = mMediaManager.getInternalStorageFileListSnapshot();
                        }
                        switch (index) {
                            case 0:
                                for (int i = 0; i < List.size(); i++) {
                                    mediaFileList.add(List.get(i));
                                }
                                break;
                            case 1:
                                for (int i = 0; i < List.size(); i++) {
                                    if (List.get(i).getMediaType() == MediaFile.MediaType.JPEG) {
                                        mediaFileList.add(List.get(i));
                                        MyLog.d("图片名称:"+List.get(i).getFileName());
                                    }
                                }
                                break;
                            case 2:
                                for (int i = 0; i < List.size(); i++) {
                                    if ((List.get(i).getMediaType() == MediaFile.MediaType.MOV) || (List.get(i).getMediaType() == MediaFile.MediaType.MP4)) {
                                        mediaFileList.add(List.get(i));
                                        MyLog.d("视频名称:"+List.get(i).getFileName());
                                    }
                                }
                                break;
                        }
                        if (mediaFileList != null) {
                            Collections.sort(mediaFileList, (lhs, rhs) -> {
                                if (lhs.getTimeCreated() < rhs.getTimeCreated()) {
                                    return 1;
                                } else if (lhs.getTimeCreated() > rhs.getTimeCreated()) {
                                    return -1;
                                }
                                return 0;
                            });
                        }
                        scheduler.resume(error -> {
                            if (error == null) {
                                getThumbnails();
                            }
                        });
                    } else {
                        hideProgressDialog();
                        showToasts("获取媒体文件列表失败:" + djiError.getDescription());
                    }
                });
            }
        }
    }
    private void getThumbnails() {
        if (mediaFileList.size() <= 0) {
            showToasts("没有用于下载缩略图的文件信息");
            return;
        }
        for (int i = 0; i < mediaFileList.size(); i++) {
            getThumbnailByIndex(i);
        }
    }
    private FetchMediaTask.Callback taskCallback = new FetchMediaTask.Callback() {
        @Override
        public void onUpdate(MediaFile file, FetchMediaTaskContent option, DJIError error) {
            if (null == error) {
                if (option == FetchMediaTaskContent.PREVIEW) {
                    runOnUiThread(new Runnable() {
                        public void run() {
                            mListAdapter.notifyDataSetChanged();
                        }
                    });
                }
                if (option == FetchMediaTaskContent.THUMBNAIL) {
                    runOnUiThread(new Runnable() {
                        public void run() {
                            mListAdapter.notifyDataSetChanged();
                        }
                    });
                }
            } else {
                DJILog.e(TAG, "获取媒体任务失败" + error.getDescription());
            }
        }
    };
    private void getThumbnailByIndex(final int index) {
        FetchMediaTask task = new FetchMediaTask(mediaFileList.get(index), FetchMediaTaskContent.THUMBNAIL, taskCallback);
        scheduler.moveTaskToEnd(task);
    }
    class ItemHolder extends RecyclerView.ViewHolder {
        ImageView thumbnail_img;
        TextView file_name;
        TextView file_type;
        TextView file_size;
        TextView file_time;
        public ItemHolder(View itemView) {
            super(itemView);
            this.thumbnail_img = (ImageView) itemView.findViewById(R.id.filethumbnail);
            this.file_name = (TextView) itemView.findViewById(R.id.filename);
            this.file_type = (TextView) itemView.findViewById(R.id.filetype);
            this.file_size = (TextView) itemView.findViewById(R.id.fileSize);
            this.file_time = (TextView) itemView.findViewById(R.id.filetime);
        }
    }
    private class FileListAdapter extends RecyclerView.Adapter<ItemHolder{
        @Override
        public int getItemCount() {
            if (mediaFileList != null) {
                return mediaFileList.size();
            }
            return 0;
        }
        @Override
        public ItemHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.media_info_item, parent, false);
            return new ItemHolder(view);
        }
        @Override
        public void onBindViewHolder(ItemHolder mItemHolder, final int index) {
            final MediaFile mediaFile = mediaFileList.get(index);
            if (mediaFile != null) {
                if (mediaFile.getMediaType() != MediaFile.MediaType.MOV && mediaFile.getMediaType() != MediaFile.MediaType.MP4) {
                    mItemHolder.file_time.setVisibility(View.GONE);
                } else {
                    mItemHolder.file_time.setVisibility(View.VISIBLE);
                    mItemHolder.file_time.setText(mediaFile.getDurationInSeconds() + " s");
                }
                mItemHolder.file_name.setText(mediaFile.getFileName());
                mItemHolder.file_type.setText(mediaFile.getMediaType().name());
                mItemHolder.file_size.setText(String.format("%.2f", (double) (mediaFile.getFileSize() / 1048576d)) + " MB");
                mItemHolder.thumbnail_img.setImageBitmap(mediaFile.getThumbnail());
                mItemHolder.thumbnail_img.setTag(mediaFile);
                mItemHolder.itemView.setTag(index);
                if (lastClickViewIndex == index) {
                    mItemHolder.itemView.setSelected(true);
                } else {
                    mItemHolder.itemView.setSelected(false);
                }
                mItemHolder.itemView.setOnClickListener(itemViewOnClickListener);
            }
        }
    }
    private View.OnClickListener itemViewOnClickListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            lastClickViewIndex = (int) (v.getTag());
            if (lastClickView != null && lastClickView != v) {
                lastClickView.setSelected(false);
            }
            v.setSelected(true);
            lastClickView = v;
            MediaFile selectedMedia = mediaFileList.get(lastClickViewIndex);
            if (selectedMedia != null && mMediaManager != null) {
                addMediaTask(selectedMedia);
            }
        }
    };
    private void addMediaTask(final MediaFile mediaFile) {
        final FetchMediaTaskScheduler scheduler = mMediaManager.getScheduler();
        final FetchMediaTask task =
                new FetchMediaTask(mediaFile, FetchMediaTaskContent.PREVIEW, new FetchMediaTask.Callback() {
                    @Override
                    public void onUpdate(final MediaFile mediaFile, FetchMediaTaskContent fetchMediaTaskContent, DJIError error) {
                        if (null == error) {
                            if (mediaFile.getPreview() != null) {
                                runOnUiThread(new Runnable() {
                                    @Override
                                    public void run() {
                                        final Bitmap previewBitmap = mediaFile.getPreview();
                                        mImageView.setVisibility(View.VISIBLE);
                                        mImageView.setImageBitmap(previewBitmap);
                                        if (mediaFile.getMediaType() == MediaFile.MediaType.MP4){
                                            mLinearLayoutVideo.setVisibility(View.VISIBLE);
                                        }else {
                                            mLinearLayoutVideo.setVisibility(View.GONE);
                                        }
                                    }
                                });
                            } else {
                                showToasts("没有图像bitmap!");
                            }
                        } else {
                            showToasts("查找图像内容失败: " + error.getDescription());
                        }
                    }
                });
        scheduler.resume(error -> {
            if (error == null) {
                scheduler.moveTaskToNext(task);
            } else {
                showToasts("恢复计划程序失败: " + error.getDescription());
            }
        });
    }
    //Listeners
    private MediaManager.FileListStateListener updateFileListStateListener = state -> currentFileListState = state;
    private void deleteFileByIndex(final int index) {
        ArrayList<MediaFile> fileToDelete = new ArrayList<MediaFile>();
        if (mediaFileList.size() > index) {
            fileToDelete.add(mediaFileList.get(index));
            mMediaManager.deleteFiles(fileToDelete, new CommonCallbacks.CompletionCallbackWithTwoParam<List<MediaFile>, DJICameraError>() {
                @Override
                public void onSuccess(List<MediaFile> x, DJICameraError y) {
                    DJILog.e(TAG, "Delete file success");
                    runOnUiThread(new Runnable() {
                        public void run() {
                            mediaFileList.remove(index);
                            //Reset select view
                            lastClickViewIndex = -1;
                            lastClickView = null;
                            //Update recyclerView
                            mListAdapter.notifyDataSetChanged();
                        }
                    });
                }
                @Override
                public void onFailure(DJIError error) {
                    showToasts("删除失败");
                }
            });
        }
    }
    private void downloadFileByIndex(final int index) {
        if ((mediaFileList.get(index).getMediaType() == MediaFile.MediaType.PANORAMA)
                || (mediaFileList.get(index).getMediaType() == MediaFile.MediaType.SHALLOW_FOCUS)) {
            return;
        }
        if ((mediaFileList.get(index).getMediaType() == MediaFile.MediaType.MOV) || (mediaFileList.get(index).getMediaType() == MediaFile.MediaType.MP4)) {
            SavePath = MyStatic.FLY_FILE_VIDEO;
        } else if (mediaFileList.get(index).getMediaType() == MediaFile.MediaType.JPEG) {
            SavePath = MyStatic.FLY_FILE_PHOTO;
        }
        File destDir = new File(FileUtil.checkDirPath(SavePath));
        mediaFileList.get(index).fetchFileData(destDir,nullnew DownloadListener<String>() {
            @Override
            public void onFailure(DJIError error) {
                HideDownloadProgressDialog();
                showToasts("下载失败" + error.getDescription());
                currentProgress = -1;
            }
            @Override
            public void onProgress(long total, long current) {
            }
            @Override
            public void onRateUpdate(long total, long current, long persize) {
                int tmpProgress = (int) (1.0 * current / total * 100);
                if (tmpProgress != currentProgress) {
                    mDownloadDialog.setProgress(tmpProgress);
                    currentProgress = tmpProgress;
                }
            }
            @Override
            public void onRealtimeDataUpdate(byte[] bytes, long l, boolean b) {
            }
            @Override
            public void onStart() {
                currentProgress = -1;
                ShowDownloadProgressDialog();
            }
            @Override
            public void onSuccess(String filePath) {
                HideDownloadProgressDialog();
                showToasts("下载成功" + ":" + filePath);
                currentProgress = -1;
            }
        });
//        mediaFileList.get(index).fetchFileByteData(0, new DownloadListener<String>() {
//            @Override
//            public void onStart() {
//                currentProgress = -1;
//                ShowDownloadProgressDialog();
//            }
//
//            @Override
//            public void onRateUpdate(long total, long current, long persize) {
//                int tmpProgress = (int) (1.0 * current / total * 100);
//                if (tmpProgress != currentProgress) {
//                    mDownloadDialog.setProgress(tmpProgress);
//                    currentProgress = tmpProgress;
//                }
//            }
//
//            @Override
//            public void onRealtimeDataUpdate(byte[] bytes, long l, boolean b) {
//                byteToFile(bytes, FileUtil.checkDirPath(SavePath)+mediaFileList.get(index).getFileName());
//            }
//
//            @Override
//            public void onProgress(long l, long l1) {
//
//            }
//
//            @Override
//            public void onSuccess(String s) {
//                HideDownloadProgressDialog();
//                showToasts("下载成功" + ":" + s);
//                currentProgress = -1;
//            }
//
//            @Override
//            public void onFailure(DJIError djiError) {
//
//            }
//        });
    }
    public static void byteToFile(byte[] bytes, String path)
    
{
        try
        {
            // 根据绝对路径初始化文件
            File localFile = new File(path);
            if (!localFile.exists())
            {
                localFile.createNewFile();
            }
            // 输出流
            OutputStream os = new FileOutputStream(localFile);
            os.write(bytes);
            os.close();
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }
    private void playVideo() {
        mImageView.setVisibility(View.INVISIBLE);
        MediaFile selectedMediaFile = mediaFileList.get(lastClickViewIndex);
        if ((selectedMediaFile.getMediaType() == MediaFile.MediaType.MOV) || (selectedMediaFile.getMediaType() == MediaFile.MediaType.MP4)) {
            mMediaManager.playVideoMediaFile(selectedMediaFile, error -> {
                if (null != error) {
                    showToasts("播放失败 " + error.getDescription());
                } else {
                    DJILog.e(TAG, "播放成功");
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            mImageViewVideoPlay.setEnabled(false);
                            mImageViewVideoPause.setEnabled(true);
                        }
                    });
                }
            });
        }
    }
    @OnClick({R.id.img_back, R.id.img_delete, R.id.img_download, R.id.img_upload, R.id.img_video_play,
            R.id.img_video_pause, R.id.img_video_stop})
    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.img_back:
                FileManagementActivity.this.finish();
                break;
            case R.id.img_delete:
                if (lastClickViewIndex >= 0) {
                    deleteFileByIndex(lastClickViewIndex);
                } else {
                    showToasts("请先选择文件。");
                }
                break;
            case R.id.img_download:
                if (lastClickViewIndex >= 0) {
                    downloadFileByIndex(lastClickViewIndex);
                } else {
                    showToasts("请先选择文件。");
                }
                break;
            case R.id.img_upload:
                if (lastClickViewIndex >= 0) {
                    uploadFileByIndex(lastClickViewIndex);
                } else {
                    showToasts("请先选择文件。");
                }
                break;
            case R.id.img_video_play:
                if (state.getPlaybackStatus() == MediaFile.VideoPlaybackStatus.STOPPED){
                    playVideo();
                }else if (state.getPlaybackStatus() == MediaFile.VideoPlaybackStatus.PAUSED){
                    mMediaManager.resume(error -> {
                        if (null != error) {
                            showToasts("继续播放失败:" + error.getDescription());
                        } else {
                            DJILog.e(TAG, "继续播放成功");
                            runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    mImageViewVideoPlay.setEnabled(false);
                                    mImageViewVideoPause.setEnabled(true);
                                }
                            });
                        }
                    });
                }
                break;
            case R.id.img_video_pause:
                mMediaManager.pause(error -> {
                    if (null != error) {
                        showToasts("暂停播放失败:" + error.getDescription());
                    } else {
                        DJILog.e(TAG, "暂停播放成功");
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                mImageViewVideoPlay.setEnabled(true);
                                mImageViewVideoPause.setEnabled(false);
                            }
                        });
                    }
                });
                break;
            case R.id.img_video_stop:
                mMediaManager.stop(error -> {
                    if (null != error) {
                        showToasts("停止播放失败:" + error.getDescription());
                    } else {
                        DJILog.e(TAG, "停止播放成功");
                    }
                });
                break;
        }
    }
    private void uploadFileByIndex(int index) {
        if ((mediaFileList.get(index).getMediaType() == MediaFile.MediaType.MOV) || (mediaFileList.get(index).getMediaType() == MediaFile.MediaType.MP4)) {
            showProgressDialog("正在上传");
            new Thread(new Runnable() {
                        @Override
                        public void run() {
                            boolean isConnect = sftp.connect().isConnected();
                            if (isConnect){
                                boolean isUpdate = sftp.uploadFile("/mnt/uavFtpFolder/",mediaFileList.get(index).getFileName(), FLY_FILE_VIDEO, mediaFileList.get(index).getFileName());
                                if (isUpdate){
                                    runOnUiThread(new Runnable() {
                                        @Override
                                        public void run() {
                                            removeProgressDialog();
                                            http.getHttp(GET_VIDEO_INFO+"?fileName="+mediaFileList.get(index).getFileName(),"GET");
                                        }
                                    });
                                    sftp.disconnect();
                                }else {
                                    runOnUiThread(new Runnable() {
                                        @Override
                                        public void run() {
                                            showErrorTip("上传失败");
                                            removeProgressDialog();
                                        }
                                    });
                                }
                            }else {
                                runOnUiThread(new Runnable() {
                                    @Override
                                    public void run() {
                                        showErrorTip("服务器连接失败");
                                        removeProgressDialog();
                                    }
                                });
                            }
                        }
                    }).start();
        }else {
            showToasts("当前仅支持视频上传,请选择视频文件!");
        }
    }
    private boolean isMavicAir2() {
        BaseProduct baseProduct = ReceiverApplication.getProductInstance();
        if (baseProduct != null) {
            return baseProduct.getModel() == Model.MAVIC_AIR_2;
        }
        return false;
    }
    private boolean isM300() {
        BaseProduct baseProduct = ReceiverApplication.getProductInstance();
        if (baseProduct != null) {
            return baseProduct.getModel() == Model.MATRICE_300_RTK;
        }
        return false;
    }
}

运行后界面如下:

图片



*博客内容为网友个人发布,仅代表博主个人观点,如有侵权请联系工作人员删除。

参与讨论
登录后参与讨论
推荐文章
最近访客