电子产业一站式赋能平台

PCB联盟网

搜索
查看: 68|回复: 0
收起左侧

基于Mobile SDK V4版固件开发大疆无人机手机端遥控器(2)

[复制链接]

752

主题

752

帖子

6398

积分

高级会员

Rank: 5Rank: 5

积分
6398
发表于 2023-6-8 12:00:00 | 显示全部楼层 |阅读模式

n1njpvfuqfl64023083205.gif

n1njpvfuqfl64023083205.gif
( o  \9 X' \: \# K
点击上方蓝色字体,关注我们& f! u" C7 N  |  C) t- L2 N# w. [

8 G5 b1 U% S! x! j上一篇文章(基于Mobile SDK V4版固件开发大疆无人机手机端遥控器(1))因为时间原因介绍了一部分内容,如果已经完成上一篇内容的操作就可以进行下面功能方面的制作了。自己开发的APP功能不是很多,但是已经将大疆无人机的常用功能进行了结合,同大家一起进行学习~/ {" }6 U0 U1 x6 H$ k" G2 t
1% v0 g9 G/ C% X* o
应用程序激活与绑定- p4 j6 w9 C4 V
如果在中国使用DJI飞行器固件,则需要使用该用户的DJI帐户激活控制DJI飞行器的移动应用程序。这将确保大疆能根据飞行器的地理位置和用户个人资料,为飞行器配置正确的地理空间信息和飞行功能集。激活系统的主要是:
! Q5 \6 ?/ b! @  C
  • 中国用户必须在每三个月至少登录一次DJI帐户以遍激活应用程序。
  • 激活信息将存储在应用程序中,直到用户注销为止。
  • 登录DJI帐号需要连接互联网。
  • 在中国境外,SDK会自动激活应用程序,无需用户登录。
  • 另外,中国用户必须将飞机绑定到DJI官方app中的用户帐户。这仅需要一次。如果未激活应用程序,未绑定飞机(如果需要)或使用旧版SDK(+ ?! K2 _+ }8 e7 l% g9 ~

    8 ]5 J# _1 G% Y$ S% l& ]; q2( g+ q  @: d' d1 n
    为应用程序创建UI编写MApplication、ReceiverApplication和RegistrationActivity文件(此处粘贴部分代码)。
    2 M- e6 v' r% `2 P' H* Vpublic class MApplication extends MultiDexApplication {
    8 Y+ s; r. \9 ?# @7 N6 ^    private ReceiverApplication receiverApplication;
    8 }2 Y6 V3 `8 f) ^* S    @Override# O4 W! q, i( Q# t* H/ W# A  [
        protected void attachBaseContext(Context paramContext) {3 i% z% `' I# }, D* y) o! a# i
            super.attachBaseContext(paramContext);% H  p& r1 ~7 D7 e& J0 B
            CrashHandler.getInstance().init(this);7 L# U, R& d* m: ~. H3 Y
            Helper.install(MApplication.this);
    1 H( x4 N+ m3 ?8 j* |( x! a2 V3 ?        if (receiverApplication == null) {
    $ {! O% F, O% ^+ A3 {            receiverApplication = new ReceiverApplication();
    # I; g- C, N- U; v$ ]$ \/ K            receiverApplication.setContext(this);. u3 L/ W+ S9 e/ q. X! a: u
            }  @2 ^" q3 ^* @6 e
        }" Y2 v' J8 w8 l4 o+ |/ ^
        @Override
    2 O9 {& P8 s4 t2 D# F    public void onCreate() {8 x# E) _$ `6 h# j
            super.onCreate();
      T& H" u8 I3 O! J* R& ^6 F) E' P( q        receiverApplication.onCreate();
    + t$ r- ^  E5 l+ z4 G5 F2 o9 t    }( n% ]2 X* {% A7 V" f  E4 x2 S4 q4 Z! {
    }
    ! O% }" V# H, t7 |上面的代码实现了绑定当前APP,将后续需要用到的类函数封装到ReceiverApplication 中,在ReceiverApplication 中也能够进行账户登录的操作。# A- \, I' @' X: Y1 G
    public class ReceiverApplication extends MultiDexApplication {; a' S- r/ L; P3 ~; z
        public static final String FLAG_CONNECTION_CHANGE = "activation_connection_change";9 j0 m4 R3 e2 y: ^) D8 X
        private static BaseProduct mProduct;
    $ J* Q/ M7 s1 [8 M3 U$ d    public Handler mHandler;7 i3 h$ p# }/ M+ K5 \% H. G
        private Application instance;/ ~4 B' d; L' T
        public void setContext(Application application) {
    8 b8 v# M% A, G' B8 d- f        instance = application;
    / H: c6 a5 s7 u- V- p    }
    ) X1 x' d8 s' S: P; b$ T    @Override, l: _, l$ l+ e3 {; d' m' a
        protected void attachBaseContext(Context base) {
    7 ?; F; G$ M! N4 n$ F2 ~        super.attachBaseContext(base);
    3 Q4 {9 k9 H* Q1 A        Helper.install(this);
      I7 C: S: s7 M, k! K+ g3 F+ W7 y- h    }
    ; Y2 Z" P2 q. O8 v. O6 [    @Override
    " I0 h! [; S8 `4 E+ c/ @* @# ~    public Context getApplicationContext() {
    5 |$ e4 f% T' {8 U        return instance;1 n. j2 x5 b& a  T
        }5 x) F4 u3 X. [4 K$ d2 C3 z
        public ReceiverApplication() {! A, f5 S6 P5 e- f" b; @( H. Z5 r; `
        }
    , q0 ~' r, a& r( {+ W) [. L    /**
    : V- U; S2 c' O     * This function is used to get the instance of DJIBaseProduct.
    ' p% m& u$ N, _# W; P; A+ F1 `     * If no product is connected, it returns null.8 Q% a: L6 X. z9 c
         */
    4 d  ^* W- B# S* w; j. ]: O) n    public static synchronized BaseProduct getProductInstance() {
    5 I" Q7 J2 q' S' L        if (null == mProduct) {" A% e: `/ l5 x7 ?
                mProduct = DJISDKManager.getInstance().getProduct();- J# b7 n$ T) }5 J
            }" y( J# ^" F8 K+ j1 d3 a
            return mProduct;5 m$ ^# j' _. c, z/ Y9 f
        }( H( A/ V0 Y) h2 Q3 B
        public static synchronized Aircraft getAircraftInstance() {
    6 ?$ X! X) B) x+ e& Y  ^$ ?        if (!isAircraftConnected()) return null;- }+ p  \7 \2 y2 r: ~- {
            return (Aircraft) getProductInstance();: H, s2 m2 g# J$ g; B. d
        }
    4 Z7 m$ `7 G) @    public static synchronized Camera getCameraInstance() {3 R# A% P/ Q$ B0 a" Y& }' x9 N
            if (getProductInstance() == null) return null;
    " A' W' ?8 b) h8 R) A        Camera camera = null;
    / h! s+ I! f4 e3 |$ q; Y! Y/ O        if (getProductInstance() instanceof Aircraft){" ^, a! q+ z; q6 I! c0 E
                camera = ((Aircraft) getProductInstance()).getCamera();" ?0 u3 M4 B6 @; \
            } else if (getProductInstance() instanceof HandHeld) {
    " m" v) i0 Z% G: e            camera = ((HandHeld) getProductInstance()).getCamera();# O2 h% B, H1 I4 Q7 ~9 m+ k
            }
      m" G/ U  F. j  M4 m        return camera;$ R& Y. B$ a; O; Z- M2 ]6 s& {
        }3 k* R6 M& D- y8 q1 k0 V" I
        public static boolean isAircraftConnected() {1 k5 U* c5 x- s- h7 o, V, C" r* W
            return getProductInstance() != null && getProductInstance() instanceof Aircraft;
    - f- ~% z( y1 e( G    }
    : ]7 s+ B3 C# d  d4 o, n1 F    public static boolean isHandHeldConnected() {$ [: X1 ]) L* u: D' `
            return getProductInstance() != null && getProductInstance() instanceof HandHeld;
    0 r; r( n8 r3 e) r$ ^    }1 m) R7 @( J2 u# r- W8 n9 J
        public static boolean isProductModuleAvailable() {
    2 X/ Q( n  r* X" ^% N        return (null != ReceiverApplication.getProductInstance());
    ) W7 y& g) ^8 a" A    }1 B/ l) ?6 ~" _/ H) l' q1 S* l! I
        public static boolean isCameraModuleAvailable() {
    " R# [' O" S" X, y/ ?+ w3 y4 U+ [        return isProductModuleAvailable() &&
    4 N9 e, T& |# G0 D( D6 o                (null != ReceiverApplication.getProductInstance().getCamera());; O/ q1 L1 _' _7 W9 n. I
        }8 q2 h9 {8 d. e2 @+ U; ?
        public static boolean isPlaybackAvailable() {
    2 i3 Q& [+ b' C3 y' `2 S6 ]        return isCameraModuleAvailable() &&8 ~9 U" F7 j/ ]8 Y! t
                    (null != ReceiverApplication.getProductInstance().getCamera().getPlaybackManager());' L+ i" J# ~. `0 Y7 {
        }
    2 J9 l5 _( ]0 y# [& P4 V    @Override
    * j( M7 b7 s5 A    public void onCreate() {* F( {  N- G7 S) x! L
            super.onCreate();5 Z$ d0 Q2 R* [/ K
            mHandler = new Handler(Looper.getMainLooper());
    & C; _$ ?3 C- g( c& V        /**  L  L( G" u7 Z5 a+ J
             * When starting SDK services, an instance of interface DJISDKManager.DJISDKManagerCallback will be used to listen to
    " D) s8 i$ ?" |' u1 H9 a         * the SDK Registration result and the product changing.7 ?7 j: @) l1 @, n/ p3 g
             */
    & i5 _8 N9 u+ r; l        //Listens to the SDK registration result
    - ]$ [! ?8 g( Z& X' [7 z        DJISDKManager.SDKManagerCallback mDJISDKManagerCallback = new DJISDKManager.SDKManagerCallback() {
    0 {* X# Y# A2 _' d            //Listens to the SDK registration result
    ' o5 F, u( @% ?% W            @Override( l# |6 Q/ p; c6 g$ e7 ?/ d, X
                public void onRegister(DJIError error) {
    ' Z  p1 M8 S2 N# E- t                if (error == DJISDKError.REGISTRATION_SUCCESS) {& x4 L5 w5 h; e" Y, W
                        Handler handler = new Handler(Looper.getMainLooper());+ `: b5 m6 @9 L
                        handler.post(new Runnable() {
    , L8 o/ P$ x5 W7 L" W                        @Override# K" j- h5 `- ]! }; `
                            public void run() {6 s+ B' Q7 a1 f4 _
    //                            ToastUtils.showToast(getApplicationContext(), "注册成功");
    6 B% C  v: Q$ L7 D6 J3 [) L$ M//                            Toast.makeText(getApplicationContext(), "注册成功", Toast.LENGTH_LONG).show();* e+ H5 f$ L3 l- a) B. A
    //                            loginAccount();
    # Q1 i1 h7 s. `2 i$ M3 G1 R1 e                        }
    5 Y2 [9 z4 L9 O8 T" n' f) T; s) p                    });
    % L' |& l# W9 q# r                    DJISDKManager.getInstance().startConnectionToProduct();7 D4 l& U$ r( r
                    } else {. ~1 u0 _3 c5 p8 r! X4 J
                        Handler handler = new Handler(Looper.getMainLooper());
    8 F4 j8 V' y4 |                    handler.post(new Runnable() {( D2 p2 l1 C: N. }
                            @Override
    2 V* b3 U7 z; q5 ^8 u0 g                        public void run() {
    5 |9 f: W  B' D- ]1 {9 i6 I//                            ToastUtils.showToast(getApplicationContext(), "注册sdk失败,请检查网络是否可用");
    * f* N  P  b: V5 O5 q, H% F//                            Toast.makeText(getApplicationContext(), "注册sdk失败,请检查网络是否可用", Toast.LENGTH_LONG).show();6 Z9 X- ^2 H) E4 D8 Q( i
                            }
    ! J' A+ M/ t- H7 H                    });
    # X- P: M7 o" X0 l9 n) H                }: p* b" Q2 f& A! A  Y
                    Log.e("TAG", error.toString());$ l. f' q4 K! Q( q/ y( ]4 o' h  }8 @
                }9 q7 q( g+ [9 m$ r  Z, ^
                @Override4 b: ]6 p" {, K) n) ?
                public void onProductDisconnect() {/ G0 t/ N) \( j" t1 ?9 h& V, l! I* m
                    Log.d("TAG", "设备连接");
    4 S+ `* o1 L1 P1 b                notifyStatusChange();
    # T: b4 E6 ]6 d            }6 |8 s. p; l: n
                @Override
    $ @; h* P. I! z- T            public void onProductConnect(BaseProduct baseProduct) {* g& j: C% M7 L. {
                    Log.d("TAG", String.format("新设备连接:%s", baseProduct));1 ^1 G$ N* Y0 s8 e1 E. N
                    notifyStatusChange();# O3 @* ]" c% m8 p: D, F9 ?
                }
    ) {6 M" {. V9 A& T9 g            @Override
    * R# p+ a. t; F" Y% Z            public void onProductChanged(BaseProduct baseProduct) {
    0 j1 [0 H/ O8 }! J/ s" D' O            }& \$ h: Y+ R( m+ E( T
                @Override
    # `* r- i6 ?! p. L9 t7 E7 n" |% n            public void onComponentChange(BaseProduct.ComponentKey componentKey, BaseComponent oldComponent,' w: t% r- _9 j5 m2 l  v1 z8 Z: M
                                              BaseComponent newComponent) {
    # h, v: }( v* p8 l% h) [                if (newComponent != null) {! ~6 y& b" b# G4 N! p' ]  t
                        newComponent.setComponentListener(new BaseComponent.ComponentListener() {
    ( N2 s2 @& @& e9 f4 O                        @Override
    ( I# c& ~* Y% ]/ z6 j3 u# Q                        public void onConnectivityChange(boolean isConnected) {
    3 \2 s, K! K: w$ V6 @                            Log.d("TAG", "设备连接已更改: " + isConnected);
    / ~/ R, z* u( E% e7 L$ a: w! U1 V                            notifyStatusChange();
    $ |+ g6 u; s* {3 O: {3 n  o3 H                        }# j% j9 X9 ~; l6 T- x% Q
                        });
    ) S* \, ~5 O) v                }7 Z, r7 B* l- j9 N
                    Log.d("TAG",
    . T' a% G# D0 X1 m# e+ \0 R" B3 s; ]                        String.format("设备改变 key:%s, 旧设备:%s, 新设备:%s",  Y, Z1 p& J1 d, {6 U+ J
                                    componentKey,
    ( M  v1 m, o* b$ r                                oldComponent,' K- ^# m; j8 Y$ n+ k
                                    newComponent));
    : L( M6 H/ m  d            }! T) Z; E+ q! i4 B3 r
                @Override/ b3 i6 t! m8 ?( X, O; a
                public void onInitProcess(DJISDKInitEvent djisdkInitEvent, int i) {
    2 J: M& Q# ?: c+ P; u: r            }1 b+ ?( y# `- X$ {- u) b6 H
                @Override
    : z( P; v8 |- I& v) C) Z            public void onDatabaseDownloadProgress(long l, long l1) {
    3 R0 Z$ D8 I7 `; T6 M5 c            }% \: b, r. g% S
            };# l: }9 w9 H; Z% F" F, ]
            //Check the permissions before registering the application for android system 6.0 above.) S8 |/ V2 q; L% y& e- d$ r5 X
            int permissionCheck = ContextCompat.checkSelfPermission(getApplicationContext(), android.Manifest.permission.WRITE_EXTERNAL_STORAGE);' K) F: \) v( @. W( x$ }
            int permissionCheck2 = ContextCompat.checkSelfPermission(getApplicationContext(), android.Manifest.permission.READ_PHONE_STATE);; [9 F; p' s! m+ S/ ]' ?9 ~, B
            if (Build.VERSION.SDK_INT 0 && permissionCheck2 == 0)) {2 L: l; N# x3 U
                //This is used to start SDK services and initiate SDK.
    3 V7 M7 j  x' ]            DJISDKManager.getInstance().registerApp(getApplicationContext(), mDJISDKManagerCallback);7 u) u3 u1 a9 O( O* K
    //            ToastUtils.showToast(getApplicationContext(), "正在注册,请等待...");
    ; r/ U! [! p  o//            Toast.makeText(getApplicationContext(), "正在注册,请等待...", Toast.LENGTH_LONG).show();
    ! z1 A/ T+ q# @) }6 e' g        } else {
      b& x# X# O' B5 {//            ToastUtils.showToast(getApplicationContext(), "请检查是否授予了权限");: P& L! s! y) t8 \8 I6 B# I
    //            Toast.makeText(getApplicationContext(), "请检查是否授予了权限。", Toast.LENGTH_LONG).show();
    5 M' S" p- k- e0 X8 v% R" E1 m        }& f8 K4 J' C% s8 O9 T2 W) v4 ^, f
        }  t/ Z% a5 H& S$ h  [8 [
        private void notifyStatusChange() {1 s. y* T  Q0 [" O/ a- |
            mHandler.removeCallbacks(updateRunnable);9 S! S7 O+ J1 o7 c3 P
            mHandler.postDelayed(updateRunnable, 500);
    5 ~3 m, ?. c0 o! ^- e9 N: N+ v    }& S' D+ I3 S) ^/ q: t7 k$ C
        private Runnable updateRunnable = new Runnable() {
    $ F/ [5 V, I" p0 `: Z        @Override9 P1 P* `; j" X) D
            public void run() {
    / u0 R3 s; Y6 n6 V            Intent intent = new Intent(FLAG_CONNECTION_CHANGE);
    2 x, K! K2 p/ s2 R# z' x) O6 e            getApplicationContext().sendBroadcast(intent);
    9 x; R0 y8 w- p3 g" {" ^' l        }. Q0 U( B1 n# O( q( I) S1 \
        };8 i: I3 g7 {; d, I# n4 m9 ^
    }
    3 n& ?" n$ l2 e6 Q4 M上面的代码是对BaseProduct、Aircraft和Camera类进行实例化,在后续使用中不用再去进行重复的实例化工作,减少内存的消耗。
    : R  `3 A) i) I/ n5 {+ ^@layout(R.layout.activity_registration)
    9 P( s0 N8 e( Kpublic class RegistrationActivity extends BaseActivity implements View.OnClickListener{* A1 s. h* {/ K; }$ s, x2 N
        private static final String TAG = RegistrationActivity.class.getName();
    " `4 w/ ]9 d1 H$ V/ Z    private AtomicBoolean isRegistrationInProgress = new AtomicBoolean(false);
    / Z! h) t" y4 V; S' K5 W    private static final String[] permissions = new String[]{
    7 G' _9 U. x& O            Manifest.permission.BLUETOOTH,
    ) j& A  ^" z% K7 W* W            Manifest.permission.BLUETOOTH_ADMIN,
    4 R2 P1 d3 y8 U3 P$ k+ z            Manifest.permission.VIBRATE,
    , |0 y4 h+ B9 [; ^            Manifest.permission.INTERNET,
    : [4 L" ]  u3 i. P8 a) ~2 B2 y            Manifest.permission.ACCESS_WIFI_STATE,
    $ h! F$ Z  Z, g1 }            Manifest.permission.ACCESS_COARSE_LOCATION,9 t& y, S+ J5 e+ b! }
                Manifest.permission.ACCESS_NETWORK_STATE,/ `: Z& H, a/ z4 z
                Manifest.permission.ACCESS_FINE_LOCATION,0 ^9 Z' g1 w# f1 \
                Manifest.permission.CHANGE_WIFI_STATE,2 m2 m1 Q+ W2 S+ }
                Manifest.permission.RECORD_AUDIO,
    6 i5 Q, r9 ?; G1 F            Manifest.permission.WRITE_EXTERNAL_STORAGE,
    , t5 I. K  d/ \            Manifest.permission.READ_EXTERNAL_STORAGE,
    + Q( J' }+ s/ k4 e. u            Manifest.permission.READ_PHONE_STATE,9 ]* Y) `& E" L+ X( D
        };
    9 ]  G% j* V. s6 W) b
    ( u9 P$ u* b' ~0 s% V& |    @Override
    * I; }  Q1 @8 v- T    public void initViews() {5 t. K, B# f. J/ J- Y) T- ^  ~
            isPermission();
    8 m% Z/ @9 T+ W( U6 D        IntentFilter filter = new IntentFilter();
    2 e8 i0 H2 P1 T2 u3 D# u0 |        filter.addAction(ReceiverApplication.FLAG_CONNECTION_CHANGE);- {. x' M0 ^5 v& `+ S
            registerReceiver(mReceiver, filter);$ _2 b+ p7 s- e
        }) u5 F* A, g7 \, Z9 `- ?* R
        @Override: C4 S/ ~& N! V8 ^0 K, v
        public void initDatas() {& w/ U* s# W  m
            startSDKRegistration();
    3 u7 t$ q) }- [    }  x: p( B' J! g% h/ C- m
        @Override; M2 Q% W& E; y/ Z1 H( ]
        protected void requestData() {
    " v4 S8 c) m% ^" y8 R# }        
    ' C# p2 r. ]) s+ F4 ]2 i+ C    }
    & a; K% n- N9 F) I2 J% Y$ r# P: s1 _( Y
        @Override
    7 _& k1 u5 l7 r    protected void onResume() {: i1 U& H0 ?* Y8 ~
            super.onResume();
    : W+ k  p! _4 L. q6 r2 |8 u) A    }
    * I* i: r5 e! s, u" y- f; q5 m8 H; z" e- T/ Q, [  u
        private void isPermission() {2 ?, {# ~- x3 l$ M& e% B7 W  b
            requestRunTimePermission(permissions, new IPermission() {' _, M' r( f% ]9 S1 g  h
                @Override$ ~4 |; r8 C" Q; A
                public void onGranted() {
    / m+ y" m% o& i            }
    5 b6 L. o4 y% K4 a  j/ y  ~/ A4 j            @Override
    , ]3 _- P# j9 K& A. U            public void onDenied(List deniedPermissions) {
    # z) Z9 A- E& D6 {" z            }
    ) S8 }- H* W6 r& W! y. d) e: ]        });
    ) d. ]+ i! }/ }, ^    }4 H  i2 T0 @+ o. a
      
    # @4 H) h3 y5 D; h& P    //无人机首次注册
    : S% M. W- ~7 i' u5 S/ M% D" c        private void startSDKRegistration() {
    . `. D+ c. G+ `* Z1 P/ [            if (isRegistrationInProgress.compareAndSet(false, true)) {1 N+ w) e/ o1 s# v
                    AsyncTask.execute(new Runnable() {7 p9 O- p/ Z/ P; ], p! F  g& x, D
                        @Override
    ; l% _. K' v3 E+ y/ M6 L6 z                    public void run() {4 l7 i  g+ `! ?, d+ s9 n  y
    //                      showToasts("注册中,请等待...");
      Q9 I' p* `5 u# n' H+ h                        DJISDKManager.getInstance().registerApp(getApplicationContext(), new DJISDKManager.SDKManagerCallback() {! U0 Z2 v9 W- ?" W/ v
                                @Override
    7 o3 o  A8 y% N/ V- X# Q. P" N" _                            public void onRegister(DJIError djiError) {0 q5 o/ f7 ~  d! F# o3 h( }; h
                                    if (djiError == DJISDKError.REGISTRATION_SUCCESS) {
    4 {6 J  z$ D! N' c. G                                    DJILog.e("App 注册", DJISDKError.REGISTRATION_SUCCESS.getDescription());2 q4 O) b# W; r7 q& R
                                        DJISDKManager.getInstance().startConnectionToProduct();
    " K* Y3 C4 V2 ^    //                                showToasts("注册成功");+ W) I6 W# z# J* n
                                        loginAccount();5 H) o" C- T( J, Z& h) N
                                    } else {
    ' g. u. @+ g; Z; k1 [1 i                                    showToasts("注册sdk失败,请检查网络是否可用");. V. z+ q/ T) d5 v8 F0 q
                                    }
    ( P7 Y% \5 B, W                                Log.v(TAG, djiError.getDescription());
    / e0 _8 f' U1 g- d                            }
    , l2 a8 K' c2 h$ ?& l5 X+ Z/ m! h                            @Override' M1 ?$ w# S+ u( I0 W
                                public void onProductDisconnect() {* \8 G/ N& g1 ?8 c4 P4 \; M% M
                                    Log.d(TAG, "产品断开连接");
    2 F" M1 B9 _, v+ ^7 b! J0 y  h    //                            showToasts("产品断开连接");
    0 s0 U) ^& t/ N! s" B9 E                            }4 o" N, U( Q/ S' P; S( l$ X
                                @Override
    5 `6 W- E  f/ r8 d8 j2 s                            public void onProductConnect(BaseProduct baseProduct) {+ i5 T* H8 J* Y
                                    Log.d(TAG, String.format("新产品连接:%s", baseProduct));/ d) G. Q6 g2 P- u: U' j4 x
        //                            showToasts("产品连接");, l: E" k4 D+ _
                                }  v0 _1 u& O! R/ v7 e
                                @Override
    7 [$ r8 I9 }, D% j/ Y2 @6 O6 v$ W                            public void onProductChanged(BaseProduct baseProduct) {0 G- A: s0 f- T6 `. V$ @2 K
                                }2 S+ ?: C4 s# X. Y! J. q0 ?( e
                                @Override( h* S' J" `5 G3 h
                                public void onComponentChange(BaseProduct.ComponentKey componentKey, BaseComponent oldComponent,$ p- s# V. b) y$ J: t0 c* G& k$ D' I
                                                              BaseComponent newComponent) {
    ) N' E1 c' I3 `$ |1 C, i2 J) \* {                                if (newComponent != null) {
    ; C3 V- W) \) Y1 j                                    newComponent.setComponentListener(new BaseComponent.ComponentListener() {
    . l; Q# K/ }( p- E! F) M                                        @Override9 X) K( W2 f+ B1 V' [/ _
                                            public void onConnectivityChange(boolean isConnected) {  ~4 ]2 V" ?8 p+ c- o
                                                Log.d(TAG, "组件连接已更改: " + isConnected);% D  h, X" J, X5 M+ ~! }0 E3 z
                                            }! X, g9 g( \& ^; J- ?; j' K( ~$ X1 |
                                        });) w6 N4 n; f0 D7 i- E: d
                                    }
    $ ]' n$ ~% k3 p5 z1 h, k: c                                Log.d(TAG, String.format("改变设备Key:%s, " + "旧设备:%s, " + "新设备:%s",# B* o& Q7 h& i, T
                                            componentKey, oldComponent, newComponent));
    ! ~4 J  L. Y, G0 Z                            }
    ! G8 p9 g# b" p& y; q8 e                            @Override2 Q! q: ^) @& \8 b1 q7 l6 i
                                public void onInitProcess(DJISDKInitEvent djisdkInitEvent, int i) {
    7 @' ^, j8 y& B6 ]% K2 t8 Y                            }
    7 h) M7 @5 S4 D: n/ Q! M! y                            @Override
    0 l9 I. P4 d1 `  h                            public void onDatabaseDownloadProgress(long l, long l1) {5 v' P1 F1 ^  d7 G1 l
                                }/ F4 M! `. L" T: g6 ?
                            });
    ) j+ ~- m9 @" G+ N  A                    }$ r+ ]( q0 Q4 I, Z2 a9 C
                    });
    ) g7 _  X( ]  `) [            }
    # ~) }0 w& H; I$ a& W: c0 s1 U        }
      T! U' q( B5 Q. N; R/ M5 e9 p8 w    protected BroadcastReceiver mReceiver = new BroadcastReceiver() {
    1 C% W2 g) i7 o        @Override0 g+ z/ m6 R2 i  i& ?
            public void onReceive(Context context, Intent intent) {% z, c5 }8 C9 K( {9 E
                refreshSDKRelativeUI();
    % f- p6 R* L/ Z( d6 r# n        }
    " r) ]  i' Y8 l# K    };
    4 ~, {# f/ k& a0 v/ s    private void refreshSDKRelativeUI() {/ [3 U' m* ~& w0 Q
            BaseProduct mProduct = ReceiverApplication.getProductInstance();$ r! K, ^' E9 {1 _) A9 R) g
            if (null != mProduct && mProduct.isConnected()) {
    " b) T! C: {+ H- X8 \            Log.v(TAG, "刷新SDK: True");
    ! [% T9 v8 D- F" Q            mButtonFlightTask.setEnabled(true);% {5 y  k! i( w$ H/ l
                mButtonSettingRoute.setEnabled(true);
    7 L+ y8 D% O4 J7 f, B            mButtonFileManagement.setEnabled(true);
    7 F6 y1 ~/ f7 e2 `, }        } else {
    ( e& `) U, l2 J2 r: I# x            Log.v(TAG, "刷新SDK: False");
    * u2 F: B$ e' D2 w//            mButtonOpen.setEnabled(false);
    . V. H0 Y5 C/ W, I8 h# x//            mButtonSettingRoute.setEnabled(false);& d8 T( }) x- f9 o  V1 @
    //            mButtonFileManagement.setEnabled(false);5 Y8 _  h& w' k  d1 A
    //            startSDKRegistration();: i3 w9 {* S$ i$ c4 F4 b: \* G! X
            }; G8 u" Z. s. [5 l( z3 K7 k
        }% x% M* L! E; g4 i. C+ _2 A
        protected long exitTime;   //记录第一次点击时的时间
    ) \7 D: D5 f, k4 P8 a  Y9 C    @Override5 `% Y% @( }# \! _$ w% p
        public boolean onKeyDown(int keyCode, KeyEvent event) {
    ; Q5 n8 d2 p6 N1 \9 Q7 i        if (keyCode == KeyEvent.KEYCODE_BACK
    / s4 a6 s: Y) A( A5 D- ^1 i                && event.getAction() == KeyEvent.ACTION_DOWN) {
    ) v5 @0 Z1 j" L' \1 ]6 v# c$ x            if ((System.currentTimeMillis() - exitTime) > 2000) {
      s- }$ O9 Y3 n" f. U) f                showToast("再按一次退出程序");
      f, x% J0 F' K7 c* p  U                exitTime = System.currentTimeMillis();3 n/ F" H6 K7 z8 v0 U  S7 @; h
                } else {
    9 S: ~- A; W% N7 T* N+ t- ?                RegistrationActivity.this.finish();/ N0 n1 f3 K* W: J4 c2 o( ?
                    System.exit(0);& ?% ^  V% z3 L2 b" B* a& b4 g8 C
                }
    1 L" A. L6 @# E: \1 v( m            return true;
    6 A( m9 j0 f4 Y8 x0 \        }( G4 X& l+ \* g2 F
            return super.onKeyDown(keyCode, event);
    . `* c/ N# H. Y( @    }# A' f9 H. l6 b3 ~  l7 n1 m& i$ J

    ! E7 r* j5 n; a5 l8 c% t        private void loginAccount() {
      x2 }6 L5 k! M) l            UserAccountManager.getInstance().logIntoDJIUserAccount(this, new CommonCallbacks.CompletionCallbackWith[U]() {
    1 H3 f/ |5 _& d( m; R1 a8 m' t& S  @                @Override
    ) ?7 x4 E# S* d% y; X& u* {                public void onSuccess(UserAccountState userAccountState) {/ O! }- W5 f0 E+ ^$ _+ L
                        runOnUiThread(new Runnable() {
    : I. A) }" f. W/ P2 m) g4 w/ U                        @Override5 L5 a4 M0 g6 e- Y8 O' X# x
                            public void run() {
    / s% ?/ J+ b1 U# i' ~! i                            mButtonFlightTask.setEnabled(true);
    . O* j# s. X) e- Z6 F! ]0 Q1 u                            mButtonSettingRoute.setEnabled(true);
    # N5 I" r" r: a1 r. ~                            mButtonFileManagement.setEnabled(true);
    6 ?5 A2 E! N' B  D$ H4 M                        }
    ) g5 y2 `# G, n3 _8 B                    });
    2 k: m7 Y/ J4 u1 R+ _                }
    5 ~) A8 k6 l$ C* C4 D5 T+ K                @Override
    ) e& A$ Q* w+ u9 {3 h                public void onFailure(DJIError djiError) {
    6 S+ T; ^2 i; x5 h* i                }
    0 l+ D. w4 M, E% ^            });
    3 K4 Q% B/ N* s6 [        }& F$ O3 _6 n% H* `; _) d
    }
    8 T# O) L3 ]3 z' \上面的代码就要进行第一次注册登录了,当然你不需要自己去设计登录注册页面,大疆会调取自己的登录注册页面供你使用。$ x5 h# O, u2 ?& d

    5vvpks3hoqw64023083305.png

    5vvpks3hoqw64023083305.png
    % L0 l) {4 |  [+ b& V* g
    安装提示注册登录即可。* b$ C, {. J" S, r) m& f5 I
    上面的这些做完后,恭喜你!现在,您的移动应用程序和飞机可以在中国使用而没有任何问题。换句话说,您的应用程序现在可以看到飞机的视频流,并且飞行将不仅限于直径为100m和高度为30m的圆柱体区域。
    & F6 C, P# I5 c. Y+ H5 a3! ^  N+ k1 n/ \' s3 r
    飞行界面使用$ T+ L' ~; e# ?% }5 l* }
    虽然说可以正常飞行了,但是飞行需要设计飞行界面。那么创建一下飞行界面的UI及逻辑处理文件。逻辑处理文件中包含了获取飞机的实时姿态信息,代码中有注释内容,描述的内容就不多说了。( o6 m) Z  f; i, v. N' v
    " }: Z/ j# A1 r5 i  k* h. E+ N
    导入UX SDK依赖
    : k0 I, x8 ~! q7 ]5 `. R( |3 B$ J( s+ \上一节有说过集成部分,其中内容有导入UxSDk 的操作,这里再顺便提一下。再build.gradle文件中加入implementation "com.dji:dji-uxsdk:4.16"依赖,等待安装即可。
    7 M) N( i+ `. U+ }) g, _* }+ K; A$ E
    设计界面UI
    + u% D8 |1 O; ^* o7 E" ?创建MainActivity文件及activity_main.xml。
      G7 S% F: i2 F( IRelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"0 e: U- ?  z# e2 Y2 C- e; V* ]
        xmlns:tools="http://schemas.android.com/tools"6 m- ?6 F' R4 c, F7 j
        xmlns:custom="http://schemas.android.com/apk/res-auto"" K% n% Q7 c0 ~1 y# W. g
        android:layout_width="match_parent"
    ! O! _1 L4 p1 s- k7 D    android:layout_height="match_parent"
      I1 B) w5 `  k: ?/ K4 {/ H    android:background="@color/background_blue"; b5 X# m6 Q6 k: h2 h( R1 A5 b( O
        android:id="@+id/root_view"
    ! Z* M% O% F3 s; G; Q# w    tools:context=".ui.MainActivity">9 e& L& ~4 z* u& l1 `  p7 r5 T2 G2 |
        + _" @+ J5 C; q4 F% P
        RelativeLayout
    ! Y* j& F% e  C5 _) ?7 X& K" j4 c3 h        android:id="@+id/fpv_container"
    1 W, ~7 R* [+ Z# V2 K& j& v        android:layout_width="match_parent"
    + [. I8 {9 O: P# g9 J8 k2 |3 F% T        android:layout_height="match_parent">3 t! }7 i+ m3 K& c9 c3 P$ e
            dji.ux.widget.FPVWidget, s; ?" [. k- D" t8 I
                android:id="@+id/fpv_widget"
    0 ?) i2 X: }- X. p. S/ ]/ d( T            android:layout_width="match_parent"
    $ N8 l& e+ f; V" q& C/ w& ^5 \            android:layout_height="match_parent"
    * \! o9 o) Y# U2 ]2 G            android:layout_centerInParent="true"
    3 x1 A9 A  N. W/ G) r. ]* i            custom:sourceCameraNameVisibility="false" />
    5 k0 z+ B+ s; `3 l1 b6 C    RelativeLayout>; s5 c" H) `; q' h% g
        dji.ux.widget.FPVOverlayWidget# F4 _& J7 s  }8 [
            android:id="@+id/fpv_overlay_widget"- I7 v8 C  L; t9 E; ]
            android:layout_width="match_parent"1 a' Z- @. C0 ~8 m: T- Z0 {
            android:layout_height="match_parent"/>' r. z$ j; N: k1 F7 ?- b, j
        RelativeLayout+ D5 M+ r0 c  @3 I+ M' \4 k
            android:layout_width="match_parent"
    # I6 P6 }1 a% s2 O) z( b2 E( W) \        android:layout_height="match_parent"# {8 H, v* T- ~7 X1 j/ g" \, P
            android:layout_marginBottom="40dp"& D3 a  q( |% q3 w
            android:layout_toRightOf="@+id/TakeOffReturnPanel"
    + S, ^: H; n+ C/ |  E, x6 A        android:layout_toLeftOf="@+id/CameraCapturePanel"* p2 d1 |- R+ c( k: ^8 h! Y5 g
            android:layout_below="@+id/camera"8 G; F( ]0 g; s* Y) N8 L6 Y3 \
            tools:ignore="RtlHardcoded">/ H0 l" x9 n5 C$ M9 r- M' _* i4 i; R2 C
            dji.ux.widget.RadarWidget
    8 m/ s6 D" I6 C0 I6 b' e( p' z            android:layout_width="wrap_content"
    6 v5 p# a+ z( n! X- @; J  q            android:layout_height="wrap_content"
    / m+ M' E# Z% L0 S2 _6 @/ w) O            android:layout_centerInParent="true"/>
    4 |% J1 X( _/ I: e    RelativeLayout>
    / c1 v9 I1 _+ F; K   
    7 u4 O4 J: h4 ~* k    LinearLayout+ \( _. w) W7 r) _
            android:id="@+id/TakeOffReturnPanel"6 Q4 y, P: T8 d$ m
            android:layout_width="40dp"$ j/ ?0 ~3 U% L6 m. L; ~8 @
            android:layout_height="wrap_content"
    9 ]3 C" O: I0 _. f        android:layout_marginLeft="12dp"
    + l% b( E5 G7 `+ q! v* }+ E        android:layout_marginBottom="4dp"
    # n  a5 o/ n$ H; }1 z  z6 n        android:layout_marginTop="50dp"' K- f' ~$ S7 |# v. U7 W
            android:orientation="vertical"
    - E7 n2 M" m1 [- q8 E. c        android:gravity="center">9 V+ D( y) X9 W' u. c- N
            ImageView5 B( w/ O  Z1 m/ L& N, ]
                android:id="@+id/img_show_back"* l& f, s- g$ N% j7 Y! v1 Z
                android:layout_width="match_parent"
    + j  T2 `5 j% W# c$ m* L% l, y; {$ C            android:layout_height="38dp"' S7 M' E, t" A3 Y/ n: _5 O9 u' |
                android:src="@mipmap/ic_back_36dp"
    % b% d/ E0 v& T6 n+ }/ ^" N% d5 ~! q            android:layout_marginBottom="10dp">ImageView>
    8 }5 K: [' ?! S$ p5 o5 r        dji.ux.widget.TakeOffWidget: T4 m7 N% c# X0 T) o* g) z
                android:layout_width="40dp"0 q2 G/ f) P8 F1 {$ z
                android:layout_height="40dp", n: k8 s& _7 j% d4 `7 {
                android:layout_marginBottom="5dp" />  ^0 |. u) F3 k0 F
            dji.ux.widget.ReturnHomeWidget* o& G3 K  K. k, n6 U
                android:layout_width="40dp"
    3 {! C$ O2 Y- \" A5 I0 N            android:layout_height="40dp"
    0 X  Q& S# i& b& x            android:layout_marginTop="5dp"
    ) ]9 ?9 q, P* c5 r- Z            android:layout_marginBottom="5dp"/>+ P- }$ f- y) e0 c' d, T  l
            ImageView
    . n) [. T6 g! L, n% K, X            android:id="@+id/img_live") M4 ]4 X2 }2 M
                android:layout_width="35dp"( @& h4 Y$ U* V6 A
                android:layout_height="35dp"
    5 @# X- F4 |$ @            android:layout_marginTop="5dp"
    6 b1 }* R- k7 z  V# N            android:layout_marginBottom="5dp"( L4 T2 d# }8 i/ W
                android:src="@mipmap/ic_live_write_36dp">ImageView># i$ g0 |3 Z# y. r" H  q& ~* X
        LinearLayout>
    , N) Z3 r% F8 w2 ]& V0 v    FrameLayout" H' b9 J1 R, F3 J  H
            android:layout_width="150dp"
    , i4 B0 D# i! l        android:layout_height="100dp"& C- i8 K! \, {* z, }& ]6 x
            android:id="@+id/secondary_video_view"
    4 x% {' I6 |/ m        android:layout_marginLeft="12dp"
    ; u, X* D; u% `7 o7 z6 e3 [& V        android:layout_marginBottom="7dp"
    0 A+ W% Q! e' ?( Y% \        android:layout_marginTop="50dp"6 o* y* P9 H3 W( B6 R
            android:layout_alignParentLeft="true"
    7 I  [2 H# X9 V4 V/ n" ^' u+ Z        android:layout_below="@+id/TakeOffReturnPanel"" x; F+ W% {! K
            android:background="@color/black">9 x, Z( q: b" ?: r2 U
            dji.ux.widget.FPVWidget* ]9 m4 @- E# w8 a8 g
                android:id="@+id/secondary_fpv_widget"  J9 Z# ^1 a3 ^$ t, F& ]. q5 X
                android:layout_width="match_parent"
    7 N2 j% ^5 X  S( T: Q- r& N! s, k4 r            android:layout_height="match_parent"" l. R% n$ q1 b" i+ }; w. i0 M* }$ `
                custom:sourceCameraNameVisibility="false"0 y" o+ K( X+ \+ K- \
                custom:videoSource="secondary"/>2 f3 v1 t& x% E/ Y
        FrameLayout>
    - L$ y3 q5 }$ |. J3 {% x    dji.ux.workflow.CompassCalibratingWorkFlow
    9 C5 s# C% w2 ^8 b4 I0 {        android:layout_width="match_parent"+ }8 i8 M/ g8 e8 F3 j
            android:layout_height="match_parent"/>( G6 m3 b6 ~/ X1 a7 w, G
        dji.ux.workflow.CameraSensorCleaningWorkFlow! q+ L- \' \+ {% W) v) L. z
            android:layout_width="match_parent"9 W7 e, Y3 h: ^8 f  A6 W
            android:layout_height="match_parent"/># \( P9 A. p# N/ W& ~3 u; }6 R
        dji.ux.widget.RemainingFlightTimeWidget
    & O6 X) E: u' J. N$ T; {4 E, q        android:layout_alignParentTop="true"
    5 ?2 R7 M* H: C3 |        android:layout_marginTop="18dp"5 ~  {0 p) N+ k( R
            android:layout_width="match_parent"/ J7 K, O, P/ p2 z! O
            android:id="@+id/remaining_flight_time"! }7 y2 i" j2 [3 N  B
            android:background="@color/transparent"9 R5 t3 x6 W1 ]/ j. b3 z
            android:layout_height="20dp"/>
    2 T$ {$ `+ N* ^& }    LinearLayout
    ) {, m, R) B$ P) i        android:id="@+id/camera"
    , O4 m! s) R" g; S4 p0 ~        android:layout_alignParentRight="true"
    4 H  R( f% D6 c1 ?* s( c        android:layout_width="wrap_content"; P3 x8 s( r% u% [; c* \' U  ~' l8 C
            android:layout_height="wrap_content"
    7 T: V, _" W8 b3 i- a  m, F        android:layout_below="@+id/signal"/ }  z+ _! o/ T; Z
            android:layout_marginTop="15dp"
    1 X# H% S0 ?# G8 p0 k8 B        android:background="@color/dark_gray") S) f+ n' @* g1 y0 h  l
            android:orientation="horizontal">! _1 g& S! D4 g2 @9 \4 g
            dji.ux.widget.config.CameraConfigISOAndEIWidget7 y; @! v& m: h1 H  l
                android:layout_width="50dp"% g$ W2 L+ k2 X
                android:layout_height="25dp"/>$ Y; B# X' z+ Z3 O0 _- ]3 H- ]
            dji.ux.widget.config.CameraConfigShutterWidget$ p; ?  i' w8 G
                android:layout_width="50dp"% M- J  e2 t6 z6 e) D* k
                android:layout_height="25dp"/>
    " q& @. L. X% u7 Q# D        dji.ux.widget.config.CameraConfigApertureWidget% ^  w: r1 ?3 S& E' \
                android:layout_width="50dp") {+ _% I, Q1 ~% G: Y4 |
                android:layout_height="25dp"/>
    9 J( j& X: c/ n; N        dji.ux.widget.config.CameraConfigEVWidget
    , E  k/ B+ x/ L6 H- t0 c3 {            android:layout_width="50dp"" I* G% J2 d* W6 A
                android:layout_height="25dp"/>3 V6 x8 l1 R! J- q
            dji.ux.widget.config.CameraConfigWBWidget! ?( `: u4 S0 x; F5 s
                android:layout_width="60dp"$ v7 g. _& I3 S% ^) R$ g, J
                android:layout_height="25dp"/>1 t& O  p8 \) E" V/ C: `3 a
            dji.ux.widget.config.CameraConfigStorageWidget- j3 ~& D6 p7 n8 `8 j! P! f
                android:layout_width="108dp"2 z/ D, U4 ?. w( k+ Z, o! R0 r7 G
                android:layout_height="25dp"/>" H' V1 L: U+ g: O
            dji.ux.widget.config.CameraConfigSSDWidget
    ! V: g  q8 e4 E4 v+ Q            android:layout_width="125dp"% B8 B5 R8 Z. I' d* j$ Z" U
                android:layout_height="25dp"/>
    , _% ^8 \: ~0 `" I, ^    LinearLayout>" s4 x& n' w( H% M! n, A
        LinearLayout/ F4 g0 a# q; S7 Z$ D
            android:id="@+id/camera2"
    4 f6 J+ B! {* ^  Y3 }% I        android:layout_width="wrap_content"
    8 U1 l# o% C6 \& u2 g        android:layout_height="wrap_content"
    7 _/ l. O9 M' g+ f( }, G4 ?        android:layout_marginTop="5dp"
    1 H5 l& u+ k( }* }' e$ n0 v        android:layout_below="@id/camera"' r$ \$ X4 M7 w+ Z
            android:layout_toLeftOf="@+id/CameraCapturePanel"
    ( ^9 j$ O& M# g& v6 o9 @        android:background="@color/dark_gray"
      \4 G; b* u) p3 A: ~) Z' ?        android:orientation="horizontal">  R# \8 G+ P! X- v
            dji.ux.widget.SpeakerWidget
    0 H* b6 y9 G4 l$ p6 a- E4 h4 K% K            android:layout_width="35dp": t% d$ G+ |" i3 C' R/ K: S
                android:layout_height="35dp"/>
    # l7 p( l, j; i8 T5 {" ]* u4 r        dji.ux.widget.AutoExposureLockWidget# v- a; l5 ?' F5 i) J+ |- @$ m
                android:layout_width="35dp"4 U& B: O! R& ]
                android:layout_height="35dp"/>% G2 p0 _7 w. }
            dji.ux.widget.FocusModeWidget
    . G4 `4 L2 m5 I) M& F$ m5 z            android:layout_width="35dp"
    2 c' T' h. `3 C: N. M2 ?1 K            android:layout_height="35dp"/>
    # Z; p6 G& Q; r& _) C        dji.ux.widget.FocusExposureSwitchWidget" m& s0 ^9 F$ I$ h+ r" k& P
                android:layout_width="35dp"8 `8 J6 O$ C, H5 R0 C0 R* J5 E: f
                android:layout_height="35dp"/>
    % d! F' }  s: y8 [- l$ t7 |) H        dji.ux.widget.BeaconWidget
    9 n( `/ ^7 O! e9 E            android:layout_width="35dp"
    3 ?" Z* H% x$ |/ Z. W            android:layout_height="35dp"/>& E$ _; L% }" n: P, h& E, C
            dji.ux.widget.SpotlightWidget
    3 V- V8 N+ \6 X            android:layout_width="35dp"
    ! O/ V9 h" l4 [1 V3 t4 v$ @            android:layout_height="35dp"/>1 `# x" Q, |1 J' B0 l  Q
            dji.ux.widget.AccessLockerWidget5 j$ Y9 |* d! H. \. p
                android:layout_width="35dp"5 Q) t  t- E& N1 ?& A
                android:layout_height="35dp"/>3 r: ^5 h9 g% d
        LinearLayout>( G1 H' c, ]% n; {7 O
        dji.ux.widget.ManualFocusWidget/ `! |2 z4 I' X
            android:layout_alignTop="@+id/camera2"
    / f3 k8 f1 O% d1 m+ H        android:layout_toLeftOf="@+id/camera2"7 }3 X3 A2 q, D( Q. V
            android:layout_width="50dp"& V" v/ x/ }" G6 `( n  f1 F
            android:layout_height="210dp"
    4 u7 G8 U& X* N! x' A        tools:ignore="RtlHardcoded"/>
    % Q  A& B6 J. h( N    dji.ux.widget.MapWidget; I4 D1 V# c/ Q0 U
            android:id="@+id/map_widget"6 |- P' y. h& L" \1 D5 G
            android:layout_width="150dp"
    ( F  K. C0 P; v1 u; \        android:layout_height="100dp"2 a  ]; @% i% _
            android:layout_marginRight="12dp"
    : ?, E+ H$ J% c3 s5 K. J$ I1 j        android:layout_marginBottom="12dp"
    1 L3 S, d+ H: e) t8 ~8 J3 t        android:layout_alignParentRight="true"
    6 B( B+ D( E* H* T8 b3 s9 L) p        android:layout_alignParentBottom="true"/>
    ! o; ^7 C. p3 ^1 e& m/ c6 \( {( h   
    + S' W5 X/ W3 q( h! R    dji.ux.widget.controls.CameraControlsWidget
    5 m$ @" D3 L: G- K+ V        android:id="@+id/CameraCapturePanel"
    ! o0 |5 u( z" u0 f1 K        android:layout_alignParentRight="true"
    $ _) n& Y2 c) t5 a# X. t        android:layout_below="@id/camera"
      A2 x* S* @& V. {' r/ z, Y6 W        android:layout_width="50dp") e/ q7 [. J: X, k' b! E% k
            android:layout_height="213dp"
    ' S* h9 W* t" B' [/ U. c# d- [        android:layout_marginTop="5dp"
    4 M8 D# p( K# y$ Y' x+ X        tools:ignore="RtlHardcoded"/>
    $ x* T% a$ k* I- G7 ^- ^" e8 F1 B    7 T, E. X* d. m8 O0 j: G  c  U
        LinearLayout5 |7 C5 q, D1 c' v
            android:id="@+id/signal"* [7 o) t. q5 ^; ?6 E, }6 N
            android:layout_width="match_parent"
    ' ~% R& c7 w* k/ c        android:layout_height="25dp"
    : |; z& M: W8 Y" K        android:background="@color/dark_gray"6 m9 h* u+ L. B4 c; }/ ^1 p0 N4 C
            android:orientation="horizontal">
    ; L" L3 e! ]$ f6 o" F        dji.ux.widget.PreFlightStatusWidget
      D$ l9 n5 N7 @+ Z4 G            android:layout_width="180dp"- [* s. n; j7 t( t2 ~. ~
                android:layout_height="25dp"/>
    ) I3 _4 N; e/ o  h& }5 G7 J' A        dji.ux.widget.FlightModeWidget
    4 j/ a9 k$ J9 L  q$ h            android:layout_width="103dp"
    0 ~/ C5 W7 s) X            android:layout_height="22dp"/>
    2 Y) O2 c) h9 `0 f1 _        dji.ux.widget.GPSSignalWidget/ v) _7 V1 n3 G4 @" m3 T3 ?1 T
                android:layout_width="44dp"
    / M7 r4 V! R$ Q: @- k9 x: C7 @& D1 h3 I            android:layout_height="22dp"/>3 k, {, }0 Q0 Q: V
            dji.ux.widget.VisionWidget
    " c: M! ]3 |& o& ?, e$ f            android:layout_width="22dp"/ K# M8 p9 t3 R' m2 X
                android:layout_height="22dp"/># ^7 f, q1 O7 h: b+ C) @* C& K
            dji.ux.widget.RemoteControlSignalWidget2 o8 y6 {6 X' X0 Z$ N- j# I
                android:layout_width="38dp"" A0 {3 {5 t/ B: G; Y1 ^
                android:layout_height="22dp"/>1 ]4 u* ?" n* i6 X8 X' _
            dji.ux.widget.VideoSignalWidget
    . ~5 I' i, K+ D/ x+ t7 D' i            android:layout_width="38dp"  a& M  h, F$ |
                android:layout_height="22dp"/>+ ]3 Z1 l! j3 J' _
            dji.ux.widget.WiFiSignalWidget( a$ E* \6 T, ^, Q
                android:layout_width="32dp"' t0 S$ `1 w0 h6 Q' X0 L3 t
                android:layout_height="25dp"/>. h0 H: @0 u! q, N8 b& F; q) M
            dji.ux.widget.BatteryWidget/ x. `# n9 I. R% `
                android:layout_width="96dp"
    4 D0 e# ]$ \3 {4 H! Y* |& b% ]  e            android:layout_height="22dp"
    & R% Q& I! O6 W: a4 ]6 I            custom:excludeView="singleVoltage"/>. n$ {+ _) o6 o- P6 Y
            dji.ux.widget.ConnectionWidget  q# X7 r: G) n; v  }7 d; k! W
                android:layout_marginTop="3dp"! M/ b( G1 ?0 K7 ~8 ]3 W
                android:layout_width="18dp"% W* }/ h) V  c% F
                android:layout_height="18dp"/>
    % [) q  A# V  F1 c) i    LinearLayout>
    8 _) K4 \. c: g$ @2 t1 v    LinearLayout
    ! V# V1 p+ O7 J. ?2 F. Q; ~* G+ n        android:id="@+id/dashboard_widget"
    8 J: x% Y8 f$ t1 |5 g/ ]. K! [        android:layout_width="match_parent"
    6 q! ^6 w7 F3 c" {1 r        android:layout_height="wrap_content"- F; R  @+ C, O* |. T6 e+ F) q* H- G1 O
            android:layout_alignParentBottom="true"
    9 ]4 v* @6 B* v7 U        android:orientation="horizontal"+ B; \" Z" J- s, a
            android:padding="12dp">2 N2 a  Z. U8 L
            dji.ux.widget.dashboard.DashboardWidget
    ) u/ g# t  t/ M) M9 x+ ?* j/ d5 G            android:id="@+id/Compass"2 U/ ^* x8 ~0 y8 I- G6 d  R
                android:layout_width="405dp"
    + V3 J; J; M1 b4 W+ ^0 t            android:layout_height="91dp"
    0 g8 ?& x! _! G7 V& _* P            android:layout_marginRight="12dp"
    " m* o2 e! L$ V8 T/ v* |            tools:ignore="RtlHardcoded" />1 m. o5 H" `4 S' z0 N# z& z
        LinearLayout>
    ( g7 D1 x9 v& T
    9 E4 n  n, ~, V2 q7 ?7 ^7 K6 g) z0 T
        * W3 p  v3 w) J  N# K0 f
        dji.ux.widget.HistogramWidget4 Q* h2 L" A8 [
            android:layout_width="150dp", R" y9 i- L9 l; l/ Z4 T/ s
            android:layout_height="75dp"
    7 S8 s2 L5 Z7 t        android:layout_centerVertical="true"" g- w7 l$ a9 Y
            android:layout_toRightOf="@+id/TakeOffReturnPanel"! r- J- C' I" T. q: X- B* y/ I1 j
            tools:ignore="RtlHardcoded" />! q' F' W3 k# m* f# D) d
        dji.ux.panel.CameraSettingExposurePanel
    : L( n' H$ z  Q; }2 J        android:layout_width="180dp"
    & P7 \4 t5 e+ X& P: I  e) `; m        android:layout_below="@id/camera"5 J5 {, |( \6 z+ Z
            android:layout_toLeftOf="@+id/CameraCapturePanel"
    . e) h8 n* i& x        android:gravity="center"; H0 c- @& C! B0 W3 i9 n
            android:layout_height="263dp"
    ! o( F+ f" `7 R# i% ^) n: J        android:visibility="gone"4 ?5 o$ Q( D) N6 ]7 U  ]
            tools:ignore="RtlHardcoded"/>$ G- Z4 V5 X0 N+ {$ G1 e: u
        dji.ux.panel.CameraSettingAdvancedPanel
    . F7 [' @# K# |5 I& r% {        android:layout_width="180dp"% ~/ _8 J) a! I; f6 z& q! V
            android:layout_height="263dp"+ r0 `: m* q( P2 q
            android:layout_below="@id/camera"
    7 Q; |# X* [3 o" z) T, |4 |        android:layout_toLeftOf="@+id/CameraCapturePanel"
    ( s/ o0 x, O# l2 t! @+ i: U. Z! X        android:gravity="center"$ K* x7 H% G2 `, ?' C
            android:visibility="gone"8 v# V9 Y2 G! U, a  _- J6 k
            tools:ignore="RtlHardcoded"/>7 y9 |& n9 }4 `$ h
        dji.ux.panel.RTKStatusPanel
    . f8 h3 |9 L5 z, e8 s. I        android:id="@+id/rtk_panel"
    7 T# i- r" c. y0 Z1 q5 L2 y        android:layout_width="500dp"
    % h; a+ l* W% R1 f  k, B( w& f        android:layout_height="350dp"  Z8 S) u7 \3 Z( x1 N
            android:layout_below="@id/signal"6 q1 C# M. k6 n; Z& y4 R
            android:gravity="center"" a3 g) M. n' I
            android:layout_centerInParent="true"  l4 k0 X6 Q+ F) M4 D) c! d+ X7 i8 J
            android:visibility="gone"/>
    # O2 k+ k8 g. l7 E    dji.ux.widget.ColorWaveformWidget* R, ?8 h5 H; |
            android:layout_width="394dp"9 H7 @7 p) w7 y! r) d
            android:layout_height="300dp"
    ' n$ J6 C/ Q0 h4 X+ K; }+ ?2 h/ G5 g        android:layout_below="@+id/camera"
    * _. K$ u, o6 s: @6 b. N        android:gravity="center"
    8 C+ _$ j# ?: l7 x* `9 I: `* @        android:layout_centerInParent="true"
    4 a! }9 m4 K6 R& p) \( ?4 i' p! Z        android:visibility="gone"/>! ^+ T- K7 z" P8 F6 K; |" X( V
        & Q; ]; [8 C0 h5 ], _: P
        dji.ux.panel.PreFlightCheckListPanel
    1 c2 E8 C4 k) q        android:id="@+id/pre_flight_check_list"
    4 `/ m4 \( J) l) A+ C9 E7 T        android:layout_width="400dp"
    7 Y6 b0 `" U: B& G6 T        android:layout_height="wrap_content"8 s) G; G" Y, ]5 \4 @  P8 u7 B3 E- l- e
            android:layout_below="@id/signal"
      f% w! M6 f, a% d        custom:excludeItem="ESCStatus"
    / F9 t/ C! a; E. X1 ]% L; N) i% i2 R        android:visibility="gone"/>
    8 L7 B$ P5 w: B6 I  B. w  E    dji.ux.panel.SpotlightPanel
    ) M4 e' I8 p/ k% X# X        android:id="@+id/spotlight_panel"( i1 a3 Q" T+ U' e: A' J* [. @& m
            android:layout_width="300dp"
    ; w( U, I) d) g5 a1 e  G        android:layout_height="wrap_content"
    2 i4 \9 B. f* I) ~( _1 p# x        android:layout_below="@id/camera2"
    , v. V; ]% T, `6 s6 F7 ?" G6 P        android:layout_alignRight="@+id/camera2"
    # `' W0 B% C& ?( j4 y        android:visibility="gone"
    % L: v' l* s; G: g- }        android:gravity="center" /># j  ?& ^5 j5 n& ?  A
        dji.ux.panel.SpeakerPanel
    3 q$ p2 |7 ?5 i" O! K        android:id="@+id/speaker_panel"
    2 o; Y: u+ |) ?        android:layout_width="300dp"
    $ u" \: Q% [( {& u( b4 ^. L- F        android:layout_height="match_parent"9 X2 f$ s! U5 ~& c' x( _- z
            android:layout_alignParentLeft="true"
    ) _& Z6 U! v! y9 v; N        android:layout_below="@+id/signal"
    , C- F1 _# C* A  h3 k: M- f        android:visibility="gone"  }- q' |3 X% o, |
            android:gravity="center" />
    , m' t3 ~$ V9 }# K+ Y! SRelativeLayout>" W/ ]# n1 o; ^% n4 u5 F& j& x5 R
    @Layout(R.layout.activity_main)* C. J6 x5 ?9 t5 g, Q6 P: w6 Q
    public class MainActivity extends BaseActivity implements View.OnClickListener {% E  m9 \$ o3 n" A
        @BindView(R.id.img_live)
    ! Q& _) B+ G/ r/ B! d    ImageView mImageViewLive;8 U5 S  V: Y9 l( V4 q' F  L
        private MapWidget mapWidget;8 T* W" o0 `6 r' c; g7 m
        private DJIMap aMap;9 E6 o- F5 H1 a7 X0 W+ ~
        private ViewGroup parentView;
    ! f3 _$ K3 y" B% i7 C    private FPVWidget fpvWidget;2 _& y/ ~, L0 V
        private FPVWidget secondaryFPVWidget;: ^. F; |# \% ?3 o- s
        private RelativeLayout primaryVideoView;4 v8 b. l$ O% M3 [
        private FrameLayout secondaryVideoView;+ W# j5 [7 Y: z0 _
        private boolean isMapMini = true;* x, M4 @! h8 Z9 R% }/ k9 J8 ]
        private String liveShowUrl = "";
    ! H6 b" q) ?  `/ N    private int height;
    ( w& i2 X% v4 ]- `    private int width;$ K$ F( t4 n3 x
        private int margin;
    4 L$ F2 u0 K) d$ S    private int deviceWidth;1 G. [4 P6 p4 \- U+ P
        private int deviceHeight;
    ' Z2 h: u2 }- `$ f* a1 N    private SharedPreUtils mSharedPreUtils;
    & _+ l; b  \' F7 p$ w6 e) _9 H4 p/ {- \    //unix时间戳+ t! y; c- a0 D& n
        private String dateStr = "";! Y! ~  X! L1 k/ Z) ?+ z
        //飞行器管理器
    " R6 w  i: j: a8 [7 L    private FlightController controller;/ b/ q. b, I3 a" a8 n* a
        //经纬度
    1 b! }3 q  }6 F  Z9 j% F    private double lat = 0, lon = 0;
    5 }* K) @+ l8 V7 n1 G    //高度
    4 O: Z3 n- c3 v! `    private float high = 0;
    1 b3 w1 |  [/ p( a) d- W    //飞机的姿态
    1 I  L7 j- ]+ n, A: e    private Attitude attitude;
    7 d+ H2 h; Q3 h$ `0 K    //俯仰角、滚转、偏航值7 H1 h4 u; x7 ]$ R9 \
        private double pitch = 0, roll = 0, yaw = 0;0 l' B0 t5 i) q, ^
        //飞机的速度# q( O% Q: D- i# l  K! Y+ s7 {
        private float velocity_X = 0, velocity_Y = 0, velocity_Z = 0;4 q  D7 x; p6 S( g
        //飞机/控制器电池管理器0 f5 F% k0 B# `# M% a$ x& a
        private Battery battery;
    5 y/ t/ r+ L& m, n* {    //电池电量、温度
    1 K; o' Q' G3 r7 F' i- R    private int power = 0;3 a+ @+ `9 a& ~+ [/ F" `5 b
        private float temperature = 0;
    7 j# a8 w2 Y. Q, N    //云台管理器( ^1 |3 P) H' O4 \
        private Gimbal gimbal;0 }/ m9 D' }3 O/ G6 F
        //云台的姿态* S  U* t- `# {  v
        private dji.common.gimbal.Attitude g_attitude;, B% e  i4 p# O# e, _! z
        //俯仰角、滚转、偏航值
    1 f4 D1 A3 e! p    private double g_pitch = 0, g_roll = 0, g_yaw = 0;8 y5 C! z, H+ h- D6 [( m. O( G/ }
        private Camera camera;
    " D% {- P' X) l/ n- V* p6 n) X    private List lens = new ArrayList();  ~' G" S9 L( E% V. r( A. d) Z  f
        private List djiList = new ArrayList();: o' K% _1 u2 X0 m* B# q
        //手柄控制器
    ; n2 h1 L4 p- q3 Q) O    private HandheldController handheldController;
    ( m0 _8 P/ e8 v; }- z$ J5 e- B1 i    //手柄电量
    . p. ^5 r4 w& L8 e* I0 X) y2 J    private int h_power = 0;
    * j2 z* L) S6 `2 v/ N, d    private static List list = new ArrayList();$ n3 |" _" [) I, v7 X
        private static List getList = new ArrayList();2 h4 B2 u3 D( T4 V' r; q
        private MediaManager mMediaManager;9 b' o% W4 X! M* q; g4 W! i$ f
        private MediaManager.FileListState currentFileListState = MediaManager.FileListState.UNKNOWN;# `9 R+ X% L; I
        private List arrayList = new ArrayList();0 c0 K" G+ e! @; t0 O& Q# d8 @
        private List startList = new ArrayList();
    * b1 G6 Q  \6 n6 e; A1 H    private List endList = new ArrayList();3 T7 o# B: n) z
        private boolean isStartLive = false;1 g8 g3 f; X. l
        private boolean isFlying = false;0 }: V4 ]  i' W3 Y1 I3 r1 \( N
        private boolean start = false;
    ; z* [4 ~. o) T& {    private BaseProduct mProduct;
    9 H6 c8 c* f3 w7 ]. \% ^1 k    private String posName = "";6 S1 u/ k! a3 L. D
        //webSocket& X" V; M: i7 i# E% n
        private JWebSocketClient client;
    , u; n9 Q6 i" J# P9 U    private Map params = new HashMap();  R, p# H0 M9 c% H8 _
        Map mapData = new HashMap();
    , k8 M9 h# C0 N    @Override
    ; o" q* e( T2 N+ w, H* x8 Q2 |$ m    protected void onCreate(Bundle savedInstanceState) {/ i4 N" w' K" ^6 V
            super.onCreate(savedInstanceState);" W5 H) ]& t, D: f/ }* Z; r' @6 X
            height = ToolKit.dip2px(this, 100);% b4 A$ v+ `; o" J
            width = ToolKit.dip2px(this, 150);
    * j  ^( a: \1 N0 C$ E3 c) o        margin = ToolKit.dip2px(this, 12);
    3 U$ s$ @% N9 Q* L. I7 P        WindowManager windowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
    ; R& X' B& }7 {: a2 ]! ?7 w        final Display display = windowManager.getDefaultDisplay();
    : P1 o: p" h( c: P" F1 x8 c        Point outPoint = new Point();
    4 @' t+ O* ?# o' Y1 ]" H/ x- S$ U        display.getRealSize(outPoint);5 `  n7 B! O% e! c) z. B
            deviceHeight = outPoint.y;
    7 N, ~, \. n+ h3 G- m        deviceWidth = outPoint.x;
    9 t3 @+ s4 \  y        parentView = (ViewGroup) findViewById(R.id.root_view);% P' W. f' `5 U* H
            fpvWidget = findViewById(R.id.fpv_widget);2 t) d' Z, D8 Z- A, x
            fpvWidget.setOnClickListener(new View.OnClickListener() {+ F) v  Z* s1 ~0 {: Z/ O
                @Override
    4 \$ c* q8 _  P9 D( g1 W            public void onClick(View view) {
    1 }  m- q$ {. z2 j                onViewClick(fpvWidget);
    * B) U, p; A. H            }
    1 z) T: x& n/ H        });7 @4 b1 R4 d5 D7 X% g* X4 z
            primaryVideoView = (RelativeLayout) findViewById(R.id.fpv_container);8 V# Z: |0 X/ j' o8 L! C
            secondaryVideoView = (FrameLayout) findViewById(R.id.secondary_video_view);/ ?* [1 {2 w' h' t3 |
            secondaryFPVWidget = findViewById(R.id.secondary_fpv_widget);
    $ N) C1 K8 T  B2 l5 \        secondaryFPVWidget.setOnClickListener(new View.OnClickListener() {
    ( c3 D8 C: _. O- t' c, p# O0 |            @Override
    3 L0 M1 q( e5 ~. I( g- |* S            public void onClick(View view) {
    6 W* j! P+ B! i                swapVideoSource();) j! R0 |* O1 {" M8 `0 i
                }* _6 h/ w- w! ?+ f! u% A
            });
    5 l1 L0 k7 N; _7 |5 z) `) o3 v        if (VideoFeeder.getInstance() != null) {3 m& b* c/ p# `9 Q7 q* l1 m
                //If secondary video feed is already initialized, get video source$ S9 f6 a2 t9 W# H* e
                updateSecondaryVideoVisibility(VideoFeeder.getInstance().getSecondaryVideoFeed().getVideoSource() != PhysicalSource.UNKNOWN);9 Q* d4 _9 O4 J' N5 o9 D3 n
                //If secondary video feed is not yet initialized, wait for active status
    " Z! H; H7 x! q, Y* ^- D+ g# L            VideoFeeder.getInstance().getSecondaryVideoFeed()
    $ z& E4 v* F3 a                    .addVideoActiveStatusListener(isActive ->0 @. m6 |* z! F' O$ x) W/ l* f9 p
                                runOnUiThread(() -> updateSecondaryVideoVisibility(isActive)));* S: a4 L6 m# J7 x& g7 P! ~, r6 ~2 x# k
            }; M/ o6 p' z% J! Y4 L- [% N
            mSharedPreUtils = SharedPreUtils.getInStance(this);
    # p  K0 A) ^3 w        this.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
    1 S1 h: A0 Y* o* k1 V$ \( T        mapWidget = findViewById(R.id.map_widget);( \. g6 u0 t9 X/ \
            mapWidget.setFlightPathColor(Color.parseColor("#2fa8e7"));" o) W2 B, g4 T: z) \5 a
            mapWidget.setFlightPathWidth(15);
    ' {( D, Y# U. c1 k1 F% |; ?        mapWidget.setDirectionToHomeVisible(false);7 Y0 T5 ?! A" l- X
            mapWidget.initAMap(new MapWidget.OnMapReadyListener() {4 Y0 l% P7 E2 J/ K* _
                @Override
    ! r/ x! V/ P/ C, F2 G3 G" m            public void onMapReady(@NonNull DJIMap djiMap) {
    - t  E6 t1 X6 W: j( T                djiMap.setOnMapClickListener(new DJIMap.OnMapClickListener() {
    ; V/ z! f( m$ F( T% A+ S1 {                    @Override
    5 R' O* j0 i( y- Z                    public void onMapClick(DJILatLng latLng) {
    + M" H/ c$ l, E3 }1 h; Z                        onViewClick(mapWidget);
    + j2 r/ R' Y1 f3 z3 X( h                    }
    ! b( r) _; N& Q& Y, ~                });% r" \- a8 D: L0 Q
                    djiMap.getUiSettings().setZoomControlsEnabled(false);
      s) y) e/ |' u# M8 B            }
    # ~8 W1 \5 d0 o8 k/ M        });
    & _/ \/ O& H" _# i" r        if (aMap == null) {. `& D) h) ]1 w) V0 @
                aMap = mapWidget.getMap();
    ' I' v3 ^3 D6 [+ J% X* G        }
    : z" ]% G) I3 R8 S1 l        mapWidget.onCreate(savedInstanceState);
    9 t0 ]& \* i$ K3 H- n; \        mProduct = ReceiverApplication.getProductInstance();
    # t9 {( I. b2 v) o& g% _        if (null != mProduct && mProduct.isConnected()) {& W8 c% B6 L! x) A$ F4 R
                flyInformation(mProduct);
    ! ?; e; _: K  I& s& P$ o            batteryInformation(mProduct);
    ( [8 v1 F. e8 c* v  S. h* v            cameraInformation(mProduct);
    ; D4 Z) q1 L9 U* n0 h$ I! H            camera(mProduct);! U! u# l' O% ?
            }
    / |4 L, S7 `' k) y/ j1 R) g! {- `7 E        Timer timer = new Timer();8 x, t9 J4 i) D$ m- `; ^& ~% P
            timer.schedule(new TimerTask() {9 c3 N( o( m- O- H( L3 q& ~
                @Override$ S9 Y1 b- L( W4 Y; E- W1 Z
                public void run() {
    , ~5 U* u5 {3 ^1 Z% U2 ^7 y4 j                Message msg = new Message();
    1 Q: d7 Q  n" o) L* `( u                if (isFlying && !start) {; M3 B+ k  X' [) t
                        start = true;& M/ O) x: |  d, U: L5 b
                        
    9 q5 ]% X8 H' h& Q            4 _( l) C2 W- F: L1 \
                    }
    $ I/ F( I0 Q( d# [0 H                if (!isFlying && start) {) C4 A' {4 S- X' P9 F4 V5 z
                        start = false;( @, @$ y( H7 T- |8 V& }
                  9 s) v9 ^- R  I* `4 _% ]# ]$ U& }
                    }
    : S) Y% X1 T  k' e  e5 K; n                if (isFlying && high >= 0) {
    % ]# C& N8 X7 J/ M7 [. `7 F0 k                    msg.what = 1;+ y0 ^/ d1 R2 h, B  e5 I! j
                    }5 F# B, I- g6 U
                    mHandler.sendMessage(msg);7 |$ D. _7 ?+ P" f( `( \( k" F" o3 Z
                }- L6 Q" A: n: Z" [) q
            }, 200, 200);6 P$ m% m2 J. F/ S+ e
        }
    / g0 [5 t  d* S  T6 Z    Handler mHandler = new Handler() {1 q9 b3 O! W% }7 S7 k' P( q' a
            @RequiresApi(api = Build.VERSION_CODES.O): E4 H& o" {: |' w* ^& i! r: h
            @Override
    4 X" v9 S. e0 g. D! M( D; z        public void handleMessage(@NonNull Message msg) {4 D8 L' O( x  A! E4 s* U
                switch (msg.what) {2 s, C% N6 Y$ G: i) U; f
                    case 1:
    6 [4 a% x+ d: q4 n; A                    Long time = System.currentTimeMillis();; Z  c8 i+ o$ b9 x2 z( D! ]
    //                    MyLog.d("时间:"+time);
    8 u% O& U4 N/ [- \( u                    RecordModule module = new RecordModule(String.valueOf(projectId), String.valueOf(planeId),
    + \7 r' W/ ?. [* S! [; [. b  j3 c                            trajectoryId, time, String.valueOf(lon), String.valueOf(lat),
    # I* U( }4 i$ y" l                            String.valueOf(high), String.valueOf(yaw), String.valueOf(pitch), String.valueOf(roll)," Y- u& g' R: s
                                String.valueOf(""), String.valueOf(velocity_X), String.valueOf(velocity_Y),
    " Z, ~4 c8 P1 U9 z6 I0 _# l                            String.valueOf(velocity_Z), String.valueOf(g_yaw), String.valueOf(g_roll), String.valueOf(g_pitch));$ ?& y+ W+ e, Y% f, ?& c3 D
                        http.getHttp(INSERT_DATA, GsonUtil.GsonString(module));
    8 b7 I4 X0 M: t) \2 j' F3 c                    break;1 i& @' l1 V' E
                    case 2:
    $ F( Y% H$ @! |& E0 Q                    MyLog.d("飞机移动的数据:"+msg.obj.toString());& a/ Y9 Q6 N  C6 t! K2 f+ M5 s
                        ControlModule control = GsonUtil.GsonToBean(msg.obj.toString(),ControlModule.class);
    ' o* a& R- \0 a* e9 H! P                    if (controller!=null&&isFlying){4 f* f9 G1 [! ]! E
                            if (control.getContent().isBack()){* n6 ~* ?  k1 s3 v8 a7 G
                                controller.sendVirtualStickFlightControlData(new FlightControlData(-10,0,0,0),null);
    ! d0 o" B6 ]0 P9 X7 v! W3 X* v                        }
    & ^+ j+ A! S9 g                        if (control.getContent().isFront()){9 c$ n; m2 [8 [
                                controller.sendVirtualStickFlightControlData(new FlightControlData(10,0,0,0),null);
    - l3 e; D/ T$ {# w2 W                        }
    + |; c5 v; z6 M$ v) J% }1 r4 v$ l2 F# h9 W                        if (control.getContent().isDown()){& Z8 k2 \0 D8 Z% c
                                controller.sendVirtualStickFlightControlData(new FlightControlData(0,0,0,-4),null);* d; b" i' _) A) C' t& t3 S5 m+ ~
                            }
    " M3 e: ~+ m2 _: Y; U( T1 Z) O" K/ }                        if (control.getContent().isUp()){
    ) [1 O# ^# M7 C/ U' B! ?2 V- ~- O                            controller.sendVirtualStickFlightControlData(new FlightControlData(0,0,0,4),null);
    7 R2 I0 X, h0 ]; j6 G0 P( S- K                        }
    & N* S% j$ w9 t" d; ?' Y; I+ H+ T                        if (control.getContent().isLeft()){( _7 C8 [( W( |& E; r) D
                                controller.sendVirtualStickFlightControlData(new FlightControlData(0,-10,0,0),null);
    / G, h8 v' l  f4 j' n                        }8 ~+ F5 Z; l: `% q
                            if (control.getContent().isRight()){
    * m! A8 A1 N; J& W! A/ u) a, S                            controller.sendVirtualStickFlightControlData(new FlightControlData(0,10,0,0),null);
    # D# t2 P# f2 i                        }0 e3 S# P% J0 R8 n* P) b: X
                        }else {1 c. ^5 m2 m! [2 I5 ?
                            MyLog.d("controller控制器为空");
    / T3 E% ^9 M. c, u                    }
    , N/ C, @# t/ H0 y8 a                    break;
    + T1 I5 R; z6 {8 c, w$ x& n) D/ r            }
    5 r: r4 Z# w! y  @; `        }
    ! }; j$ [( A, R1 T- a    };7 E/ N! w# Z) ^& m- F% h8 e
        @Override
    8 j% I- C7 C, \6 q1 Z& {( L5 E5 m: T, r' v    public void initViews() {
    4 J; N( i& R7 @: k$ p        mMediaManager = ReceiverApplication.getCameraInstance().getMediaManager();
    $ {- |& E( T2 L1 y        getFileList("start");1 g& t; ]4 M( A8 A- E
        }- S; ?' p+ q7 j* Q) ]: B
        @Override
    9 q# }* j( e# ^4 q2 }! ]4 n2 O    public void onComplete(String url, String jsonStr) {
    % [9 \/ |+ o# ~5 w. P        super.onComplete(url, jsonStr);
    # W' Z( e- q0 v# U3 {( ^     
    ) c  I' ~. l7 n& ?+ R1 U* m    }, m' [+ T+ p4 ^$ u/ |7 P! Y
        @Override
    6 q! C  J; H5 Q! Q! M    public void initDatas() {
    + w1 K! E' o# G+ C" J    }8 f" W7 H' D/ |5 X
        private void onViewClick(View view) {
    3 y; C% y8 V- }" @' u        if (view == fpvWidget && !isMapMini) {5 K2 B$ m& G3 v. b. |  s6 U9 R
                resizeFPVWidget(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT, 0, 0);5 Q# V) m6 _  k4 P6 W! D% |8 v  [
                reorderCameraCapturePanel();
    0 z  m& A: |  f. T" L2 f" ?- H            ResizeAnimation mapViewAnimation = new ResizeAnimation(mapWidget, deviceWidth, deviceHeight, width, height, margin);
    1 i1 v8 ^1 B# D' y, A            mapWidget.startAnimation(mapViewAnimation);4 l+ o+ h" n* k1 y
                isMapMini = true;( A3 ]; ?6 ^# O) W$ `
            } else if (view == mapWidget && isMapMini) {
    ' j: z) O) b$ G            hidePanels();" Y" D) a" h; [) i. u3 C- j
                resizeFPVWidget(width, height, margin, 12);
    - }# }+ p3 @! b3 ~0 x  s- z            reorderCameraCapturePanel();. n$ A; I+ v* Z; H- H1 j6 K
                ResizeAnimation mapViewAnimation = new ResizeAnimation(mapWidget, width, height, deviceWidth, deviceHeight, 0);
    & U. F$ d* f6 r7 I            mapWidget.startAnimation(mapViewAnimation);
    & b0 m  V( _1 t& i; m            isMapMini = false;2 Z/ c! x" y, f
            }9 T0 W& t- A6 b& u  k8 }$ b* W
        }
    " g+ C; L0 B4 O, G    private void resizeFPVWidget(int width, int height, int margin, int fpvInsertPosition) {
    ( @) B. W7 r- x/ M( X! |        RelativeLayout.LayoutParams fpvParams = (RelativeLayout.LayoutParams) primaryVideoView.getLayoutParams();4 V/ ?- \( t$ n9 m- i9 S
            fpvParams.height = height;
    / M! K3 d7 Y2 c8 A5 J4 q        fpvParams.width = width;8 |- \$ c" O. ?
            fpvParams.rightMargin = margin;
    ; k+ R6 w. l" R4 ?! H8 \        fpvParams.bottomMargin = margin;( K$ z4 s5 R! D+ z1 ?' e' \
            if (isMapMini) {9 s- j  n+ z8 [7 c* L8 j8 a
                fpvParams.addRule(RelativeLayout.CENTER_IN_PARENT, 0);
    1 G1 e( m. e$ Q' g' c" c            fpvParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT, RelativeLayout.TRUE);- _( `6 z5 I4 w) k& r7 H2 E
                fpvParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, RelativeLayout.TRUE);) d" T4 H9 V, v# r
            } else {4 ~" y+ c5 {' O
                fpvParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT, 0);7 G) p' q8 W% @: Z4 e& Y2 |
                fpvParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, 0);
    ' f: q( O7 a5 z- \' i" [2 ]3 I4 S% ]            fpvParams.addRule(RelativeLayout.CENTER_IN_PARENT, RelativeLayout.TRUE);
    - k2 D2 C( [2 o* P. ?5 Y" s        }2 l9 W3 x1 J  I4 `; J: E, z3 X
            primaryVideoView.setLayoutParams(fpvParams);
    9 F0 M  s# j* W: m! V        parentView.removeView(primaryVideoView);
    0 i& K$ _$ N0 b( V) ]        parentView.addView(primaryVideoView, fpvInsertPosition);
    ! D# ]/ Z7 t( t& W4 ?# \& O    }
    - |& a3 u& S- G8 B    private void reorderCameraCapturePanel() {% K+ d" o8 \) ], f- G" K
            View cameraCapturePanel = findViewById(R.id.CameraCapturePanel);5 w4 n9 w# t1 s- s
            parentView.removeView(cameraCapturePanel);
    , _% p9 {5 K2 c' g8 f- L4 U' L% w7 ^        parentView.addView(cameraCapturePanel, isMapMini ? 9 : 13);
    ! D; M* l  D& g0 X    }3 L7 q8 n( z: o
        private void swapVideoSource() {
    & M/ |7 T1 Q# E$ h; r        if (secondaryFPVWidget.getVideoSource() == FPVWidget.VideoSource.SECONDARY) {/ n7 ], F3 e: j8 U5 E! z& a: p
                fpvWidget.setVideoSource(FPVWidget.VideoSource.SECONDARY);" G: [" y  V4 ^
                secondaryFPVWidget.setVideoSource(FPVWidget.VideoSource.PRIMARY);( g9 @: J7 Z* n" a% d+ F9 \0 V
            } else {% b2 O8 H- U- t" `
                fpvWidget.setVideoSource(FPVWidget.VideoSource.PRIMARY);6 M1 j; O5 x7 b! G6 z# q9 d& O
                secondaryFPVWidget.setVideoSource(FPVWidget.VideoSource.SECONDARY);. h3 W3 C2 I% o4 |5 X
            }
    9 s4 P$ Y; x& g2 s+ @    }
    - }  T% X6 T3 x6 a4 C! _    private void updateSecondaryVideoVisibility(boolean isActive) {* _6 q$ M& b. L9 L1 _, Q
            if (isActive) {
    - P- s5 z5 U, n- ^. x            secondaryVideoView.setVisibility(View.VISIBLE);$ U; r, M- A. ~. H% z! c
            } else {
    . t# d! W) Q: w# V5 _' @            secondaryVideoView.setVisibility(View.GONE);
    " L2 {' x) W0 a2 T        }& J0 B4 R( B' }' Z! t7 Z
        }
    0 B. X/ u0 r$ L% _- ~    private void hidePanels() {$ G  c" G0 m+ R5 Z
            //These panels appear based on keys from the drone itself.
    + ]* f& Q, K% h& {7 X) Y        if (KeyManager.getInstance() != null) {
    ' l. y5 B* k2 F            KeyManager.getInstance().setValue(CameraKey.create(CameraKey.HISTOGRAM_ENABLED), false, null);- \" {- j! A% Q/ x
                KeyManager.getInstance().setValue(CameraKey.create(CameraKey.COLOR_WAVEFORM_ENABLED), false, null);5 K6 h. `. C- e% S  _5 q. V
            }. N2 X' k( E; s' z/ w& B2 l
            //These panels have buttons that toggle them, so call the methods to make sure the button state is correct.3 j2 m5 s' L, P1 X% F8 }
            CameraControlsWidget controlsWidget = findViewById(R.id.CameraCapturePanel);9 I7 u6 `' W! s5 }
            controlsWidget.setAdvancedPanelVisibility(false);" U$ i' P: q% h& M2 I" h! p
            controlsWidget.setExposurePanelVisibility(false);! Q6 Q- m* V! J0 ^* f
            //These panels don't have a button state, so we can just hide them.
    & G4 s5 h7 w) d1 M& h        findViewById(R.id.pre_flight_check_list).setVisibility(View.GONE);, n7 H1 A7 `. h" o# S  s
            findViewById(R.id.rtk_panel).setVisibility(View.GONE);; g4 @' B, Y/ N1 a- [+ i( J
            findViewById(R.id.spotlight_panel).setVisibility(View.GONE);
    + j' k' V$ H. L0 G0 O1 |! C4 ^        findViewById(R.id.speaker_panel).setVisibility(View.GONE);
    $ A* g6 B3 W. g+ V) O# B  _    }
    ) C, y% y/ s! R7 X" M& v- O    @Override
    ! u: Y2 N* o1 u6 U( t    protected void onResume() {
    + h6 {. L& K- c        super.onResume();
    ) ]/ p  A1 i+ @: Q        // Hide both the navigation bar and the status bar.& l$ g) J- `+ ]' k+ c' F7 V+ N1 y
            View decorView = getWindow().getDecorView();: s  ]  @! j: f5 ]3 B8 ]/ `
            decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE6 u3 k# [+ o  C5 v. u  S
                    | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION  h- d0 W$ T5 q3 M- D" ^
                    | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN( f' i9 R' c4 q" P" @
                    | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
    6 A) h( j" x3 A8 v9 F$ m5 x                | View.SYSTEM_UI_FLAG_FULLSCREEN
    : O5 z8 V: ]% L0 o) _                | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
    1 d# _/ q- k5 ~        mapWidget.onResume();( b( R! Z: q) T& @2 l
            if (client == null) {4 _" m% }/ [3 K% @+ v. e
                MyLog.e("``````````````````````onResume");5 m& K' x5 [+ C, R: M
    //            initWebSocket();/ [: m' n3 V. x) J
            } else if (!client.isOpen()) {! k8 F# t" ]0 b2 T3 N' H
                reconnectWs();//进入页面发现断开开启重连4 k, Z" L$ `8 F6 ], ~3 P
            }) s' M* a/ A. U
        }  d- F( I) u/ m" Y5 g) a
        @Override2 o2 @8 g2 i: @4 D
        protected void onStop() {
      V  ~$ F2 |# I  Y% ^* M        super.onStop();
    , ~% J& m' V# V# g        MyLog.e("``````````````````````````````onStop");
    6 r7 l6 t& ?& K% @" L2 i7 q    }( N5 [- q( p) Z( a1 j- _  F+ z
        @Override9 R, f# N6 ?1 e
        protected void onPause() {
      T2 p5 c! O* q& r2 B3 F- Z1 J% e$ c        mapWidget.onPause();
    8 Q2 v8 y3 T  ~+ \  b) x; Q        super.onPause();
    : M" H- G; Q+ p    }
    4 N( B( ^) Z% i, g: R' c    @Override0 M. i/ S) @' K: q: ~+ l- `
        protected void onDestroy() {
    9 u  T, `3 T, b# a: Y        mapWidget.onDestroy();
      ?. c& @! E+ i$ z9 i8 G        super.onDestroy();5 j5 t! a* m, r1 m
            MyLog.e( "`````````````````````````onDestroy");4 P% @% o/ T+ R2 r& |- p1 q! y& C
            closeConnect();1 K  Z1 a/ N' ]3 p% i+ j4 t) t
        }
    * X$ R/ L* _3 }) e! S9 h    @Override* t" w, m, ~( f1 Y
        protected void requestData() {
    - _3 v3 B0 E+ ~" {) r$ k    }. Z6 Y; N- Z9 O! F0 B/ X
        @Override- f, z$ E1 L9 N  L; h
        protected void onSaveInstanceState(Bundle outState) {5 l; ]5 }! H: W
            super.onSaveInstanceState(outState);* u" z+ R, Q9 M& ^, u
            mapWidget.onSaveInstanceState(outState);3 c0 P3 F1 B- G
        }) D' x# x% l# W3 S
        @Override
    ( j, h# M: z9 k7 B0 B    public void onLowMemory() {+ S9 [2 y0 s0 r+ P8 @' }; B
            super.onLowMemory();
    # g8 r7 x  p6 H& H( N2 D" T% p        mapWidget.onLowMemory();
    4 V- O% E6 Y  v    }
    6 X# i8 E8 ~4 y" a+ R* d    private class ResizeAnimation extends Animation {
    ! h1 _: v& {0 r6 |% u( y' K        private View mView;& d' S2 ^! u7 i  B2 U; `0 x7 \
            private int mToHeight;% g* P& P& u' n' t$ ?  L+ y) a
            private int mFromHeight;" v) K) ~7 T  o0 L1 K  }) s9 M" i
            private int mToWidth;$ P& X' t& J1 b# V+ Q/ }
            private int mFromWidth;
    5 l! ]. G4 |' [, g4 i1 j        private int mMargin;2 ^9 K1 Y/ T& u1 i
            private ResizeAnimation(View v, int fromWidth, int fromHeight, int toWidth, int toHeight, int margin) {; i6 j% x4 j5 A% |" E3 P
                mToHeight = toHeight;( p4 v, v5 b- H0 Q
                mToWidth = toWidth;* Y1 A' `& x# u' k4 A% U, Z# U
                mFromHeight = fromHeight;6 y$ @* Y' H8 p: ]( D
                mFromWidth = fromWidth;  ]  a) M# }& }
                mView = v;
    ( _, Z( U5 E8 \' _0 h" @* n            mMargin = margin;
    2 _) m, W" \+ Q5 W* v            setDuration(300);
    $ N: D( i2 |1 M3 r  t; ~        }
    7 }! z& j) v6 V0 E$ p        @Override8 S' n, I! x8 W2 N
            protected void applyTransformation(float interpolatedTime, Transformation t) {
    , ?: w. J6 f. J9 h6 p; r; V; V/ S+ u            float height = (mToHeight - mFromHeight) * interpolatedTime + mFromHeight;
    ! S. S3 W1 T! h# ?; ?            float width = (mToWidth - mFromWidth) * interpolatedTime + mFromWidth;
    - O! W1 c' X3 q6 F6 h            RelativeLayout.LayoutParams p = (RelativeLayout.LayoutParams) mView.getLayoutParams();
    " s) K+ _. C! p+ e            p.height = (int) height;9 Z: b* n, h$ x& i
                p.width = (int) width;
    " ?5 \# F5 F- E' M, ]6 h1 I1 J+ Z0 M            p.rightMargin = mMargin;4 M) f" Q; d# ?! _$ k6 K! P
                p.bottomMargin = mMargin;1 x" A- d# b5 m
                mView.requestLayout();
    8 {$ S# C; V+ }$ u3 y, }( a        }
    0 z# K) J' [. ^    }* B% [- N8 R5 v1 [/ K" n' ?
    0 J9 p+ X9 @. W2 F  i
        //直播流推送
    # e( @* @/ J" X2 m& P: z    @RequiresApi(api = Build.VERSION_CODES.O)+ ^' ^, e/ i/ M2 U  d2 N
        @OnClick({R.id.img_live, R.id.img_show_back})  O& _, U: l) N! L6 Z  o
        @Override
    & Y' a9 j4 U9 f% A9 Z2 o( Q+ x    public void onClick(View v) {
    " i4 F4 P4 U7 i* [$ D6 Y8 n' ]* x        switch (v.getId()) {. e: |$ V5 B* [7 P
                case R.id.img_live:* ?$ u5 P9 ~5 t0 u4 J
                    params.clear();/ ^' U9 n0 e  B
                    mapData.clear();/ q2 g6 I: d' p/ X
                    if (!isStartLive) {
    + d5 f. {( j8 _" U/ f                    if (!TextUtils.isEmpty(mSharedPreUtils.getStringSharePre("rtmp_url"))) {2 P, g% o' W. u7 c
                            liveShowUrl = mSharedPreUtils.getStringSharePre("rtmp_url") + trajectoryId;- g. W2 Q( k% Y" A9 N
    //                        LiveModule module = new LiveModule("liveStreamStateChanged","plane",planeId,true,trajectoryId+"");# _& M$ U3 Q, X& |2 V2 o  o  }/ v
                            MyLog.d("地址:"+liveShowUrl);
    ' u2 W: ?6 I! H& K. N                        startLiveShow();9 J) i1 W2 k7 z6 m9 _4 I
                            isStartLive = true;2 \% d/ w: }. `
                            showToast("开始推流");" t2 S+ }5 N" y6 J1 f
                        } else {
    6 b8 |2 m6 r# d7 h4 R! V- v                        showToast("请先进行系统设置(RTMP)。");. _7 d( R- M# k8 F/ a
                        }
      p" h+ H8 j1 p* V8 Q                } else {7 g/ m( f4 l- I  q# v# k
                        stopLiveShow();0 ^; |1 V6 l  u! f, R  T
                        isStartLive = false;
    % H- c) x7 L4 T) c  b2 t                }
    6 S; S4 y% D3 R+ d4 H6 ~9 b                break;
    ( N( T' Z: b/ t) ]8 }3 e            case R.id.img_show_back:+ b! d# w+ ]4 L& O; s; T+ L; _
    //                controller = null;" d" B# m( g) X
                    closeConnect();/ h- B& B  V4 T1 g. Q
                    MainActivity.this.finish();
    ) ?6 y0 p" L0 F9 w                break;% W# r: B) W/ o: q+ t
            }
    1 x0 Q9 x/ k# A& [/ d    }
    0 d  U$ t" M& `1 {    private boolean isLiveStreamManagerOn() {
    / j. ~3 J# {3 ]2 T, _3 P        if (DJISDKManager.getInstance().getLiveStreamManager() == null) {
    5 h. J" A, ?# y# ~1 O& }            return false;
    4 Y+ u1 h  {8 w        }  T0 H. J7 }3 x( T+ p
            return true;
    : K( K+ W2 ?- V5 ?; K    }
    ! Q% l) K4 N0 C- {  P    private void startLiveShow() {$ Q8 X- J' h3 {  f+ a
            if (!isLiveStreamManagerOn()) {
    3 p7 U. |4 ~3 M  X  X# `            return;: \/ c/ f- G1 e! \6 c' i( K  L
            }
    ) k9 L0 N  J3 g        if (DJISDKManager.getInstance().getLiveStreamManager().isStreaming()) {! {+ Z5 A: A+ l9 u
                return;9 u/ U/ X6 ~0 p0 ]7 v
            }0 B" h( A7 d" I( d$ s4 g
            new Thread() {" H3 S8 H: S/ m; P
                @Override
    ! a* _$ h1 @, h$ P% \# e            public void run() {
    # f7 I7 v- p. C# Q                DJISDKManager.getInstance().getLiveStreamManager().setLiveUrl(liveShowUrl);  W" z3 f# }1 g2 f9 v8 A. r7 I: x
                    DJISDKManager.getInstance().getLiveStreamManager().setAudioStreamingEnabled(true);2 @$ P2 h; p0 K: d+ ^4 s
                    int result = DJISDKManager.getInstance().getLiveStreamManager().startStream();$ G" `9 E' z0 B1 A3 |; }8 V
                    DJISDKManager.getInstance().getLiveStreamManager().setStartTime();: u* _, o6 r* S2 G& P
                }5 h; X: M3 C: H
            }.start();) n, V7 t  E2 c
        }
    7 N; e; J( d1 s3 a    private void stopLiveShow() {8 ?* `: \: G, _" @
            AlertDialog.Builder Builder = new AlertDialog.Builder(MainActivity.this);* u6 U- c; R1 g4 m
            Builder.setTitle("提示");$ \" y5 Y$ L9 C" _  v! Q
            Builder.setMessage("是否结束推流?");
      {4 I" j7 I0 m+ r; V2 x        Builder.setIcon(android.R.drawable.ic_dialog_alert);6 ]5 g4 a4 m0 d
            Builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {
    2 F) w( n: T# a1 O' K5 ?+ H            @Override! @6 }0 D0 U* {
                public void onClick(DialogInterface dialog, int which) {9 X+ E* `' s" c( Z
                    if (!isLiveStreamManagerOn()) {% C5 q- _# D3 J/ S
                        return;3 q# P9 G* d7 x5 N
                    }* ^& {- `# j# k' C  H" h: B: P5 T- g
                    DJISDKManager.getInstance().getLiveStreamManager().stopStream();
    6 T- ~% w) N. ~& i; `7 [& v                showToast("结束推流");
    / v) h' P& F9 Z- m* e            }  _! N7 t" A/ \4 [  n8 p
            });
    # A2 G; z* s. H/ A( e0 n  V        Builder.setNegativeButton("取消", null);
    + }& B8 {4 R! U% K8 w. V        Builder.show();
    7 G. k' _3 N, e  V0 |: s$ y) M    }6 I! Z: H: U; Y. L% J2 y$ |
    4 y9 X3 G& P& U
        //获取飞机信息、云台信息
    ( M  a' _. }) L$ p$ ]    protected BroadcastReceiver mReceiver = new BroadcastReceiver() {1 C0 Y+ Z) B% s) x9 ~0 P$ ]
            @Override1 `# ~+ B8 `6 k8 P% Q2 c! E
            public void onReceive(Context context, Intent intent) {
    8 I. F+ i: d6 y* e& x            BaseProduct mProduct = ReceiverApplication.getProductInstance();, i+ [; \( i& r' h5 u- d7 x
                if (null != mProduct && mProduct.isConnected()) {
    $ X" y, n' Z1 e! ?* M/ t8 f% Z' B                flyInformation(mProduct);+ }( u4 ]5 i: g5 r( C; X, a" y  }
                    batteryInformation(mProduct);
    0 f) A% _! k1 r8 x                cameraInformation(mProduct);
    ' H" b1 M+ i( \, p+ c+ [) D                camera(mProduct);
    % K* {! w! R" M- N6 O6 i* b, v//                MobileRemote(mProduct);5 U( z3 W6 \" m1 V+ O' w
                }1 D" z% m3 s) Z0 l0 f8 f# @
            }! h" u5 Y4 g$ r1 \2 q0 j* x
        };
    0 z5 p" [1 ^0 B% g//    private void MobileRemote(BaseProduct mProduct) {
    1 l0 s: o7 [; B2 v% Y  P& d" |//        if (null != mProduct && mProduct.isConnected()) {
    - t8 R1 [1 A% o! p- H4 a+ a" W//            mobileController = ((Aircraft) mProduct).getMobileRemoteController();) x: Q8 U: @6 S
    //        }$ e8 x* `; N# I! h5 O. c/ _
    //    }# o$ t+ I0 X0 W# ]1 S4 _
        //获取飞机信息5 Y( c% U# `9 U, v. C( K, o
        private void flyInformation(BaseProduct mProduct) {, F- V% g7 a: J' z0 s
            if (null != mProduct && mProduct.isConnected()) {
      Z' ^. z/ a% u1 r, C6 J            controller = ((Aircraft) mProduct).getFlightController();/ G  `& A; x6 ~% V7 I+ A9 M. m
            }
    & j; q" Z+ R0 V6 U8 _- R! v9 ?        if (controller != null) {
    ' [, [' `" m/ ~! t4 Q! b0 s. u            controller.setStateCallback(new FlightControllerState.Callback() {
    1 y0 i( t6 R) }+ I1 Q                @RequiresApi(api = Build.VERSION_CODES.O)
    % ^; q. O! H4 F! M$ Q& ]                @Override, z) J% N0 l% x4 i9 m
                    public void onUpdate(@NonNull FlightControllerState flightControllerState) {
    0 Z. g+ U8 s4 A) {& P9 ?                    //纬度、经度、高度、俯仰角、滚转、偏航值、速度
    0 _* i% o% T5 D, r( V9 m" T7 J8 c                    lat = flightControllerState.getAircraftLocation().getLatitude();
    # H& m. O- d5 G0 A( l: |4 d0 Z                    lon = flightControllerState.getAircraftLocation().getLongitude();$ r8 y  t8 O3 g, I& V/ |/ N, d
                        high = flightControllerState.getAircraftLocation().getAltitude();6 u/ i  o9 I8 r3 e7 Z
                        attitude = flightControllerState.getAttitude();+ z- S9 {9 M4 E9 P# M. G" y
                        pitch = attitude.pitch;+ r' q# ?4 I  J
                        roll = attitude.roll;
    ; ^' ^9 I: V( _: ^0 G( ]                    yaw = attitude.yaw;. e; W6 v5 w+ Y* ~, ~; `
                        velocity_X = flightControllerState.getVelocityX();
    / o* J  _$ `( s! T' P. L+ o                    velocity_Y = flightControllerState.getVelocityY();
    # W: G- K, f/ F! O                    velocity_Z = flightControllerState.getVelocityZ();8 G# k+ o$ s4 z# F
                        isFlying = flightControllerState.isFlying();
    ( ?$ l4 H: r8 w5 {- t8 r! y                    //                    MyLog.d("经度:" + lat + ",纬度:" + lon + ",高度:" + high + ",角度:" + pitch + ",速度:" + velocity_X + "," + velocity_Y + "," + velocity_Z);" @, t( m2 n/ V- [, W
                    }/ F6 r0 g, d2 P8 d$ B+ D
                });
    ' n' b! Q  G# R0 G            controller.setVirtualStickAdvancedModeEnabled(true);0 A$ P9 J, g* u& U0 h  @+ K
                controller.setRollPitchCoordinateSystem(FlightCoordinateSystem.BODY);
      |% s/ P. n* G9 T6 R8 i            controller.setVerticalControlMode(VerticalControlMode.VELOCITY);2 r2 Q2 O5 i/ x' c
                controller.setRollPitchControlMode(RollPitchControlMode.VELOCITY);
    ; q* Z7 W$ [. `9 u+ Z: o            controller.setYawControlMode(YawControlMode.ANGULAR_VELOCITY);; p; c7 z) B% b; I! A! \/ x( X
    //            controller.setTerrainFollowModeEnabled(false, new CommonCallbacks.CompletionCallback() {- o3 Y4 |0 k* `, n% \
    //                @Override/ Q$ [! Z0 f% r  r1 W0 n4 d! g
    //                public void onResult(DJIError djiError) {+ C9 ^8 x4 P# Z% P, ?( b8 t" K( @0 q
    //                    MyLog.d(djiError.getDescription());
      j% r' @1 O4 c+ Y5 o1 _% @//                }( E% W# _0 j" s3 ^  ?
    //            });
    : g0 Z) ^. L: F! u//            controller.setTripodModeEnabled(false, new CommonCallbacks.CompletionCallback() {( n4 }9 T) o% K, I2 e0 B# h! D
    //                @Override
    ) o" S3 ^1 w" ~9 i/ Y//                public void onResult(DJIError djiError) {6 z* a2 S& s2 c* {0 A3 O0 ^" o
    //                    MyLog.d(djiError.getDescription());
    9 |  l, M1 z' p6 x/ u( _//                }' e$ a4 O6 S, [6 U1 r) u. T5 L- _! f
    //            });$ J- C1 |# L5 v
    //            controller.setFlightOrientationMode(FlightOrientationMode.AIRCRAFT_HEADING, new CommonCallbacks.CompletionCallback() {
    1 q/ Q" N* m& _: Q3 {1 u0 w//                @Override
    3 t' {" f5 C6 H/ a  R//                public void onResult(DJIError djiError) {
    3 s7 ^6 U, F8 ?//                    MyLog.d(djiError.getDescription());1 E% ]' B$ k9 l- u6 S6 X& M/ @2 y
    //                    if (djiError==null){1 ?1 t/ p- B/ h% ^, T
    //                        if (controller.isVirtualStickControlModeAvailable()){5 A8 J. E) r8 g4 ], Y
    //
    0 K/ @8 V* H! A//                        }else {
    ! p, }6 J( |4 j) g  |0 X" _' I//                            MyLog.d("虚拟摇杆模式不可用");
    0 x  w8 {4 _' L3 @  O& ?$ s9 N//                        }
    / N) G& A6 e5 n2 K//                    }
    # v: }% d9 S$ c& }//                }
    1 c) i& t" s5 Q. @0 X5 B9 v  S//            });
    . s! E- F9 \6 N% S  [7 X        }/ @8 H6 C! F% d- B/ D% u% K7 w+ _4 j
        }
    2 K7 p4 a8 q/ V) e; }* W( D    //电池信息" F4 w9 b4 u, m8 r/ |, u
        private void batteryInformation(BaseProduct mProduct) {. }8 b3 O6 C$ \
            if (null != mProduct && mProduct.isConnected()) {
    3 c" S) Z% }0 F            battery = ((Aircraft) mProduct).getBattery();
    ( j: b8 ~5 B9 H6 Z        }
    9 ]- S6 x, x  t9 ^        if (battery != null) {
    3 @. m( D( d4 H, k            battery.setStateCallback(new BatteryState.Callback() {
    4 \! y* N, s; Y* H( |                @Override
    8 F' e: m  g) I/ y/ p2 V$ l* }8 n2 B; S                public void onUpdate(BatteryState batteryState) {. e6 r7 v8 H' a3 r  q
                        //电池电量) z3 U) y# v% a5 C
                        power = batteryState.getChargeRemainingInPercent();
    ' x8 l' ~) W) d5 E# D1 ?. j                    //电池温度
    8 ^% o9 g8 X- U- [+ E" z+ w                    temperature = batteryState.getTemperature();( B6 j/ G7 K, Q! B/ a# ~
                    }
    5 Z( R- a. x" e4 i) X* O$ w            });0 ^8 r% o: C/ p, E
            }
    0 @/ @( ~" h' Y; I$ t5 L) k    }
    8 _% ^, I* \1 w$ T    //云台信息6 z- v0 n1 p% U8 ]( _8 g
        private void cameraInformation(BaseProduct mProduct) {3 }9 f; c& `0 i1 `9 H% ^4 s( |8 d  h
            if (null != mProduct && mProduct.isConnected()) {
    + `7 y& Q, t2 |- u# ~            gimbal = ((Aircraft) mProduct).getGimbal();
    + B: s( P( U4 g- M; X5 m        }1 v+ i4 j0 x5 _/ x4 ^
            if (gimbal != null) {
    9 Y7 v- i! z  h; k5 o            gimbal.setMode(GimbalMode.YAW_FOLLOW, null);0 q1 w7 ]: J) n: l7 K! O8 L4 X
                gimbal.setStateCallback(new GimbalState.Callback() {
    5 E; O+ T* P& I" W3 Z% Z  ]" j- l! o                @Override* p3 J7 P3 \+ T% N
                    public void onUpdate(@NonNull GimbalState gimbalState) {
    : Q8 o( @4 W! d0 z. D                    //俯仰角、滚转、偏航值2 e- b8 i& b2 M
                        g_attitude = gimbalState.getAttitudeInDegrees();
    - w! O& T  M; _  x                    g_pitch = g_attitude.getPitch();( H3 B, a& G' F; W; k
                        g_roll = g_attitude.getRoll();
    7 b% Z3 Q$ p) K# q) P# k8 o                    g_yaw = g_attitude.getYaw();* F; \3 V# S% i! a
                    }" H  }2 H+ q9 ^. H
                });
    3 v! g5 C5 ^) u- Y* n% ]4 r' N        }8 R2 }/ J& z, D1 [
        }6 |1 x  A) ^; A9 B
        private void camera(BaseProduct mProduct) {! N' H& L0 ?5 K1 h, d! M8 ~+ K
            if (null != mProduct && mProduct.isConnected()) {+ r8 T" G3 Y' i( Q. Q7 p2 d5 d
                camera = ((Aircraft) mProduct).getCamera();( w3 ?7 _0 Y; c& G" }" _4 j
            }
    * A; I! R9 }4 q6 |4 B        if (camera != null) {
    & N0 e& Z8 `9 C            //            camera.setVideoCaptionEnabled(true, new CommonCallbacks.CompletionCallback() {$ M. n  ]  r6 P7 J
                //                @Override' W3 M& G+ J( s8 F: U  Y
                //                public void onResult(DJIError djiError) {* v/ M% v- g# O
                //                    MyLog.d("VideoCaptionEnabled"+djiError.toString());$ I( y- t. H$ J
                //                }
    8 P. y. _, ?$ D' C: W            //            });
    % y  \4 q% T5 ~: e            //            camera.setMediaFileCustomInformation(projectId +","+trajectoryId, new CommonCallbacks.CompletionCallback() {' |3 m4 `1 l, I5 M; F
                //                @Override9 b( Z/ A. L. e: {
                //                public void onResult(DJIError djiError) {
    ) b% `$ o3 c# \) n: G7 n2 F            //                    MyLog.d("自定义信息:"+djiError.toString());
    - _' W6 @5 P) X9 A: \+ z$ `) C            //                }
    ' u8 V! U" l4 P; e' E4 [            //            });
    - Y$ G3 c  r  Y4 E$ u$ \5 w            camera.setSystemStateCallback(new SystemState.Callback() {
    " r6 L1 Z4 R: P, Z                @RequiresApi(api = Build.VERSION_CODES.O)! T! A3 j: L0 ?; j; k1 `# K+ u
                    @Override5 \; ]2 r; o7 n/ o& {' w
                    public void onUpdate(@NonNull SystemState systemState) {) D4 h! a9 ^2 d3 M. C
                        if (systemState.getMode().equals(SettingsDefinitions.CameraMode.SHOOT_PHOTO)) {
    ( |! i# f) f( o- R5 P% S. M                        if (systemState.isStoringPhoto()) {. G4 g% [( H$ ]+ T& k
                                dateStr = Long.toString(System.currentTimeMillis());4 Z: b5 e2 ]0 ]5 q+ ?% |
                                list.add(new DeviceInfo(dateStr, lat, lon, high, pitch, roll, yaw, velocity_X, velocity_Y, velocity_Z, g_yaw, g_roll, g_pitch));. P+ N5 @; S3 {* y$ x
                                CsvWriter.getInstance(",", "UTF-8").writeDataToFile(list, FileUtil.checkDirPath(FLY_FILE_PATH + "/照片数据") + "/" + DateUtils.getCurrentDates() + ".csv");& Q0 X  Z6 l8 r; c' f: {! j' B
                                list.clear();  C, [) D( c9 s0 m5 R; C' s6 f( c4 v
                                return;4 ]) @# x/ n. u  f* _4 D; p
                            }' i7 k; x+ }  R, u
                        } else if (systemState.getMode().equals(SettingsDefinitions.CameraMode.RECORD_VIDEO)) {  m0 o! p) {! \" g
                            if (systemState.isRecording()) {& i; [/ D9 `5 V/ R5 w* O
                                try {7 R4 L0 ?5 |- G8 E+ w9 `2 [
                                    dateStr = Long.toString(System.currentTimeMillis());
      `7 E% s) `* C7 ~                                list.add(new DeviceInfo(dateStr, lat, lon, high, pitch, roll, yaw, velocity_X, velocity_Y, velocity_Z, g_yaw, g_roll, g_pitch));* {& A$ I8 C  a; |$ a/ S% t$ u
                                    getList.add(dateStr);
    3 H, U% P5 h0 l1 ?+ ^                                Thread.sleep(100);
    6 q1 A: a2 q  i- X9 z# k& \. S                            } catch (InterruptedException e) {4 E) N: L" L( w8 j; o( W; e
                                    e.printStackTrace();
    + Y$ O1 r% C1 m1 Y3 T. _                            }
    ' Y! d1 n0 D/ L' g. A: P1 i                        } else {
      Z* z& v1 J  k. V. F                            if (list.size() > 1) {2 H/ }  S0 Q: M$ ]/ T
                                    posName = DateUtils.getCurrentDates() + ".csv";1 J0 M: c* b9 s5 w/ }. J& ]
                                    CsvWriter.getInstance(",", "UTF-8").writeDataToFile(list, FileUtil.checkDirPath(FLY_FILE_PATH + "/视频数据") + "/" + posName);
    0 ~8 t% k5 a- ?/ r; E" q- m8 F                                list.clear();) y; O6 n3 T0 p2 r$ C2 D
                                    runOnUiThread(new Runnable() {2 n# o6 q7 f$ d* V! i$ Q
                                        @Override
    ! g/ s. F( x5 I, m4 O3 K8 B- J                                    public void run() {
    : [; f0 ]( ~& x! P& A/ u                                        getFileList("end");
    - y. Y7 J0 L9 E; ?" x$ k0 B                                    }: J7 x! u" C! g, m  Z1 v
                                    });, @0 h! A/ Z$ Z- R: [8 ]
                                }
    * z- Q* j  J! ^+ V8 _6 b                        }( p+ ~% J3 _3 {# F1 t
                        }
    3 E1 U) m" ~) c                }
    7 _& J" ~1 h7 b0 A8 v3 Z            });
    / m+ w) P% R4 n, U8 b( [        }
    1 I) k: z  b0 V8 T    }! e; D* |% o" e( d
        //遥控器信息1 }4 k0 e" T3 z" Q
        private void handheldInforamation(BaseProduct mProduct) {
    * V6 w' @+ D% G3 s' Y+ @- G; M        if (null != mProduct && mProduct.isConnected()) {
    ! b5 w: Y! P- T6 G+ ]7 ~            handheldController = ((HandHeld) mProduct).getHandHeldController();
    ' P) `* j* v( U- v- n& P. z        }7 s2 ?' `+ E/ X; f; x4 G+ ^
            if (handheldController != null) {# J! @7 e/ _! z# ~% i4 Z' a
                handheldController.setPowerModeCallback(new PowerMode.Callback() {
    4 p0 O3 }: |) Q" J' L                @Override9 A! Q" X/ f$ `1 c0 Y3 P
                    public void onUpdate(PowerMode powerMode) {
    ; U3 J9 n# x9 [                    switch (powerMode) {
    . S  M' x9 E. X4 z                        case ON:
    # @* N$ ^: q0 \9 v' {! n$ [9 y1 o                            Battery battery = ((HandHeld) mProduct).getBattery();
    ) x# z) j' H5 k; F& e                            battery.setStateCallback(new BatteryState.Callback() {0 m# k4 K: d! d& N% Z& C3 g# b
                                    @Override* Y( Z9 v! y. }% ]& T
                                    public void onUpdate(BatteryState batteryState) {# w! i. _# I+ b+ t) J
                                        h_power = batteryState.getChargeRemainingInPercent();
    0 a3 V, K8 I4 a/ Q6 p4 u& q                                }) }3 ]- k! O. ^) V: N
                                });+ d8 [7 i2 y* ~( o2 ?3 l3 `! f5 S; N
                                break;5 e* c1 @5 e) }0 l
                        }5 U4 z0 @3 ?- N1 i5 t1 s6 F) U3 N7 P
                    }, M- O. B. n1 Q/ M3 Q
                });& Z* V7 k" [5 b0 E
            }0 \% _  A1 _2 c4 L* e" U5 q
        }
    ( A% i8 M! N; |   5 O, V) C& D( h, H
        @Override
    9 M/ l1 d2 C/ ]$ o/ q    public boolean onKeyDown(int keyCode, KeyEvent event) {
    6 v9 l# `6 v) Z$ Z        if (keyCode == KeyEvent.KEYCODE_BACK
    , e+ ]1 m. E! T- [8 V                && event.getAction() == KeyEvent.ACTION_DOWN) {
    4 a& L- Z- N2 a6 {( O//                        closeConnect();" L9 Y" u/ z$ Q+ C  w
                MainActivity.this.finish();
    5 V( M3 p7 P8 ]6 V% C        }  m  \5 d' l0 M/ t( @+ R
            return super.onKeyDown(keyCode, event);$ G! b5 Q! w2 H& L
        }1 x+ L& S! `: F/ j& g
    }5 s$ j# m2 k, j- x3 L
    完成后界面如下所示:- X' w0 a1 L* b8 O) D

    rndxjmine2a64023083406.jpg

    rndxjmine2a64023083406.jpg

    ! e# i) x0 K2 ~/ t  u上面的工作完成后就可以在无人且宽阔的地方进行无人机飞行了。$ @/ o4 w( K" d+ u8 s: ^) p/ [
    40 ~/ f- i: |* V
    多媒体资源的操作; \% ]; R2 b& o5 e0 Y
    多媒体文件操作,主要为多媒体文件的获取、查看、删除、下载的操作. }5 l0 D6 z# R7 O8 w
    同样创建多媒体功能文件FileManagementActivity及activity_file_management.xml$ a4 A; Q( `# b* J9 @7 ]
    activity_file_management.xml
    . R$ @: J* t, y& W5 T6 U. O( vLinearLayout xmlns:android="http://schemas.android.com/apk/res/android"9 }5 S9 u3 Q1 z* _; g* y- K/ N
        xmlns:tools="http://schemas.android.com/tools"
    ( E+ m2 ?( ?: w: L: y2 K9 m    android:layout_width="match_parent"/ Y1 a3 J( M$ B" {3 r. p' R
        android:layout_height="match_parent"
    2 w; C! [; k8 o, E9 S1 [- r    xmlns:custom="http://schemas.android.com/apk/res-auto"
    1 C0 u1 Q) E) b6 @/ |8 N, h# P    tools:context=".ui.FileManagementActivity"
    5 v% J1 b( V  Y8 u6 F    android:orientation="vertical"
    1 Q. y1 C1 [7 _' Q5 {    android:background="@drawable/shape_corner_eight">
    - a1 w# r  P6 Y# ]! e% T7 T    include layout="@layout/activity_toolbar"
    ; e9 I$ X( z, T! i; }        android:id="@+id/layout_file">include>
    2 Y/ }" b( D3 a+ x4 u% ~: E" [0 U    LinearLayout
    5 v+ i4 n% m) c; A+ F6 D$ E, _        android:layout_width="match_parent". ~# k% B) B" _6 Y6 @1 d' p7 x6 `
            android:layout_height="match_parent"  u% J, A9 C- r& }. O
            android:orientation="horizontal">% \! l, q2 x+ q, @
            LinearLayout+ r' l) Y% L  i. {* l
                android:layout_width="250dp"+ W, X" G1 G- Q9 F+ b( ^
                android:layout_height="match_parent"# C9 m. P/ d% w/ \4 t! Z; x
                android:orientation="vertical"
    ' Y% T* ]) @8 y  r* ?& p8 [- v            android:layout_marginLeft="15dp", u8 S+ K+ ^0 U4 \1 A1 M; p6 v
                android:layout_marginRight="15dp">
    - @! ~6 w& ?# g% Z            RadioGroup6 s! R5 |) l, Q% }* L
                    android:id="@+id/rg_file_management"
    " \) N# u# l; ]" K( T$ y# x                android:layout_width="match_parent"3 A. h7 U5 S1 T" {) B, M4 b
                    android:layout_height="40dp"7 T' ^/ B9 {2 h4 K5 z% `
                    android:orientation="horizontal"1 k! W1 Z* u3 W4 z& r
                    android:background="#2B3141"3 R% W: u* Z- L5 J
                    android:gravity="center">
    8 Q1 A' g0 F; _5 T" v                RadioButton* e# P5 [  Q6 W9 t1 a% A
                        android:id="@+id/rb_file_all"
    / v) |% d) w% x* q! I" O  v/ r# C                    android:layout_width="0dp"  H. H5 r9 P# S" j7 Q; O# W3 y
                        android:layout_height="match_parent". N( i3 `2 p! M4 l% `
                        android:layout_weight="1"
    , a' B# f7 i  c# u! b                    android:button="@null"2 s, Q$ i  X! ]" v0 ]
                        android:checked="true"
    ) `  ]& t  h7 u3 ?! M/ d                    android:gravity="center"
    5 Y; g: z0 E6 k- _. {                    android:text="全部"7 _2 m7 \* m; }( R
                        android:textColor="@drawable/nav_item_color_selector"% z. p. Z5 H, P2 S: [
                        android:textSize="18sp": [. U. D& d, f- x3 B
                        tools:ignore="TouchTargetSizeCheck">RadioButton>
    % [5 V: ]$ ?9 B. ^                RadioButton! w8 _' [6 a1 p& T6 }$ R; R4 \
                        android:id="@+id/rb_file_photo"; i  ?2 P5 j+ T
                        android:layout_width="0dp"
    : m1 W& R1 x8 @2 W5 u                    android:layout_height="match_parent"
    $ i7 v  d. Y5 Y9 q. e$ `; r8 q6 Y9 a% ^                    android:layout_weight="1"
    ! d1 @' M" @& w  h# k  [                    android:button="@null"9 I5 n, I8 L, D* c/ q; Y
                        android:gravity="center"
    5 _; A" [3 j: e% I# \1 a8 ~                    android:text="照片"
    4 s' g" ^" r* z                    android:textColor="@drawable/nav_item_color_selector"+ J& s4 R; z8 K" I# Z
                        android:textSize="18sp"
    % F* h& k: J8 S1 n$ A/ W7 |- f                    tools:ignore="TouchTargetSizeCheck">RadioButton>3 }! x5 y* \7 t6 S. O) _9 O9 h8 |
                    RadioButton
    * d( s) y9 _' b; I$ {4 ]                    android:id="@+id/rb_file_video"
    ! T2 m% m- C, X                    android:layout_width="0dp"
    ! w5 E8 R4 J+ x' T7 J                    android:layout_height="match_parent"
    . n; `# N  K6 d6 u" T/ U* e                    android:layout_weight="1"
    ! I' i; f2 ^) d/ D  X, h: j/ u                    android:button="@null"
    / E8 q5 E" W. t! {5 `7 q3 G                    android:gravity="center"1 A9 L6 X2 ~( [4 ^$ x( {) D
                        android:text="视频"3 n, b8 n0 L6 i# K6 V2 a& E0 q
                        android:textColor="@drawable/nav_item_color_selector"
    ' y- R9 U# ]$ g, M* C* q- p                    android:textSize="18sp"
    ; m' q$ S' t3 \  s+ ]3 d  t: D                    tools:ignore="TouchTargetSizeCheck">RadioButton>8 p2 h* u" w1 z
                RadioGroup>
    " j8 [" M! H  n7 v: B; D7 K            androidx.recyclerview.widget.RecyclerView
    * w" \5 s& F% H& Q' P# [                android:id="@+id/rv_file_management"# T' A6 h8 X) |  A. F" v7 c9 k' m
                    android:layout_width="match_parent"
    & _2 e! A8 f/ I                android:layout_height="0dp"
    ; }% e% E' G9 ^                android:layout_weight="1"
    " z! S# Q; t$ p7 Z1 B  a. ?                android:layout_marginTop="10dp">androidx.recyclerview.widget.RecyclerView>
    6 c4 F; P6 B# A; h8 T        LinearLayout>
    % K# x4 r9 m2 y( {5 u3 @! X- n        RelativeLayout
    0 S; N7 l( i) J* \            android:layout_width="0dp"
    * c' p8 C- V& S# O$ N- d4 X            android:layout_weight="2"
    9 J# ]3 h3 E  o& B/ k$ r            android:layout_height="match_parent">
    , I# E& P% e$ ]$ Q            RelativeLayout
    3 r: {5 ]/ c6 c  _- {2 B7 X                android:layout_width="match_parent"% D3 y! v8 r8 I" h6 O, E7 a
                    android:layout_height="match_parent">/ }! o4 W# Z0 U- \5 r; e* y
                    dji.ux.widget.FPVWidget) ]+ _% j* ]2 p* I  a
                        android:id="@+id/FPVWidget"
    0 E5 D0 M' P) S+ W. t                    android:layout_width="match_parent"
    " w0 |2 w9 B" ^8 D                    android:layout_height="match_parent"* O& a6 X, l) T, Y0 c0 u! O
                        android:layout_centerInParent="true"
    0 C6 [7 ^5 y, @. N' W2 g                    custom:sourceCameraNameVisibility="false" />6 V6 E' c+ k! Q: R) I2 E+ G" I3 C1 T
                RelativeLayout>
    9 N  u& h, I! x' n% W4 v            ImageView
    4 s- f1 d) d+ [4 \2 B8 Q                android:id="@+id/img_show"
    " C5 A5 l6 P  C" Y  l2 h  M  T                android:layout_width="match_parent"
    - W$ M$ m4 e6 N) ?! z/ N2 B                android:layout_height="match_parent"
    " M3 s2 v! [$ W/ h                android:scaleType="fitXY"
    " u+ L' f0 b3 M- c" M: n! u                android:visibility="invisible">ImageView>/ [( ^7 O2 S+ Y
                LinearLayout& m+ D9 o. L" m" v: x
                    android:id="@+id/ll_video_btn"
    - `& }! z" U2 ~                android:layout_width="match_parent"7 x$ E" S- O4 O) u* g
                    android:layout_height="50dp"' ~% e& t# \" o% D# q2 ^' Z
                    android:orientation="horizontal", ~# A3 g+ n3 c* g( t$ ?
                    android:gravity="center"
      |+ U5 S$ g% V% N3 M( u- G* G                android:layout_marginBottom="15dp"
    ( W* Z  y8 y& m3 U& S: t3 q" G                android:layout_alignParentBottom="true"
    ' V5 F8 m5 Z5 m! d) |/ p* {) [                android:visibility="gone">1 `/ f- A( c' I& s2 Z. A. D
                    ImageView
    - |- a( q% c' l# I- t6 t; m                    android:id="@+id/img_video_pause"( i- l/ |; h% J
                        android:layout_width="35dp"/ F$ i8 B  d% n, L9 G) R
                        android:layout_height="35dp"
    - u, h& X) c; x3 J  u* g8 P                    android:src="@drawable/background_stop_selector">ImageView>: \" ?4 p& v7 D9 P5 D
                    ImageView
    ! ]# @2 o1 b2 [                    android:id="@+id/img_video_play"
    ' a  s+ F. x3 x                    android:layout_width="45dp"  m+ q+ d1 l: o2 l% S
                        android:layout_height="45dp"
    % {0 ]+ i, o# g) p2 e                    android:layout_marginLeft="20dp"
    & x) v. k7 g. n6 o1 ~                    android:src="@drawable/background_palyer_selector">ImageView>
    * ?- A# f" z1 ]( {                ImageView3 O+ G  \8 H* b/ d
                        android:id="@+id/img_video_stop"- C7 d0 I9 |  X1 N  m
                        android:layout_width="35dp"
    6 U, `( a1 \* ^" S                    android:layout_height="35dp"
    3 j' Q% C  f) |/ ~0 ?                    android:layout_marginLeft="20dp"3 `9 l2 \$ g7 ^" ^8 _
                        android:src="@mipmap/ic_reset_36dp">ImageView>& e5 j0 n1 Z. u4 ?6 _; n
                LinearLayout>
    / z" w& m5 o1 _& P) B        RelativeLayout>, G/ v3 t0 i! e  q, `3 c' l, H8 G
        LinearLayout>4 G, {0 Z, T8 B
    LinearLayout>4 D7 G  [- J) {& y! s  v
    FileManagementActivity
    7 g) M2 B; l5 y! @) `; P  k@Layout(R.layout.activity_file_management)( o) b. }; C& m8 G. A% Y! z* Y
    public class FileManagementActivity extends BaseActivity implements View.OnClickListener {5 p9 ^: S* C& U8 g
        private static final String TAG = FileManagementActivity.class.getName();" B( T1 p! o9 v/ D
        @BindView(R.id.layout_file)
    7 i) _. `4 Z" S    View mViewLayoutToolbar;
    # V- D; `3 @/ W0 H& O5 P. h. K5 B    @BindView(R.id.tv_toolbar_title)/ r3 u0 h' G5 S  x' ?; w; b9 o
        TextView mTextViewToolbarTitle;
    * L! m  V9 T! S9 l* h1 Y/ z! C    @BindView(R.id.ll_file)
    ) x+ ^- e& q2 r0 `9 g  ~6 Z5 T    LinearLayout mLinearLayout;$ n9 K" k0 M! }  Z
        @BindView(R.id.rg_file_management)2 S/ _  e" O" r2 A' s& {' q
        RadioGroup mRadioGroup;
    * B3 a2 `) P$ a% i# f5 B    @BindView(R.id.rv_file_management)
    ( m8 b2 d/ h, Z    RecyclerView mRecyclerView;! j3 S5 c0 F( ~0 G
        @BindView(R.id.img_show)
      q5 `- c" q/ @# K  C. w    ImageView mImageView;/ D6 B0 j& \: [
        @BindView(R.id.ll_video_btn)
    . Z% A6 b9 S. R9 g0 z    LinearLayout mLinearLayoutVideo;  _2 f- I3 M$ d
        @BindView(R.id.img_video_play)* j. t  {8 ~1 c2 ?. H7 g
        ImageView mImageViewVideoPlay;
    2 D; S4 i$ n* A1 d7 Y    @BindView(R.id.img_video_pause)
    5 y2 ?& K- ]# ]" }/ n, ]) B    ImageView mImageViewVideoPause;9 F6 O" X4 ?& q- v; p9 e
        private FileListAdapter mListAdapter;) o0 M  u( `9 b% X3 t. F" s
        private List List = new ArrayList();9 n5 T& u3 @' u- y* {
        private List mediaFileList = new ArrayList();
    $ t1 |2 G, S- @3 \    private MediaManager mMediaManager;# H; u0 ?: k! T2 d1 w9 e5 B
        private MediaManager.FileListState currentFileListState = MediaManager.FileListState.UNKNOWN;0 B1 [) \/ _# l7 Z8 w; a
        private MediaManager.VideoPlaybackState state;2 j: z/ L5 I' U9 O/ T
        private ProgressDialog mLoadingDialog;7 f8 N0 h, Q1 F* k' L: A& ~" c5 ^" z
        private ProgressDialog mDownloadDialog;
    $ q& l( Y! ?8 F3 o    private FetchMediaTaskScheduler scheduler;
    ; @& p# b6 O3 B' f3 p9 \    private int lastClickViewIndex = -1;9 D( ^. \1 Y4 ?$ J% W5 t/ z' V
        private int currentProgress = -1;+ O+ \* q" J$ ]( B: f# u" {
        private String SavePath = "";
    4 ]* D, h- z" f) {: \! t" \; E' Q    private View lastClickView;
    ; \% z- f1 _9 J4 B9 A, ^. C7 b    private boolean isResume = false;4 p/ p9 F% O/ X" ~7 I$ s  q
        private SFTPUtils sftp;
    7 i5 |) T+ ~/ l4 g# X0 l! T    private SettingsDefinitions.StorageLocation storageLocation;
    , [) T$ Q! ?9 s* n    @Override$ o) \; J/ b9 }4 d7 q- s5 c* b
        public void initViews() {& O7 A( V' M. R0 |# z
            mLinearLayout.setVisibility(View.VISIBLE);
    # e+ Q. e3 S, U- r. ]5 K- l        mTextViewToolbarTitle.setText("文件管理");( q6 b9 N  {8 _
            mImageViewVideoPlay.setEnabled(true);; l1 N: A4 S$ c( T9 a/ R
            mImageViewVideoPause.setEnabled(false);
    4 b7 `( _4 l' W/ Z7 v' R        mRadioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
    8 ], D( H' i+ S. k            @Override; U1 w: b8 e. a2 P  y9 M8 s1 C( o
                public void onCheckedChanged(RadioGroup group, int checkedId) {: s2 A# I$ a! J) X7 W- h
                    List.clear();6 F, l0 @, c! j- K) B# H* v9 J$ ?
                    mediaFileList.clear();: }1 p; n. |' I7 }; I5 V
                    switch (checkedId) {
    4 j- a9 D; v3 `; o                    case R.id.rb_file_all:% _; I5 G; D) R3 X1 A
                            getFileList(0);" x, G# y0 M6 w8 m) q
                            mListAdapter.notifyDataSetChanged();
    1 Y6 F+ y. X" W6 M                        break;  q/ y8 w6 X, p3 h3 k
                        case R.id.rb_file_photo:5 a2 j4 e0 V* O6 u; U# a
                            getFileList(1);
    % @* ^: l+ w8 \                        mListAdapter.notifyDataSetChanged();* w0 \5 V- R! ^/ @2 P5 M  ]% V
                            break;1 Q9 S- N) }) S+ Y1 v$ Q" v: f
                        case R.id.rb_file_video:
    . r2 |+ D3 `" G; ?% c3 H  C                        getFileList(2);- Q- _! o5 W; n+ o+ D
                            mListAdapter.notifyDataSetChanged();
    ) v9 }# B4 I% S0 E0 B                        break;4 `7 \% X# H8 f! `
                    }
    ' n. z! q4 I; m            }! N' L$ X7 g2 H  b, o& f9 Z
            });
    1 n, ~2 s' Y9 D6 `& v& L4 n- s  e        LinearLayoutManager layoutManager = new LinearLayoutManager(FileManagementActivity.this, RecyclerView.VERTICAL, false);! Y% X9 I1 z4 L2 G4 l1 n* I" r+ m
            mRecyclerView.setLayoutManager(layoutManager);
    ! F+ }0 S' H3 |, ?0 w6 k2 K7 v  `        //Init FileListAdapter
    3 ?0 D% h  e. i3 D        mListAdapter = new FileListAdapter();
    2 k3 j: g6 Y' W6 M: L        mRecyclerView.setAdapter(mListAdapter);) N, ~3 \1 K& R1 y; @! y
            //Init Loading Dialog  Q2 r( H2 ?" o3 S; F
            mLoadingDialog = new ProgressDialog(FileManagementActivity.this);
    9 g- \9 T5 p# T8 K) Y" ~        mLoadingDialog.setMessage("请等待...");
    . g: G6 i6 R( p* v9 _- |/ ~        mLoadingDialog.setCanceledOnTouchOutside(false);" T1 M5 [6 ?' B+ C6 C% y0 Q
            mLoadingDialog.setCancelable(false);
    + q' E3 l; o& b4 C- q& U        //Init Download Dialog- n9 F! |1 Q% \# F
            mDownloadDialog = new ProgressDialog(FileManagementActivity.this);1 a  \6 ?8 N# J" R, ?7 R! e8 t
            mDownloadDialog.setTitle("下载中...");
    4 F" D$ k" ^! Q        mDownloadDialog.setIcon(android.R.drawable.ic_dialog_info);& I4 @5 X8 Z% c, L$ d
            mDownloadDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
    " k' n) A, q( f0 [        mDownloadDialog.setCanceledOnTouchOutside(false);) }5 ^# M# X9 \
            mDownloadDialog.setCancelable(true);
    # m  O6 D/ W) k3 T! f7 c* q        mDownloadDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {7 j( }; Q& E0 @  b- X7 n/ \
                @Override" e6 w3 o0 g1 S9 l4 f
                public void onCancel(DialogInterface dialog) {: m* I$ V$ I; O- v
                    if (mMediaManager != null) {' g( k  t' c  q3 K9 N7 O4 v
                        mMediaManager.exitMediaDownloading();
    $ v1 p+ a) h$ d0 I8 b                }/ h% m9 P+ N! v. U
                }) y' c( Y# p; X+ X+ c! ]
            });1 S1 A  V/ q! }3 m
            sftp = new SFTPUtils("49.4.79.249","uav","uavHHch@YREC.cn");
    + z+ V! o' X. X; N4 E$ T+ S" [2 a8 _        ReceiverApplication.getAircraftInstance().getCamera().setStorageStateCallBack(new StorageState.Callback() {4 A1 y6 H& m; r: O
                @Override
    ! J1 h* X9 d* h+ A4 [+ g* p& n            public void onUpdate(@NonNull @NotNull StorageState storageState) {
    ( O$ h, u5 ^8 c& d. @$ N                if(storageState.isInserted()) {3 m  Z% w+ V2 I' [
                        storageLocation = SettingsDefinitions.StorageLocation.SDCARD;# y; }# x3 a( [% ^
                        ReceiverApplication.getAircraftInstance().getCamera().setStorageLocation(SettingsDefinitions.StorageLocation.SDCARD, new CommonCallbacks.CompletionCallback() {
    5 `8 H" k/ a$ o+ X2 _6 `, i                        @Override: [( W, b* V" |9 f) a
                            public void onResult(DJIError djiError) {, J) `4 j" R) k+ M: u5 g8 Y
                            }& Z1 H3 o7 R5 B( c# ?, z& h
                        });
      P+ }  F! V2 {# _7 G; r+ d# v                } else {- N" U1 t& A) s' X+ J/ d6 ?
                        storageLocation = SettingsDefinitions.StorageLocation.INTERNAL_STORAGE;+ }' c$ `8 O. n. g, m4 H
                        ReceiverApplication.getAircraftInstance().getCamera().setStorageLocation(SettingsDefinitions.StorageLocation.INTERNAL_STORAGE, new CommonCallbacks.CompletionCallback() {: R3 K% S, p( r. O
                            @Override- b4 _, c# M' z8 S! \! H. {
                            public void onResult(DJIError djiError) {
    7 X. P3 T  F3 K! n0 z: `7 u6 l; b                        }$ z  ~! m$ T4 ^
                        });
    9 J! F, ?+ H# u1 \5 ^3 p0 u' M! v: W                }
    4 Q; e$ Z# O5 J/ E: n% W, S            }- Z  y& U" J/ r6 K8 D7 z9 ^
            });9 a6 G/ U; G9 Y# x
        }
    3 S' Z7 G* U+ ~3 a$ F) ^7 V* Z    @Override7 z6 k- U9 E) j) d1 u4 z
        public void initDatas() {
    3 d) h1 [) f7 e/ |0 v- p    }
    9 w9 L! N, p( K3 _* J    @Override
    5 ]% f% n, r! ^+ V    protected void requestData() {
    " c8 I/ a6 n: w# r$ G; |7 a    }
    2 s, G8 D7 _9 l. q4 r- k" P5 G    @Override
    ; X! F2 c7 w- K8 H* Q1 i9 m4 `1 f    public void onComplete(String url, String jsonStr) {; _- _6 C5 W& x  B- D
            super.onComplete(url, jsonStr);0 {! V2 f* j& T2 d# {) t* m$ C, y9 W
            switch (url){
    ) |2 M" T$ }& q% m/ I4 ^0 B$ a- F            case POST_VIDEO_INFO:5 o* a' f# Z: t# F& F" f* ]
                    break;7 w& e. A4 d% t; w
                default:) M/ X# A  G2 o+ a. s6 {3 ~
                    getVideoJson(jsonStr);
    8 h6 ^2 e& g2 I0 z5 ~+ C                break;5 F% n6 c+ `' ^. U4 Z
            }# G3 n) q  u0 Q/ Z
        }. N$ I0 O+ k; u4 o
        private void getVideoJson(String jsonStr) {4 h/ Y# P$ b, K& B
            VideoModule module = GsonUtil.GsonToBean(jsonStr,VideoModule.class);. m8 @" d7 h9 D2 d
            if (module.getCode() == 200 && module.getRows().size() == 1){7 ?9 u) h! k: g5 I7 T
                runOnUiThread(new Runnable() {
    9 g5 i& Q9 C$ J( F- o/ P  f- f                @Override
    ( e& z# m! M2 c, _/ a                public void run() {
    * D) f, `+ W$ @# m# O                    UpdateFileModule fileModule = new UpdateFileModule(module.getRows().get(0).getId(),"/mnt/uavFtpFolder/"+module.getRows().get(0).getFileName());
    7 ~7 Q5 f  M% N3 A- [9 D# M- j                    http.getHttp(POST_VIDEO_INFO,"PUT",GsonUtil.GsonString(fileModule));
    ( J: l# G0 r3 b3 _  `                }8 c) h2 ^$ s" t
                });
    - r1 k+ \# H* z4 U6 [        }- n4 a* |/ U  @  x' V0 Y0 I+ t/ T
        }
    2 n; {) e9 S# B    @Override
    " y+ T# X0 n& r* G  z2 L    protected void onResume() {1 Z" r" s( {/ q( @3 o9 v5 B+ }
            super.onResume();
    5 {4 O2 s' ~6 v$ g        initMediaManager();$ u, V# b8 [) _  O6 @" I
        }
    + n1 ]) l! W& N; ^    @Override
    ! }9 x9 J3 D. f4 I/ W/ s: r: l- w6 T    protected void onPause() {; X: ]- f$ H7 x
            super.onPause();
    " I5 i& w1 |+ t, }    }
    6 m& `7 U  \3 O7 W    @Override) K  F" d0 C5 F/ `% Q+ m
        protected void onStop() {7 @) `  y0 Q- B4 ?. B6 G
            super.onStop();
    : N' R5 G! F0 Z! f    }
    ) c& D! M" W$ A. r) z/ R3 ~4 {
    , z9 K& i& ]/ t    @Override
    - ?" D6 h$ a9 i+ R9 w% u/ r# K    protected void onDestroy() {5 k) {" O: W9 A. _. r* o  G
            lastClickView = null;
    , `8 F9 T/ [$ j2 v- i8 _% B        if (mMediaManager != null) {9 _. ]& u4 v& }* B2 Z4 m
                mMediaManager.stop(null);
    1 L. ?7 I3 @6 r5 M. l0 ^# O            mMediaManager.removeFileListStateCallback(this.updateFileListStateListener);7 p0 v/ J( c( a1 i. U3 Z: h
                mMediaManager.exitMediaDownloading();
    ' }+ Z8 W) V$ ^. D( y0 O  x" I            if (scheduler != null) {  K! [$ M! ?; m' m$ i
                    scheduler.removeAllTasks();
    6 G( {& G& T% }+ k  |. c. {            }
    * n1 I) |9 `) t( z+ ^6 R2 S        }
    ; e# y0 a  H# ?8 O+ p+ B4 F        if (isMavicAir2() || isM300()) {
    ( x0 A6 W- p. K: S5 C$ o9 f            if (ReceiverApplication.getCameraInstance() != null) {
    " I: L8 G" X( B  t2 u8 c  H  S                ReceiverApplication.getCameraInstance().exitPlayback(djiError -> {
    $ b3 S( {; R: Y$ ~; d, @7 H) x                    if (djiError != null) {
    " c; ]$ T2 X& f# j1 f2 Y8 N7 R                        ReceiverApplication.getCameraInstance().setFlatMode(SettingsDefinitions.FlatCameraMode.PHOTO_SINGLE, djiError1 -> {: F+ F9 `) Z) A5 e2 u
                                if (djiError1 != null) {- Y# c* U% S" H+ S. L
                                    showToasts("设置单张拍照模式失败. " + djiError1.getDescription());2 m, R! i( N, T2 H- N, d4 }" ]. \! x
                                }5 Y, y- _' S' X; x4 F8 H* a
                            });
    * x8 z2 y1 ^  G- h- |                    }
    & @  J# ]3 e  D                });
    + Q8 [7 e9 n% l3 N2 t. L; t7 t            } else {3 g" A3 i! _0 {7 Q5 q: }
                    ReceiverApplication.getCameraInstance().setMode(SettingsDefinitions.CameraMode.SHOOT_PHOTO, djiError -> {8 A* f* v/ @4 t' c7 p2 A
                        if (djiError != null) {9 r. l& j1 S  y
                            showToasts("设置拍照模式失败. " + djiError.getDescription());
    , W5 Q7 M) f7 u5 o: q                    }; r9 f9 p/ [+ R+ _( J
                    });( E, {9 I! I, W7 z6 @2 ~
                }/ B- d, Y* ]. B% ]
            }" [" B% N1 ^2 U
            if (mediaFileList != null) {( O5 ^5 X( g: L" f( N
                //            List.clear();8 _# y# b1 g' ~% R+ t  d1 o" v
                mediaFileList.clear();! C0 p% ~3 V+ K, w: |* R  q* a
            }( C, M$ m/ B( f3 P4 r
            super.onDestroy();
    ' h# o1 ]7 `3 L. T, f4 @& |% T    }
    + P  {' G" P  N* Z/ d! w    private void showProgressDialogs() {# r1 z( }2 v9 |
            runOnUiThread(new Runnable() {9 ^! N  p4 ?) D. f7 \. }
                public void run() {
      o0 r" u1 z: W$ }5 Y# }6 Y                if (mLoadingDialog != null) {
    , P3 Z! h4 n! i( V                    mLoadingDialog.show();1 `1 F8 c. {; m
                    }2 ^+ s8 U- y7 v' y0 b+ Z
                }
    : \2 Q+ C0 Y  g$ m2 f) u        });
    $ E# i/ V0 L& n: ~/ X6 j% e! A    }
    & j0 e2 W# c+ E3 I* ]/ w" Q    private void hideProgressDialog() {) Y3 s. x; I! B  T6 I- z6 I( ]: C
            runOnUiThread(new Runnable() {4 g& x7 Y" Q8 ^( `2 T! ]0 g
                public void run() {
    * @- G3 W/ I/ B3 [/ Y$ e2 a                if (null != mLoadingDialog && mLoadingDialog.isShowing()) {; O; h3 m$ t' ^2 V( ?4 ]
                        mLoadingDialog.dismiss();. B3 C- C1 ]2 N  W3 j0 n
                    }
    - T9 [  A/ a9 ~            }
    & [2 x6 I+ A  I* x: A3 f$ X1 g        });
    ; i! Y( M8 o4 p1 M: c    }
    9 Y9 @2 J, w7 Q7 C1 x0 r    private void ShowDownloadProgressDialog() {
    . v. a: e/ W  Z8 B& s        if (mDownloadDialog != null) {/ ^- n" C. e4 ~4 [7 D" P
                runOnUiThread(new Runnable() {9 [/ f1 ~' C' }! |! w1 b# x
                    public void run() {
    % S" q, t/ ?- p* o: F( m# p                    mDownloadDialog.incrementProgressBy(-mDownloadDialog.getProgress());
    * f6 p$ |5 o7 p! \                    mDownloadDialog.show();
    ) M2 B. B' h' Q' m% L                }
    / i5 i' x; d' J  G            });4 ]7 |* `) H- n0 U- |( i! |
            }
    1 V2 x9 T3 M$ q+ U    }8 V' b: `% G0 a& Z' W6 k- o
        private void HideDownloadProgressDialog() {
    6 B$ b2 h& v% l9 I' @; E1 W2 G( K        if (null != mDownloadDialog && mDownloadDialog.isShowing()) {. u! l2 @# _6 ?" {  j, l
                runOnUiThread(new Runnable() {$ J  `+ l" J! P4 U! t, k" J- ~
                    public void run() {
    ! Y" v8 h4 t9 a( {                    mDownloadDialog.dismiss();
    3 I4 ~2 l5 }$ f7 g                }6 _: `3 j, z8 v% y) N
                });% L9 P: C7 P2 Z' f) p) d
            }
    / K4 f& e( b, v* n3 \* Z    }
    / E- K! T: Q4 \    private void initMediaManager() {# n6 }6 _9 T1 S6 _
            if (ReceiverApplication.getProductInstance() == null) {
    8 H% v& X+ b3 I" j            mediaFileList.clear();% V7 X4 L6 T/ N
                mListAdapter.notifyDataSetChanged();# Y; O5 F: c8 X6 e" L
                DJILog.e(TAG, "设备已断开");
    6 V, r  ~  V5 T            return;2 h4 l. M9 w4 c1 j: r( ^8 z
            } else {# p5 D) X; E8 O9 O' Z& \
                if (null != ReceiverApplication.getCameraInstance() && ReceiverApplication.getCameraInstance().isMediaDownloadModeSupported()) {
    7 R1 D, R8 `6 j% Y6 K                mMediaManager = ReceiverApplication.getCameraInstance().getMediaManager();% b! U4 ]4 s' p: q" ^( B
                    if (null != mMediaManager) {
    ! u! L0 @# r, g% ?                    mMediaManager.addUpdateFileListStateListener(this.updateFileListStateListener);
      d* U( a( _- L' i9 {/ d, Q1 j. K                    mMediaManager.addMediaUpdatedVideoPlaybackStateListener(new MediaManager.VideoPlaybackStateListener() {
    7 _# |. Q+ A) c* |0 z; {9 X                        @Override
    , h7 j8 C7 Y6 X7 y; u' o+ s1 S                        public void onUpdate(MediaManager.VideoPlaybackState videoPlaybackState) {
    $ ]; ~- K8 s5 e                            state = videoPlaybackState;0 r( v6 P2 `; V. k" J6 E) X
                                if (videoPlaybackState.getPlaybackStatus() == MediaFile.VideoPlaybackStatus.STOPPED){6 n( `: @0 w' e: A. _
                                    runOnUiThread(new Runnable() {
    ! V* X' b! p$ Y. d8 {                                    @Override
    # v# G* J& y1 g6 M( G                                    public void run() {1 {& [/ A  d) M6 ]# t$ L- [
    //                                        mImageViewVideoPlay.setEnabled(true);
    ( o- W1 V4 z' D4 q; |# ^0 J8 r; s  c//                                        mImageViewVideoPause.setEnabled(false);! x* K* B' q* q/ k6 \+ e
                                        }8 X' B9 ]4 p( o& ?$ C5 x
                                    });% m" t1 d( e% r4 p' V
                                }
    ( Q; r3 |( {7 V                        }" _+ |) S6 M! M% I! y
                        });4 ~1 i2 v% i! _8 U/ r
                        if (isMavicAir2() || isM300()) {
    / ^/ {8 a+ c. |7 h; D! z5 ~                        ReceiverApplication.getCameraInstance().enterPlayback(djiError -> {0 ?5 W0 f; |$ I" T2 V2 P
                                if (djiError == null) {
    3 N- B! H1 ~& y1 Z6 k8 o8 S% ]                                DJILog.e(TAG, "设置cameraMode成功");8 K; v) r6 |6 F" ]# _3 X1 g
                                    showProgressDialogs();. [4 D1 O5 j9 I& m4 d" S
                                    getFileList(0);
    " a# w( Z& Q+ U) c6 w1 o1 B( a                            } else {
    * o, z) U! P! o! T                                showToasts("设置cameraMode失败");
    1 ~2 d/ m' r+ R" Y- v. ~( f( L/ I                            }4 q8 f8 ^- C! s+ S
                            });/ c3 M, n$ J% g- N
                        } else {4 e+ m# _4 a/ R
                            ReceiverApplication.getCameraInstance().setMode(SettingsDefinitions.CameraMode.MEDIA_DOWNLOAD, error -> {
    " |! z9 Y1 `/ [+ c5 E+ A2 L                            if (error == null) {9 M0 g3 D! p( a4 f) q9 u& f, j+ R: w
                                    DJILog.e(TAG, "设置cameraMode成功");
    / p3 r2 q# f% C9 z1 Q+ Y  T                                showProgressDialogs();! S+ ~4 c) t5 J  H7 w
                                    getFileList(0);
    ) f+ Q; c; P& t; ?, g                            } else {2 s2 u* d# s* h3 j5 D' I
                                    showToasts("设置cameraMode失败");
    " t( y" |1 E% I- W% v                            }
    7 N9 o; Q; T7 E4 u                        });3 O) \8 t6 i. |' L. R
                        }% k, I9 g& b- _/ n: |
                        if (mMediaManager.isVideoPlaybackSupported()) {
    # v5 K1 n1 S  l                        DJILog.e(TAG, "摄像头支持视频播放!");! V/ m- a) f3 k3 K9 h/ Q' \: q) r
                        } else {5 u& P7 E! Y, c$ A, X
                            showToasts("摄像头不支持视频播放!");0 C1 A2 v  C5 P/ f# v& m1 s& j0 G
                        }
    9 B& H8 B) s0 l8 B                    scheduler = mMediaManager.getScheduler();9 [$ ?# y$ ?6 }3 H' v( n9 r# k0 ?
                    }
    * P) M3 |* n. E, R! }0 L            } else if (null != ReceiverApplication.getCameraInstance()
    8 q& _2 w( a7 `$ A: D* H4 m# H! T( }: \                    && !ReceiverApplication.getCameraInstance().isMediaDownloadModeSupported()) {8 H1 L, H1 q6 j! R
                    showToasts("不支持媒体下载模式");
    . r8 \1 f, o4 a7 Y# |+ I  h            }! S3 }% s% h4 R8 _$ K0 {
            }( t# p1 a& b( `: n/ ]6 f9 V
            return;& z6 R. X% M, N3 c
        }
    ; @: d8 ?# |/ Y6 p1 F2 ^    private void getFileList(int index) {
    % \" J9 l0 u  k9 n; R        mMediaManager = ReceiverApplication.getCameraInstance().getMediaManager();1 L( u+ a" L1 B0 M( f
            if (mMediaManager != null) {
    ; y# i* l1 ^- t  \1 K& S3 ?' N$ g0 W            if ((currentFileListState == MediaManager.FileListState.SYNCING) || (currentFileListState == MediaManager.FileListState.DELETING)) {5 k& o2 f9 }: l) W  V4 {" ^
                    DJILog.e(TAG, "媒体管理器正忙.");
    1 g+ ~  C! K( I) T            } else {9 l* b" F" D* f3 p4 j
                    mMediaManager.refreshFileListOfStorageLocation(storageLocation, djiError -> {  U; z. A1 K3 H$ i* u' o
    //                mMediaManager.refreshFileListOfStorageLocation(SettingsDefinitions.StorageLocation.SDCARD, djiError -> {
    2 ?  C: W/ _$ D( H/ w" M                    if (null == djiError) {
    : w8 M5 C3 B' K- L4 I' K3 L, E' }                        hideProgressDialog();
    : a. g" ^2 y, z. k* a% c                        //Reset data
    ! `* o9 B: o0 T# x) j' b, R, y                        if (currentFileListState != MediaManager.FileListState.INCOMPLETE) {* s. p0 i2 q& e2 h
                                List.clear();, [& B2 a0 `5 _9 M3 u0 p( u9 p
                                mediaFileList.clear();, d1 Y: A, Q! S" _6 s
                                lastClickViewIndex = -1;
    ) c; R. {! F6 {; T/ g: ^4 h                        }9 J6 [4 C8 G' B: @, a& \* v  j
    //                        List = mMediaManager.getSDCardFileListSnapshot();
    ! l4 ^  Z: c9 b$ S//                        List = mMediaManager.getInternalStorageFileListSnapshot();
    7 d* u( s: {# u+ u, W- S                        if (storageLocation == SettingsDefinitions.StorageLocation.SDCARD) {
    ' I- W# E, q1 f' W; p  s0 W                            List = mMediaManager.getSDCardFileListSnapshot();
    , q; W. z+ A) J/ v% `                        } else {, Q* Z" B8 b& C# ~
                                List = mMediaManager.getInternalStorageFileListSnapshot();
      ?+ g1 L2 D) s. Y2 h5 j7 E                        }) C+ }( |  N* c7 G
                            switch (index) {
    , g- G) B! B! a% F3 _                            case 0:
    ! g( b. Y. b, F' n* p                                for (int i = 0; i break;7 W3 a7 z9 g7 b3 W) H. E  C
                                case 1:2 C6 `- S2 ]9 O4 T! W
                                    for (int i = 0; i if (List.get(i).getMediaType() == MediaFile.MediaType.JPEG) {
    ! k1 C3 h6 ?; w7 s/ ?- n% j; e: g7 n2 Y                                        mediaFileList.add(List.get(i));
    ; J' U+ A8 h2 d7 j) n                                        MyLog.d("图片名称:"+List.get(i).getFileName());, Z" X. f. y3 O, \* s, _/ I/ P  C' o
                                        }
    / k: P7 l5 ^' ^4 V8 A' a; i                                }
    " h) X$ t8 I: v: o# v' O. c                                break;
    5 V' C- b$ T. `                            case 2:$ F1 q2 C) J0 H
                                    for (int i = 0; i if ((List.get(i).getMediaType() == MediaFile.MediaType.MOV) || (List.get(i).getMediaType() == MediaFile.MediaType.MP4)) {
    % @! O* o" |$ p8 v                                        mediaFileList.add(List.get(i));
    ) m8 @1 Z  a0 C                                        MyLog.d("视频名称:"+List.get(i).getFileName());* f' X7 o' B7 O- j' N1 {
                                        }
    ( S! m9 ]3 e, \3 i3 _3 v3 G                                }( H# K% D+ e" Q# e: Q2 K  {
                                    break;" t  B/ L2 y# ]* F8 T; G' }0 I
                            }
    . T2 j# [# `' _7 Y1 z! _& R                        if (mediaFileList != null) {# R1 i' `5 ]1 j6 E4 Q0 @4 x
                                Collections.sort(mediaFileList, (lhs, rhs) -> {
    ' o: m4 h- M2 H3 w( s                                if (lhs.getTimeCreated() return 1;
    4 ?% h' l7 Q& c: u/ G- w5 N# E                                } else if (lhs.getTimeCreated() > rhs.getTimeCreated()) {
    ( Q! Q# J0 n) L2 D# u9 Z                                    return -1;1 F1 Q8 A$ `5 N, f
                                    }  J4 }4 F3 [. Q$ g$ }) i- _: L
                                    return 0;
    # G9 O; J5 e% x1 s3 \/ g8 R                            });
    + ?( Z' J7 Y+ Y9 S                        }
    : V" m! ]2 L! u                        scheduler.resume(error -> {
    - t! P5 g+ d$ L8 H6 U- R                            if (error == null) {* h4 ^7 [8 c+ F# Z, r. i9 Y: r
                                    getThumbnails();5 M) {, ?+ D( m7 f5 d$ O
                                }1 l" I% }, @$ j- t# F7 Z, {# e# M
                            });( K1 ]# _& d3 T9 a. x* n6 t6 a
                        } else {$ H* `: g7 S7 D* C6 [9 ?9 B
                            hideProgressDialog();
      a4 z1 i" y& Z. F2 q. k                        showToasts("获取媒体文件列表失败:" + djiError.getDescription());
    ; a9 v1 V- X$ z                    }
    8 i: B; p. q# \2 e$ v3 l                });7 ]' }$ F4 L2 f  H7 j
                }
    ; x7 _% g' H+ A" X* g        }6 z+ o& t% C1 [) X; g. M/ S/ M
        }, b, `, {/ O7 B  @
        private void getThumbnails() {
    7 Q+ d1 `7 X" `        if (mediaFileList.size() 0) {1 v* `  i3 K% R
                showToasts("没有用于下载缩略图的文件信息");
    , u! \0 ]6 ]3 F9 h* j            return;
    . z/ r. B' q5 e5 H7 w- h8 y% _        }
    ' Q# h" `  F# m        for (int i = 0; i private FetchMediaTask.Callback taskCallback = new FetchMediaTask.Callback() {
    - a) C9 T8 o1 D5 o        @Override: }* C$ c. u; d8 a6 J
            public void onUpdate(MediaFile file, FetchMediaTaskContent option, DJIError error) {
    * J- u1 I9 j, q+ K- y            if (null == error) {
    2 k) c" X, U9 Q- p2 ~                if (option == FetchMediaTaskContent.PREVIEW) {
    6 |+ X. Y# k6 k. \* ?0 P  \                    runOnUiThread(new Runnable() {4 S  W% [- K9 A2 |) Z3 f+ }# `% w
                            public void run() {
      i  ~# j3 d9 E+ D, s- l                            mListAdapter.notifyDataSetChanged();) y# I5 N7 M- ^
                            }
    6 d- k9 K, ^0 f) x$ o! ?                    });
    8 X1 j) K# K  _2 c' \                }8 Q' a5 X0 G0 v9 f+ p' b
                    if (option == FetchMediaTaskContent.THUMBNAIL) {0 d' G# j: |1 l( m% ~
                        runOnUiThread(new Runnable() {  W' j* e4 q# h4 r2 h% r
                            public void run() {
    # w$ j$ H/ X- k  o! k8 z3 G                            mListAdapter.notifyDataSetChanged();3 u: h; a$ E8 b- K. ]0 W1 O
                            }2 h, M+ v2 V- b8 }
                        });& X/ S# [, n+ Q
                    }' h' h* o# N8 `) o
                } else {+ \1 S- d+ p+ `" L1 T9 C* F2 z
                    DJILog.e(TAG, "获取媒体任务失败" + error.getDescription());% ]: e# L, o1 _
                }
    . h4 K$ h, a; j4 z5 Q        }4 g: \3 ]3 m: {! g9 k* y
        };
    9 \5 C% D* X3 {/ }& N$ ^    private void getThumbnailByIndex(final int index) {) G2 \- M# Y3 @( `
            FetchMediaTask task = new FetchMediaTask(mediaFileList.get(index), FetchMediaTaskContent.THUMBNAIL, taskCallback);
    # S8 |; x4 n6 Z6 Y5 W8 S/ O$ R        scheduler.moveTaskToEnd(task);
    : M7 _; m- i5 f  s1 j    }. v( T' n4 Q1 S/ T: p
        class ItemHolder extends RecyclerView.ViewHolder {
      S" e" _  R  T* m* h2 R2 l- ~        ImageView thumbnail_img;: O/ F0 @9 }! o4 R
            TextView file_name;
    ) L" ?2 G/ Z; c. B, E        TextView file_type;' t; x2 U! E/ y' W4 p/ J
            TextView file_size;# N. l+ z7 i1 Y% O
            TextView file_time;
    2 S( {3 `: P9 u) t) [+ ^8 ?) c        public ItemHolder(View itemView) {, q9 g, u) D& C9 F( q5 K$ M
                super(itemView);
    % n/ a2 C) M: |( D7 S. w* {            this.thumbnail_img = (ImageView) itemView.findViewById(R.id.filethumbnail);3 W2 r$ b  J9 m8 [& j( ~
                this.file_name = (TextView) itemView.findViewById(R.id.filename);
    % M0 Q, O, J/ w8 a; T. s* M            this.file_type = (TextView) itemView.findViewById(R.id.filetype);
    0 C/ Y, r) c3 {+ m            this.file_size = (TextView) itemView.findViewById(R.id.fileSize);
    # `9 j) V0 _3 R3 y0 i1 O            this.file_time = (TextView) itemView.findViewById(R.id.filetime);3 G5 \. Y; i( O! v- Z/ O3 x2 R( s8 t
            }0 K& x8 g! D5 R6 O
        }6 n: E$ ?, L/ P8 h" S
        private class FileListAdapter extends RecyclerView.AdapterItemHolder> {3 S  y6 Y1 ~: H. t7 O
            @Override1 e8 V* S: Q0 Q( ]3 a
            public int getItemcount() {
    ' E+ u4 R, c+ s( U            if (mediaFileList != null) {
    ) v( i, l8 U2 I- C2 x' y                return mediaFileList.size();
    7 t+ o6 l5 a' E' w: c$ S            }
    $ e  b' V2 D, r1 T( j            return 0;
    # j2 c$ @9 \+ S8 w# @0 I6 }# R# ~        }
    $ c! e/ e1 d- v$ _* d        @Override$ q- M2 x0 X0 o
            public ItemHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    ) y3 t; B: S" y8 {. r            View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.media_info_item, parent, false);. o+ h  g  @' L. B6 k; K
                return new ItemHolder(view);
    0 y* I; J8 }# [) w5 G# C' z8 t) ?        }2 A9 G& B1 i7 _8 Y9 I
            @Override
    1 J/ b$ M' R, {# o( _        public void onBindViewHolder(ItemHolder mItemHolder, final int index) {5 z: s# \+ d) w' k( e8 @, e+ `7 U
                final MediaFile mediaFile = mediaFileList.get(index);
    5 Z9 [  o0 H+ @7 q' `5 e$ L9 o1 P            if (mediaFile != null) {
    + t% {1 A5 J3 E3 b% b" c- p  Z% O; S                if (mediaFile.getMediaType() != MediaFile.MediaType.MOV && mediaFile.getMediaType() != MediaFile.MediaType.MP4) {
    3 m; q9 {1 }/ A                    mItemHolder.file_time.setVisibility(View.GONE);/ r. E# ]; k& _
                    } else {% Z# @/ i$ s0 @' @9 J3 v
                        mItemHolder.file_time.setVisibility(View.VISIBLE);% O) t3 X4 d* X
                        mItemHolder.file_time.setText(mediaFile.getDurationInSeconds() + " s");/ t( A  b9 ~4 B7 R
                    }
    # `6 t1 I5 J4 g5 Q% x0 z                mItemHolder.file_name.setText(mediaFile.getFileName());
    5 e# B2 ^/ h% Z! Z                mItemHolder.file_type.setText(mediaFile.getMediaType().name());
    * `3 h0 X7 b1 D/ A8 ~* g                mItemHolder.file_size.setText(String.format("%.2f", (double) (mediaFile.getFileSize() / 1048576d)) + " MB");; [! G/ E" |5 \6 q6 f+ Z
                    mItemHolder.thumbnail_img.setImageBitmap(mediaFile.getThumbnail());
    3 B  ]5 P2 J" d4 J' e                mItemHolder.thumbnail_img.setTag(mediaFile);
    " m" s2 o3 y% A4 K0 k/ s) O+ m; c                mItemHolder.itemView.setTag(index);$ B4 J& n. g/ d: O; Q
                    if (lastClickViewIndex == index) {6 ]* r: G4 G  a) Z9 t( }) y
                        mItemHolder.itemView.setSelected(true);1 o% n* R: w+ p: x  B
                    } else {
    $ X4 y& j2 e& Y; i% \7 R+ @                    mItemHolder.itemView.setSelected(false);
    % e0 u( u6 p% c                }
    5 D" R% j; t! F! S6 m5 ^                mItemHolder.itemView.setOnClickListener(itemViewOnClickListener);
    6 q0 s+ }$ n$ B9 N. d0 ~8 W3 n. s            }
    3 H5 [# n1 x! w6 @, y4 o# i% N        }; P& P8 U9 m/ O) \
        }
      K+ ^$ t- x  p9 ~- c    private View.OnClickListener itemViewOnClickListener = new View.OnClickListener() {
    . @3 |7 \0 Q  _2 t9 A1 O        @Override
    - R2 q, c) P! t4 @) a. M        public void onClick(View v) {
    3 R1 Q+ |4 H; t  F9 v) L            lastClickViewIndex = (int) (v.getTag());
    ! ?; H$ ~! L/ F- L5 K5 k9 E% |            if (lastClickView != null && lastClickView != v) {6 u# M! [' H8 I/ ?" A' }
                    lastClickView.setSelected(false);( Q/ m* N/ f4 N& a5 j
                }) I# E$ T6 _" a3 H8 c
                v.setSelected(true);
    . B8 Y$ I, }. K. _            lastClickView = v;$ R3 o0 }! Q  S  V: K5 z1 V" u, E
                MediaFile selectedMedia = mediaFileList.get(lastClickViewIndex);
    , H$ \( c. X& j$ R            if (selectedMedia != null && mMediaManager != null) {" q) @! r! h) S, V
                    addMediaTask(selectedMedia);
    # Z# n, n5 G8 q# x2 W" q% N            }
    , E! V/ O9 n9 b* G        }: ]- W2 k/ \7 [
        };4 ~) e5 f6 t1 l7 y; R
        private void addMediaTask(final MediaFile mediaFile) {
      @- H  i$ K5 m0 K8 f( \        final FetchMediaTaskScheduler scheduler = mMediaManager.getScheduler();7 _( Z, {) {7 V: v
            final FetchMediaTask task =
    0 @/ a2 H7 y3 Y4 `+ \                new FetchMediaTask(mediaFile, FetchMediaTaskContent.PREVIEW, new FetchMediaTask.Callback() {$ t! N/ r0 m9 m' D  a* F9 G* z2 W
                        @Override0 f) Q0 C# a4 [- y! r& J
                        public void onUpdate(final MediaFile mediaFile, FetchMediaTaskContent fetchMediaTaskContent, DJIError error) {2 o1 z. n) J3 ~5 g2 j' j! D
                            if (null == error) {
    " A" U% E2 }& R) ], J                            if (mediaFile.getPreview() != null) {& y: U' K' j6 p) Y$ u0 F6 k
                                    runOnUiThread(new Runnable() {9 D8 U* Q; b! w& K
                                        @Override% _; l: {1 F" k/ O
                                        public void run() {0 }' ]3 [3 D/ V' B5 C
                                            final Bitmap previewBitmap = mediaFile.getPreview();" `% M1 k* b9 M. @  I; W
                                            mImageView.setVisibility(View.VISIBLE);
    9 x2 C* H; M2 R                                        mImageView.setImageBitmap(previewBitmap);' A3 ?: t( q; F; h; l& H+ s
                                            if (mediaFile.getMediaType() == MediaFile.MediaType.MP4){  I) s5 v3 H% E# ^- k( m" [
                                                mLinearLayoutVideo.setVisibility(View.VISIBLE);
    , B8 x1 S$ a! r                                        }else {
    ) {# C2 o- U8 A6 N! G& b                                            mLinearLayoutVideo.setVisibility(View.GONE);: o5 z' V( N5 K; \# Z5 J/ m% @
                                            }4 ]: \3 F& J) U  S6 @: q+ @, u, O
                                        }
    , w5 p. n( i: q' h                                });9 e9 Z4 u( \5 f( X' {1 v3 ^
                                } else {8 l& s6 z, x2 B
                                    showToasts("没有图像bitmap!");/ y8 ^" @9 E$ q
                                }! V9 N9 g/ h0 e$ h( R3 Q1 d  d
                            } else {
    , F& S, G5 e2 e! f% f2 F; w( W                            showToasts("查找图像内容失败: " + error.getDescription());6 R7 U' R' q, A! |+ C# [, E% j2 Y
                            }
    . S5 Z+ P( S. E' l9 f; p$ @& E4 s                    }. s" y5 ~( J: H1 @' w% ?7 X% X/ l8 J
                    });# U2 m  L4 c6 e! V( b% E6 S1 ^
            scheduler.resume(error -> {: L4 o% L9 O( l/ O& B" [: G" g/ P
                if (error == null) {/ L8 W$ h: H: J) k4 R7 ^4 o
                    scheduler.moveTaskToNext(task);! M0 o' g. {' Q4 }) B  Y) i; v
                } else {
    3 i5 S  g8 q% k4 _4 j1 n                showToasts("恢复计划程序失败: " + error.getDescription());
    3 \. k0 x8 M. F2 \            }, o  t, q/ l! \: o; O
            });
    5 Z4 z7 v' C# r0 V: a! }    }; O) d; ~3 d) P$ P7 M
        //Listeners
    ' w7 z. i- X# M; D    private MediaManager.FileListStateListener updateFileListStateListener = state -> currentFileListState = state;5 _& u/ i8 _* M5 ?, F! ?7 [
    ) x: {* Y7 {: c9 X
        private void deleteFileByIndex(final int index) {
    $ o; b7 G' N( v        ArrayList fileToDelete = new ArrayList();! Z0 l* J5 I6 D" d, f1 z
            if (mediaFileList.size() > index) {
    # }& M- e( U% }) Y5 ]  M$ C            fileToDelete.add(mediaFileList.get(index));
    1 G1 o3 Z$ D& n. `2 {9 z& Y( h: P            mMediaManager.deleteFiles(fileToDelete, new CommonCallbacks.CompletionCallbackWithTwoParam, DJICameraError>() {+ N6 x: Z' y9 Q7 d& h
                    @Override
    & y# j& E5 B- Y                public void onSuccess(List x, DJICameraError y) {
    : a$ ~$ `9 Z1 l! r' u. P                    DJILog.e(TAG, "Delete file success");* q+ `' m0 h9 h
                        runOnUiThread(new Runnable() {
    2 @$ J( k1 D+ X6 g8 I0 w# x' m                        public void run() {
    : i7 N9 g! C/ N                            mediaFileList.remove(index);' z# s- F. R+ Q: n
                                //Reset select view
    . C5 K+ {- {% G$ Q* w                            lastClickViewIndex = -1;* R& F" ?# y$ X/ v& R: j% v- j
                                lastClickView = null;
    . H6 g" i  r" _8 m- J$ B. v( f$ G                            //Update recyclerView
    . `6 e4 F3 r0 u5 m                            mListAdapter.notifyDataSetChanged();
    8 {# a; l* o) x9 T                        }
    8 h- r( I$ I5 Z( l                    });1 M8 D( D5 [, |9 C( Y% f
                    }
    0 I' j7 H) w: Z  A# A' m# Q                @Override: y4 ]$ _" @4 s1 l7 k2 K
                    public void onFailure(DJIError error) {
    " A7 i7 n% y/ g" }/ c) n$ t                    showToasts("删除失败");( X  |0 X  X3 e( {8 F! E" u! D
                    }
    : P3 O( n4 R5 t+ \& s" `            });
    5 Y% `, J9 u$ b. d        }
    $ }. E% J" v! n4 ?. s    }- A. z/ ?; ^) U* x5 f, f( I* ^- x; H9 K
        private void downloadFileByIndex(final int index) {
    " }: }" a8 U4 ]9 l' L        if ((mediaFileList.get(index).getMediaType() == MediaFile.MediaType.PANORAMA)+ B! Z; ^+ M, c: a( D
                    || (mediaFileList.get(index).getMediaType() == MediaFile.MediaType.SHALLOW_FOCUS)) {
    ; s4 W! j; n3 J' S3 E2 O            return;4 _4 n9 s+ z& ~$ ]7 q; u
            }) F% w. `8 b* L' E) X$ v; T
            if ((mediaFileList.get(index).getMediaType() == MediaFile.MediaType.MOV) || (mediaFileList.get(index).getMediaType() == MediaFile.MediaType.MP4)) {/ C% H3 q" i+ B, h* ^6 |1 T
                SavePath = MyStatic.FLY_FILE_VIDEO;0 Q5 W- O: b" O8 m
            } else if (mediaFileList.get(index).getMediaType() == MediaFile.MediaType.JPEG) {. `! |8 x* n# c
                SavePath = MyStatic.FLY_FILE_PHOTO;/ o# n: G, E" o- f( M* ?) G
            }
    + ~0 y: L3 l4 w        File destDir = new File(FileUtil.checkDirPath(SavePath));
    2 s/ E$ G/ N2 S) N0 H: \        mediaFileList.get(index).fetchFileData(destDir,null, new DownloadListener() {/ }3 T: D: V% {* m0 N
                @Override
    7 {% }1 @0 b. M            public void onFailure(DJIError error) {
    # X' u6 a8 G. J5 p- l0 T                HideDownloadProgressDialog();
    + A3 d4 A  h+ C" C: E2 a                showToasts("下载失败" + error.getDescription());* R4 [" O# Y9 \- K4 v; s7 r) b; ?
                    currentProgress = -1;# h% `- K- j( l) D& N9 Q/ S
                }, \# v, n  c( u0 l: {1 e- x8 q) T
                @Override
    ( Z5 i4 V8 o! A+ F            public void onProgress(long total, long current) {
    . @! }! U5 Y7 t4 Q% [5 k            }9 c! X6 e- d) s4 Z
                @Override% @2 L" c; n, h0 v4 c3 b
                public void onRateUpdate(long total, long current, long persize) {7 B; t& i* H" }% ]3 H! Y
                    int tmpProgress = (int) (1.0 * current / total * 100);3 K+ `) L1 z7 O5 A. e1 y
                    if (tmpProgress != currentProgress) {! [9 p; q5 U! K# m2 ]6 w" D* F
                        mDownloadDialog.setProgress(tmpProgress);
    ; B$ }: }3 }/ O: ]0 I8 z                    currentProgress = tmpProgress;* E" x, k! U: y3 ~( z/ b& R* k3 R) H( E
                    }% w+ l/ H  l" M1 A, y
                }4 {. a$ C$ Q: L# ^
                @Override( K6 e9 t$ }# |5 K, E
                public void onRealtimeDataUpdate(byte[] bytes, long l, boolean b) {' o% F$ |" j* Q8 _' U6 B
                }
    4 y2 {& {. @# r1 w' F1 G9 }            @Override# {0 |4 u: s. i
                public void onStart() {  ?8 }* `( o- ]' `4 T$ o
                    currentProgress = -1;
    0 b1 ~( v) v- E) H% q& s                ShowDownloadProgressDialog();
    : h% y: J5 ^9 Y& y( T% |+ T# @7 v            }1 _0 f9 P3 m" A) {
                @Override
    , N1 g7 R. s, P$ l2 D) t  c            public void onSuccess(String filePath) {& K* H: @3 s( N! [
                    HideDownloadProgressDialog();
    . l$ O# \4 Y  ~7 a, d3 O& U- t                showToasts("下载成功" + ":" + filePath);
    6 w, V# E& _8 W                currentProgress = -1;
      L% b, m( B: J3 U0 |8 y            }
    / U$ j) V& m: c6 M8 V5 A        });
    ( v+ `8 i. q" l2 W//        mediaFileList.get(index).fetchFileByteData(0, new DownloadListener() {/ J3 ^+ ~$ |) Z, O/ l$ q( q
    //            @Override
    * A9 y$ C* v  P- O//            public void onStart() {
    . b2 o4 }0 S7 ?& [! L- \& `//                currentProgress = -1;
    " [% M. e, S/ `6 [; T$ t//                ShowDownloadProgressDialog();' l8 |! X4 \& G2 K8 p, B
    //            }
    - e, R0 z8 R5 z6 ^% ]' R' t//( ~7 q1 q: M$ E% w' j) Q
    //            @Override; w- ?) u2 f6 _  s6 ]
    //            public void onRateUpdate(long total, long current, long persize) {
    . x/ I7 x% m( |( ^3 `* Z//                int tmpProgress = (int) (1.0 * current / total * 100);! ]% T/ V/ t  {( u$ b
    //                if (tmpProgress != currentProgress) {' E1 ?4 U; Z: Z+ b- o
    //                    mDownloadDialog.setProgress(tmpProgress);9 |9 e3 N5 r1 K$ _
    //                    currentProgress = tmpProgress;
    $ E; W9 I! K; n$ `; j, w4 r7 \//                }
    , ?9 [. w& P2 O7 U- @7 @% H//            }1 }) ]* P9 g# _. f5 i% M
    //8 L! x' y( Z) Q# e- Q. m
    //            @Override/ m6 ~0 A  E7 Q( x) N
    //            public void onRealtimeDataUpdate(byte[] bytes, long l, boolean b) {
    , \7 I" R3 [3 Z, @//                byteToFile(bytes, FileUtil.checkDirPath(SavePath)+mediaFileList.get(index).getFileName());. p9 B5 |6 V# D1 M
    //            }
    8 c; M% {& {' S# l//3 H" W% N5 h# T3 Z+ M" x( y
    //            @Override
    8 p1 c; y6 a1 ]- u7 L) h' s! J//            public void onProgress(long l, long l1) {( ]) @; g1 L: y; t, K# O
    //% C! s1 n1 k/ {$ v! S" u  b
    //            }8 y) \# |: \9 ~5 R& K/ Z% y$ q' W* w
    //5 u5 ?- e- H# m5 ^% g) t0 x4 `
    //            @Override8 M8 q3 v( L# i! e  C
    //            public void onSuccess(String s) {, Y  O8 O; r# }' j+ j
    //                HideDownloadProgressDialog();9 [( w* i. N1 k, ]
    //                showToasts("下载成功" + ":" + s);
    ) d  K0 `" a) e% h. T! _! S//                currentProgress = -1;
    3 D+ r& |1 I/ N3 i- K//            }
    5 u1 H7 I( e0 `, @5 I/ l) G+ n//
    + t$ |8 r$ I  G8 [//            @Override
    4 o+ N/ X, P; J  N7 y//            public void onFailure(DJIError djiError) {) o  {3 l7 x+ {! J! m6 B/ \
    //' n/ N6 T, X3 R! k7 Z
    //            }' y( P! l  u. n, S4 `' C% C1 K# }
    //        });
    ( k9 \* |- J7 u, \7 p/ o- r' q    }
    0 H. w; f' s3 |9 r  [6 \  o    public static void byteToFile(byte[] bytes, String path)  B9 \4 w5 {3 D
        {
    . ]" G1 _$ N" x2 ~& G7 J        try  _: f/ ~, T, k$ Y- M  Z
            {9 j7 u4 B5 k$ f5 k& @& I
                // 根据绝对路径初始化文件
    ( Z8 v: V4 B; l! T3 L            File localFile = new File(path);( t# F! F( P, ~
                if (!localFile.exists())% b- V+ c/ i# Y8 n9 A
                {
    ! ?7 A, i  Z- w$ D, O                localFile.createNewFile();
    6 w/ H: D1 j/ H( q# R            }# P4 r+ V( A/ y! }) E# g
                // 输出流
    / ?4 r' q9 n: E) j; G) @* T            OutputStream os = new FileOutputStream(localFile);6 ^: `; h! n# _7 x  Y# |
                os.write(bytes);
    3 h9 @1 l4 K" k            os.close();7 k" H' F) R7 c! r3 I  ^' t
            }$ y. x" m9 l" e' K. N
            catch (Exception e)
    & S- B! X2 X" P) d2 p" [- ?" e5 y        {$ D& z" S: Z7 u" T! J  U5 k7 m3 `
                e.printStackTrace();9 X! O, E5 D0 ~' D  _7 e
            }" L3 K4 e. U# [4 c' a9 u
        }8 }/ V% O# \' \; H$ E9 U9 z# k
        private void playVideo() {  g. S4 l, ^8 C+ {
            mImageView.setVisibility(View.INVISIBLE);# L  O1 \# h9 F. I- n, r
            MediaFile selectedMediaFile = mediaFileList.get(lastClickViewIndex);
    % b% h. R; v# n        if ((selectedMediaFile.getMediaType() == MediaFile.MediaType.MOV) || (selectedMediaFile.getMediaType() == MediaFile.MediaType.MP4)) {% V2 y! c& \; [: B! W% Q
                mMediaManager.playVideoMediaFile(selectedMediaFile, error -> {+ \: y  g1 k* B, g, \& m3 S
                    if (null != error) {, s# p1 p0 a. }/ Y
                        showToasts("播放失败 " + error.getDescription());
    5 y0 s6 o* h& l3 T; f0 y                } else {
    9 b, K- f, Q/ k% i% }# z                    DJILog.e(TAG, "播放成功");1 H% I, y# S0 _0 |3 e
                        runOnUiThread(new Runnable() {
    ! H' R  T0 Z, ]                        @Override( n$ x/ B. E- d3 X/ _
                            public void run() {( D4 }! {0 w% C4 k" @4 R4 A) }
                                mImageViewVideoPlay.setEnabled(false);5 t& r% U1 }8 ]0 C* |
                                mImageViewVideoPause.setEnabled(true);
    8 n( k! v& \/ u; E9 ^                        }
    ) o" G7 o9 S  f7 i0 s7 k                    });, U1 F) m2 L/ U5 n7 e9 C
                    }2 \9 x" R% c2 x
                });
    ; m! Q. z7 n6 T0 F3 z9 w        }; f% A8 g! m3 }) q+ P# g
        }' D* e9 w8 U! t+ {/ ^( ~" Z) L
        @OnClick({R.id.img_back, R.id.img_delete, R.id.img_download, R.id.img_upload, R.id.img_video_play,. Q* x9 V. b" V
                R.id.img_video_pause, R.id.img_video_stop})
      d) T" g+ d; a7 ~! N# R, @    @Override) G2 {- z  C  ?3 \, U+ Y9 E
        public void onClick(View v) {0 K3 G& l) {6 Y( k  Y  l
            switch (v.getId()) {
    7 x# g( r/ C6 }% ~            case R.id.img_back:
    & Z+ y* N3 E1 j                FileManagementActivity.this.finish();0 _0 ^- v8 @/ J2 _4 D
                    break;
    % t1 _: V4 a8 F3 c            case R.id.img_delete:; f9 Z% f# e8 C- o( O4 u4 ~
                    if (lastClickViewIndex >= 0) {& U/ A8 E- U0 Y6 }' i
                        deleteFileByIndex(lastClickViewIndex);
    5 r4 w1 Q# E* ]9 f2 Q% U                } else {. a  }* c2 |9 ]  v5 L; O
                        showToasts("请先选择文件。");2 L$ T$ v8 J" }, t" ?( w' b. V
                    }
    5 j0 L7 u" p. `! M! ^! i0 h                break;
    ( O0 x& `  c' t& C- W0 t            case R.id.img_download:4 b" u$ C+ ^  ~$ Q
                    if (lastClickViewIndex >= 0) {$ y' E3 a' K2 \4 v
                        downloadFileByIndex(lastClickViewIndex);5 c1 x8 T( ^1 p- I
                    } else {
    # ]" W4 q% E" j' c. j                    showToasts("请先选择文件。");% ]$ `8 K3 O& g( K% z5 d7 U
                    }/ A& a& I# m- x7 S3 E
                    break;6 n) k8 e) i+ W; X3 S# n4 C
                case R.id.img_upload:' s- |# |8 f8 Q; c# h& \8 E3 O, B* \
                    if (lastClickViewIndex >= 0) {% z( h* s! M3 N4 m9 {
                        uploadFileByIndex(lastClickViewIndex);; U8 @) r0 L+ z* Q) j
                    } else {2 U( K/ x1 `0 p
                        showToasts("请先选择文件。");
    1 v4 |; _+ C  h( ]# k7 J2 t                }
    , D7 w0 B2 `# L4 ]& l                break;' Y. Q! H* c; R5 P$ {6 e& s
                case R.id.img_video_play:
    5 `3 @, V! |( M0 l* B7 ~                if (state.getPlaybackStatus() == MediaFile.VideoPlaybackStatus.STOPPED){$ D# ]3 |8 c( H. c: c! x! |
                        playVideo();
    + t9 {  o7 G( |4 [- [                }else if (state.getPlaybackStatus() == MediaFile.VideoPlaybackStatus.PAUSED){
    ; r1 A4 y) X2 v$ N! A! O                    mMediaManager.resume(error -> {
    6 l+ h; u/ t" X5 r8 {9 `                        if (null != error) {9 M( L0 k, P8 n0 {( i, \
                                showToasts("继续播放失败:" + error.getDescription());
    2 g/ h" K1 G6 j                        } else {
    4 v  j0 A& M/ ]  O1 \                            DJILog.e(TAG, "继续播放成功");
    6 V2 u( F! `# N$ M$ E                            runOnUiThread(new Runnable() {5 I) B1 Y5 k# ~& M, [
                                    @Override2 O1 m; ]7 O6 s
                                    public void run() {/ w' {' K( u$ q6 b0 ^
                                        mImageViewVideoPlay.setEnabled(false);8 u- w9 N* _1 B, |4 q+ T
                                        mImageViewVideoPause.setEnabled(true);* u: Z9 J, |8 p
                                    }
    / o6 w3 |7 m3 v( ?: u& a! t9 B                            });
    * A5 t7 Y, L8 M2 h2 S. j( J                        }3 o5 ]3 f- F% |6 \% {5 M8 v
                        });8 e& I7 n. H' f# Y( W6 ^
                    }6 U. Z/ T3 Z4 A+ d
                    break;/ u' ?) [$ y$ U) J
                case R.id.img_video_pause:
    6 w' c3 o; T# _8 o                mMediaManager.pause(error -> {
    4 H* o3 M- A6 n, P                    if (null != error) {$ @! C, Z9 M. K# Y- C  o
                            showToasts("暂停播放失败:" + error.getDescription());: M' F; H# |+ L2 @# i9 }# G
                        } else {
    ! Y2 f' M( M# k                        DJILog.e(TAG, "暂停播放成功");* A: d! z% Y+ ?7 S  n6 l$ z# G, r
                            runOnUiThread(new Runnable() {
    2 }& j  Y& E& j3 }                            @Override
    $ n' I: L' o; x6 q! S                            public void run() {
    : U+ m' d% Q( Y" H, j: X                                mImageViewVideoPlay.setEnabled(true);
    1 ?( J. I) ^; X# _3 |5 J9 E" E                                mImageViewVideoPause.setEnabled(false);
    " t& w* d& y& I. C                            }
    " p; a$ d+ t9 f& v4 d9 |6 Z                        });" v) r! {- t3 r
                        }
    4 g2 J9 k" z  b% K                });# y( v. E5 X( _  I- M
                    break;% s8 C1 `. B8 V; x2 g- t* L
                case R.id.img_video_stop:7 d+ F! O, }* ~  D' s
                    mMediaManager.stop(error -> {% I) R6 l# y# o: u
                        if (null != error) {
    ( N, ^1 _3 w! [- |                        showToasts("停止播放失败:" + error.getDescription());3 l4 X9 J( |- b+ }+ k
                        } else {
    1 e) l$ A! l9 Z. f# y                        DJILog.e(TAG, "停止播放成功");2 W" h& `! f% |) T" L0 {* g+ U9 z
                        }! k4 R! p6 j) V2 D# _& C
                    });5 B5 b1 w9 I, m! t8 B$ r7 \- Q
                    break;
    * l5 [+ A& [& X. ?6 x        }
    % c0 K6 g% }' q9 a* b    }+ C' n7 L5 v8 I' Y
        private void uploadFileByIndex(int index) {
    ! R. p$ |& q2 ~        if ((mediaFileList.get(index).getMediaType() == MediaFile.MediaType.MOV) || (mediaFileList.get(index).getMediaType() == MediaFile.MediaType.MP4)) {3 d- \# `1 h$ X( ^, ]  g
                showProgressDialog("正在上传");
    $ c; c  X3 p0 ?: Y* k. t" x4 \            new Thread(new Runnable() {1 Q8 B5 W" C( T3 H' |' l
                            @Override
    & k9 G( P% F* ^: E6 }; N                        public void run() {
    9 z7 t: S2 O7 K                            boolean isConnect = sftp.connect().isConnected();1 F2 d3 W4 ^" ]0 A! }8 l! ~* N
                                if (isConnect){* D9 |$ r; i) n. W) S
                                    boolean isUpdate = sftp.uploadFile("/mnt/uavFtpFolder/",mediaFileList.get(index).getFileName(), FLY_FILE_VIDEO, mediaFileList.get(index).getFileName());
    ' S1 p+ W$ C/ }1 A# _2 C2 Y, Y4 E                                if (isUpdate){
    ; T. D3 M) H  Q# R( N, N                                    runOnUiThread(new Runnable() {; ?2 t( c6 Q' ~/ d
                                            @Override( n9 l/ \- ~8 @5 a; T) X. e* J) a
                                            public void run() {% W4 p* M& j. I3 b
                                                removeProgressDialog();
    / F/ ^6 _8 v# L( k- t* N( Y                                            http.getHttp(GET_VIDEO_INFO+"?fileName="+mediaFileList.get(index).getFileName(),"GET");
    ( r: l. }2 K# A! r/ K) O/ c                                        }
    9 g6 [- U! y1 e                                    });" u7 H+ n  D( ?
                                        sftp.disconnect();
    + [) l" t( c/ o                                }else {3 B3 K& B1 v$ J* J2 E3 P
                                        runOnUiThread(new Runnable() {
    + s  l8 w" q0 ~& _/ r                                        @Override
    0 u3 ]0 s6 t5 S' P6 N. p                                        public void run() {6 ?; j. {; c& R' Y: {
                                                showErrorTip("上传失败");* C) [, b% f8 P. M% X
                                                removeProgressDialog();
    9 H1 f- I' P9 w9 o6 x; u* \- j0 O- t4 ~                                        }4 \7 n. e0 [/ L  o# [$ ^
                                        });
    ' K0 h; y  q' L" c                                }
    ) R3 G; b$ n# P. W% S: i                            }else {; i: z4 m. h# |5 Z+ e
                                    runOnUiThread(new Runnable() {$ h* n& d' y3 n. Q8 e7 ]* [- d; o
                                        @Override
    0 i4 F- b& B* q4 x8 z# H$ {/ {                                    public void run() {6 q- O; `  w; R0 Q
                                            showErrorTip("服务器连接失败");6 q3 }; Z! o( y  j4 ~* U, \
                                            removeProgressDialog();
    ! ?! C! C8 O9 w5 v                                    }
    / s- O9 g% m( C. R0 X( b                                });
      |/ ~, \( }4 i$ _8 c; N: x8 J% @                            }
    $ ?* [( g# Q( t9 F/ N6 m& H                        }
    ) z% b1 m: E: S0 d+ F5 Q                    }).start();$ j& N: m& s4 g) B
            }else {9 b7 k( Z. J# y0 t$ E  i
                showToasts("当前仅支持视频上传,请选择视频文件!");
    8 U9 b% U2 S( A; y$ `% L        }7 E& h) t" O0 K1 ?1 n* D
        }# r" @- {/ t. N. b  H4 s; i
        private boolean isMavicAir2() {  T1 D1 {% t8 e- K
            BaseProduct baseProduct = ReceiverApplication.getProductInstance();8 S" }) {/ U3 C7 b" N
            if (baseProduct != null) {( E$ y9 w. p) y% O
                return baseProduct.getModel() == Model.MAVIC_AIR_2;* ?( e- c& F3 ^) l
            }
    ) K! W) W  U+ d1 u( p; T- ^% d        return false;! _( H6 s% D, s  _: p! r
        }
    4 k# b8 N- s$ t  j    private boolean isM300() {
    3 X4 [' p! H# A% n' o+ s" O        BaseProduct baseProduct = ReceiverApplication.getProductInstance();4 v$ F3 I! }: q- o1 K
            if (baseProduct != null) {$ ^1 z* V7 O1 L' q8 W1 n, ~. x
                return baseProduct.getModel() == Model.MATRICE_300_RTK;, g8 j% U) b, W
            }
    . [* ^; l0 N' ]( i* `  V7 r        return false;8 X% L* s; H$ Y. `( w( K5 h
        }  Y+ m9 o# S( O
    }
    4 @; V3 t/ f5 C7 i; h$ k: L; ]运行后界面如下:( s, \: X  }+ [, Y, U

    dwx4hpo5o5k64023083506.jpg

    dwx4hpo5o5k64023083506.jpg
    ) J* g6 m; o& |" @( [4 o

    9 L6 I+ R* x) g8 b

    uiwobraut0x64023083606.png

    uiwobraut0x64023083606.png

    6 [" j& y% X7 |0 Z& j( Q往期推荐LabVIEW OCR 实现车牌识别
    7 S3 e% j4 @7 ]' B. U和12岁小同志搞创客开发:有意思的激光切割技术8 _/ p8 G' [* c% Y! o5 P" X0 |2 {
    JavaScript+TensorFlow.js让你在视频中瞬间消失9 w! `) s. P; P7 z
    使用OpenCV测量图像中物体之间的距离& |; ^, m- j* m: m7 f# h
    全网仅此一篇:工业级压力传感器设计及实现. h1 L( j1 a1 s2 i, U! g- a

    2 f. b/ Q* ^& G& U6 {; J0 o- C$ B

    qye2bh0mhdb64023083706.jpg

    qye2bh0mhdb64023083706.jpg
    8 {) H) F: P4 r& s1 R

    cnnb1olyf5d64023083806.gif

    cnnb1olyf5d64023083806.gif

    3 t/ y( M& y. L2 e点击阅读原文,更精彩~
  • 回复

    使用道具 举报

    发表回复

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则


    联系客服 关注微信 下载APP 返回顶部 返回列表