电子产业一站式赋能平台

PCB联盟网

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

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

[复制链接]

840

主题

840

帖子

6491

积分

高级会员

Rank: 5Rank: 5

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

0lshyu0if0e64011358650.gif

0lshyu0if0e64011358650.gif

) z1 r8 O, c$ d# g. D! P+ Z0 h点击上方蓝色字体,关注我们4 M; f) P' p4 n, I

- m8 u5 ^, V9 O上一篇文章(基于Mobile SDK V4版固件开发大疆无人机手机端遥控器(1))因为时间原因介绍了一部分内容,如果已经完成上一篇内容的操作就可以进行下面功能方面的制作了。自己开发的APP功能不是很多,但是已经将大疆无人机的常用功能进行了结合,同大家一起进行学习~
' t( g) T2 `$ }+ ]) S, {9 ~, p1
/ Z' t  T( \, B* \( Y- n; T应用程序激活与绑定
6 G6 G2 M  k% ]! ^6 s如果在中国使用DJI飞行器固件,则需要使用该用户的DJI帐户激活控制DJI飞行器的移动应用程序。这将确保大疆能根据飞行器的地理位置和用户个人资料,为飞行器配置正确的地理空间信息和飞行功能集。激活系统的主要是:
) h- F& h6 P  G! T
  • 中国用户必须在每三个月至少登录一次DJI帐户以遍激活应用程序。
  • 激活信息将存储在应用程序中,直到用户注销为止。
  • 登录DJI帐号需要连接互联网。
  • 在中国境外,SDK会自动激活应用程序,无需用户登录。
  • 另外,中国用户必须将飞机绑定到DJI官方app中的用户帐户。这仅需要一次。如果未激活应用程序,未绑定飞机(如果需要)或使用旧版SDK(
    ! H6 U5 b4 \% O
    8 M. D4 `, ]- Z( l
    24 P' U/ ?) x7 G; E6 F
    为应用程序创建UI编写MApplication、ReceiverApplication和RegistrationActivity文件(此处粘贴部分代码)。; k  v" G0 m, t+ P
    public class MApplication extends MultiDexApplication {
    0 c+ W1 ^6 d% K2 _/ ^( s( H+ Y    private ReceiverApplication receiverApplication;
    7 j- A! u  H) ~- R    @Override# A  b; n3 I! }, X6 W
        protected void attachBaseContext(Context paramContext) {
    3 B) c2 ]( g- ?4 c& g7 l  d        super.attachBaseContext(paramContext);8 `8 I: t" |' }+ v; ^0 A) }
            CrashHandler.getInstance().init(this);
    7 Z- S  t9 c3 q* g# l( q, M% d        Helper.install(MApplication.this);; Y' T( v5 c' o4 K
            if (receiverApplication == null) {9 _0 F% w; F/ ]1 [$ k! A
                receiverApplication = new ReceiverApplication();
    $ a* C% C" r) {% K9 N% W( b2 Y            receiverApplication.setContext(this);
    / [/ s# n+ f0 }' U        }6 t) _" U" S; \6 ]3 a
        }, o1 g" X9 S& X: D
        @Override; F9 W/ v' {4 f7 b4 Q
        public void onCreate() {. w- `* Z3 {; i" @& ?6 \
            super.onCreate();
    . ^. i. T" i! J3 B) O; E        receiverApplication.onCreate();( R# @6 y* ]( B; g/ ~+ o  z
        }3 t; Q6 P& ~3 x& V
    }
    0 I& O* m7 Y9 y上面的代码实现了绑定当前APP,将后续需要用到的类函数封装到ReceiverApplication 中,在ReceiverApplication 中也能够进行账户登录的操作。
    ( x1 Z' K9 f& B, p" Wpublic class ReceiverApplication extends MultiDexApplication {
    / e) p. q4 V6 _3 J+ L3 `+ g    public static final String FLAG_CONNECTION_CHANGE = "activation_connection_change";; v; m& `6 [! i8 ^  O" U  l  y
        private static BaseProduct mProduct;
    7 M$ h6 I! e1 @" I    public Handler mHandler;% K) ^/ p" t& e, N3 `  _2 O
        private Application instance;" ~+ d& h1 m. m7 d0 x* ^
        public void setContext(Application application) {" W1 G$ z' l% p' n2 Y
            instance = application;
    & L" C8 K/ k' S7 W! }6 X& w    }
    # }# d. x5 E: a  y) ^' ]    @Override
    $ e8 n6 @9 U5 w- S. V) ?    protected void attachBaseContext(Context base) {5 d4 l4 L( H7 ^2 T1 _* O( j
            super.attachBaseContext(base);
    + N5 G7 \5 V  W- U, X: Y        Helper.install(this);5 }  o6 a. X# M
        }) ]9 J8 U. c( f  `9 d4 ^
        @Override
    - O& o1 M, ?. d4 V    public Context getApplicationContext() {
      P9 o6 [; ~+ h- c        return instance;1 D( |7 C# g' |7 R
        }9 A0 s( w# a& V
        public ReceiverApplication() {
    4 i: }5 S1 ]4 @9 n  P5 j5 S    }' e# a8 c" g8 Z" F; x" z
        /**( R( v% ?( a! X  }( Q
         * This function is used to get the instance of DJIBaseProduct.) ~+ _! ?# A0 g0 o1 k
         * If no product is connected, it returns null.
    ( S) O- F8 z! ~7 e9 Z; Q4 p     */, |( P6 o% J# D& N) f# t( W5 f
        public static synchronized BaseProduct getProductInstance() {
    ( }1 _$ x' K. ], C) P2 F        if (null == mProduct) {% o& P6 Q: ~* n% T5 w
                mProduct = DJISDKManager.getInstance().getProduct();
    4 y& a1 @/ B9 Q! o$ ^        }6 C* C2 r8 B1 e* C( W; P- |: m
            return mProduct;: K% h5 r$ V0 |. I8 S- |+ y
        }4 w- t$ K; w) S. t
        public static synchronized Aircraft getAircraftInstance() {
    $ ?8 c5 y/ u# e2 o8 O        if (!isAircraftConnected()) return null;0 L* J$ A+ T6 h/ O6 K% ?$ i! p
            return (Aircraft) getProductInstance();% ]. S: H5 i, q" c7 z) X
        }
    ( q# t7 e7 e% Z, W    public static synchronized Camera getCameraInstance() {
    7 P6 l; Z3 i3 H* l9 y5 B" y% F        if (getProductInstance() == null) return null;
    : w7 R8 i& M, ]8 y0 J9 b  }9 D        Camera camera = null;5 F8 b1 p9 c+ F* \) y6 ~
            if (getProductInstance() instanceof Aircraft){
    9 ^3 a4 k: {9 E, c; P            camera = ((Aircraft) getProductInstance()).getCamera();
    % s0 i. m0 j: Y* K7 x2 [1 N        } else if (getProductInstance() instanceof HandHeld) {+ k& q" Z+ ^2 L
                camera = ((HandHeld) getProductInstance()).getCamera();& U0 c; s" g+ |7 A0 F* k- |: G
            }+ ^& q: M/ q( f4 {& i0 z
            return camera;
    / H: J4 I3 J' v8 y( V    }
    6 q0 H' Y' G6 w; T* H4 x/ \    public static boolean isAircraftConnected() {; ~9 Q  x! `7 e, W
            return getProductInstance() != null && getProductInstance() instanceof Aircraft;
    ' W! e0 S4 Z7 {    }
    ' ], v# A" M  @, @$ R0 K+ j  X5 Q$ p    public static boolean isHandHeldConnected() {
    1 B  R- R: k5 Q        return getProductInstance() != null && getProductInstance() instanceof HandHeld;
    . p* [3 s) t6 B& X5 O% V5 U' {    }8 i# f8 ~& |5 m2 A
        public static boolean isProductModuleAvailable() {' R9 T5 s6 E# ?& _1 O
            return (null != ReceiverApplication.getProductInstance());; ^- U( Y( M! C7 a- l; X
        }
    / n0 z( J. S  b: i    public static boolean isCameraModuleAvailable() {
    " q/ T" o1 D- H  O        return isProductModuleAvailable() &&1 \8 B& I( `8 g
                    (null != ReceiverApplication.getProductInstance().getCamera());
    ) N" _. ~- x0 N# Q" s$ t. W    }# G& ^1 q- m' A9 n; I6 O
        public static boolean isPlaybackAvailable() {- `$ h8 \5 F( j3 V
            return isCameraModuleAvailable() &&
    9 @! S" l0 `+ d% A* d, y                (null != ReceiverApplication.getProductInstance().getCamera().getPlaybackManager());) g- H% ]& z% V
        }
    2 F% v1 I8 Y# C! c; u    @Override
    9 D: r- q, |, f( W) c7 d9 p/ x    public void onCreate() {
      n2 a. L4 I. X0 n' j) j& }% L        super.onCreate();
    + Q% O% m0 O  F        mHandler = new Handler(Looper.getMainLooper());
    / ]# c# Z. d4 v        /**; h  O2 d" u% w9 z7 F
             * When starting SDK services, an instance of interface DJISDKManager.DJISDKManagerCallback will be used to listen to" \4 Z! v; N4 M1 S$ w: E
             * the SDK Registration result and the product changing.
    , c5 e' ^% ]8 W9 w6 T         */# e# C; a7 R7 J# S( n
            //Listens to the SDK registration result# b3 Z' g5 H! k# U7 y9 Q
            DJISDKManager.SDKManagerCallback mDJISDKManagerCallback = new DJISDKManager.SDKManagerCallback() {
    ; M7 J: C7 e/ v1 e, T            //Listens to the SDK registration result
    ( S9 g( A  l. M1 {- }  K( ~            @Override) n; C5 t: G' Q1 Z
                public void onRegister(DJIError error) {
    5 F- r2 H: O$ `/ s  V' C3 l                if (error == DJISDKError.REGISTRATION_SUCCESS) {
    2 P8 J8 _- I8 F                    Handler handler = new Handler(Looper.getMainLooper());
    $ g+ z- o. `3 _' K                    handler.post(new Runnable() {& [- g9 o( L& A2 Q* r9 a( x; V
                            @Override* A& T& Z9 F' s/ X+ S# T) E9 y; c
                            public void run() {' B# ], d2 J$ @
    //                            ToastUtils.showToast(getApplicationContext(), "注册成功");4 l- L; Y$ U: m8 i, t, r
    //                            Toast.makeText(getApplicationContext(), "注册成功", Toast.LENGTH_LONG).show();5 f5 o9 {! Y8 a
    //                            loginAccount();
    & o2 X) g: r' U+ |                        }! j6 Y/ G$ \; V1 K
                        });% W. `3 @+ c" p
                        DJISDKManager.getInstance().startConnectionToProduct();$ C5 I/ J+ }8 \( j* k
                    } else {
    6 r0 F) U( n. G9 }                    Handler handler = new Handler(Looper.getMainLooper());
    1 T* a( u1 M' y1 y; M                    handler.post(new Runnable() {/ H. \4 \' V  k' V" f8 v
                            @Override
    8 j# X9 \* M9 [7 c  A                        public void run() {
    # Z9 E, r+ j9 D, K* J/ w//                            ToastUtils.showToast(getApplicationContext(), "注册sdk失败,请检查网络是否可用");
    , x* c+ v8 P5 t! {! _' u! O//                            Toast.makeText(getApplicationContext(), "注册sdk失败,请检查网络是否可用", Toast.LENGTH_LONG).show();. W6 \& G# C% b  ^
                            }: N3 g2 F/ E8 ~( @
                        });
    ; B" C/ F' g' G9 F& n                }% r" ]4 q7 H3 [( ^3 ^- r  |
                    Log.e("TAG", error.toString());8 v( N/ c8 X, K- I" v5 E4 x- i+ }
                }% \) c) H8 B4 ?- q/ G, R* k3 n1 a+ T
                @Override
    % z: L9 m+ ~* b7 k6 z            public void onProductDisconnect() {& d. m" |) k& E; z; F
                    Log.d("TAG", "设备连接");
    # D& \) S- A2 ]; z$ m1 U6 A7 l, T                notifyStatusChange();, ~  p* R" _$ r
                }
    ! F: N. B/ p5 K2 \: k% b            @Override: J+ w# ^; F  {7 n% N( `
                public void onProductConnect(BaseProduct baseProduct) {' P5 I3 b: Z( [
                    Log.d("TAG", String.format("新设备连接:%s", baseProduct));: E0 |) p# J+ N$ D5 H
                    notifyStatusChange();
    . n, ^* A8 ~* p, b! K            }8 Z9 C2 u9 R' p/ v! R9 H
                @Override5 z$ c' n3 Q, W' ?  d
                public void onProductChanged(BaseProduct baseProduct) {+ g# |' s- {6 g5 a* m$ [$ y
                }. C$ a- ?/ q7 G8 A3 I8 A
                @Override
    1 l  h! M7 H# H# C. g6 C9 t- V            public void onComponentChange(BaseProduct.ComponentKey componentKey, BaseComponent oldComponent,
    $ N- z, L7 t  ~1 a/ {                                          BaseComponent newComponent) {" |" _4 l2 B- r8 \1 N  [2 [; }
                    if (newComponent != null) {- K. X/ J' J2 n8 `  K* ]
                        newComponent.setComponentListener(new BaseComponent.ComponentListener() {0 `% K0 s" [7 v% W
                            @Override
    0 {# {, @/ }9 g: @1 G3 i                        public void onConnectivityChange(boolean isConnected) {
    & p8 M$ c2 n' _4 Y$ U( ?* q7 X3 K' z                            Log.d("TAG", "设备连接已更改: " + isConnected);
    ! A2 p$ O# Z6 V. f6 x6 @0 n                            notifyStatusChange();( x) V" |! _/ V. V: F; \
                            }
    $ m8 `. c" Z3 l; \, g2 H; h; ^1 i                    });
    ' [# N+ f2 |2 R                }, X7 P  @6 g/ K9 S5 r# K
                    Log.d("TAG",
    2 U' z8 y" t- E' }                        String.format("设备改变 key:%s, 旧设备:%s, 新设备:%s",
    % M* N: D- U8 U8 x# i' m                                componentKey,# L( p) z" e7 _. l2 [. m
                                    oldComponent,
    , E5 d. _, O3 O                                newComponent));
    - P% N* E" Q. {( d! w3 M            }
    , `- q  Y1 g- J: ^: m. S1 m            @Override0 Q  P; ~+ w8 m6 j- ?
                public void onInitProcess(DJISDKInitEvent djisdkInitEvent, int i) {
    ( @9 r# d" g! t            }
      |1 x# m- V$ }; u' n- Z* |' \            @Override3 U/ ~3 z' B- Q. e& u. J
                public void onDatabaseDownloadProgress(long l, long l1) {
    7 j6 _) U0 j, l            }
    4 b2 W. P4 T! @- a& a. w4 q        };$ `+ W, x2 U! C2 s- h, V. U4 J4 U/ ^
            //Check the permissions before registering the application for android system 6.0 above.
    : c0 h) Y. N4 `        int permissionCheck = ContextCompat.checkSelfPermission(getApplicationContext(), android.Manifest.permission.WRITE_EXTERNAL_STORAGE);
    ! @1 o+ O& p+ l0 z- ~3 x        int permissionCheck2 = ContextCompat.checkSelfPermission(getApplicationContext(), android.Manifest.permission.READ_PHONE_STATE);/ t3 u( s3 _7 A# j! M5 p- c
            if (Build.VERSION.SDK_INT 0 && permissionCheck2 == 0)) {
    1 ]* G; G' v# M  w8 p% E            //This is used to start SDK services and initiate SDK.# R+ f$ G* w1 ]1 H
                DJISDKManager.getInstance().registerApp(getApplicationContext(), mDJISDKManagerCallback);
    # J+ c8 W% n  s//            ToastUtils.showToast(getApplicationContext(), "正在注册,请等待...");  Y0 {! S2 @4 W; }9 B
    //            Toast.makeText(getApplicationContext(), "正在注册,请等待...", Toast.LENGTH_LONG).show();
    ( T) i: |- W0 o# h! Y/ p- e* L" {# x        } else {
    / R8 Y# X6 |7 U* T; ?2 D//            ToastUtils.showToast(getApplicationContext(), "请检查是否授予了权限");* X& X! a( H: i% T: c) ?
    //            Toast.makeText(getApplicationContext(), "请检查是否授予了权限。", Toast.LENGTH_LONG).show();( }1 E( N5 W7 f
            }- k& ?% [2 ^2 u. b! @
        }
    ' J/ m% x/ H% L2 Z    private void notifyStatusChange() {$ j2 |: R6 x7 j7 ?# p" ~& ^- n
            mHandler.removeCallbacks(updateRunnable);
    ' ]# ~; C- S- M, w        mHandler.postDelayed(updateRunnable, 500);1 g. @$ I* y* c7 c" E
        }  s7 j; E4 J' h
        private Runnable updateRunnable = new Runnable() {: |# L3 K% N% A" K* N
            @Override8 N$ ~! n- y& e7 {) |
            public void run() {
    7 Q4 V5 j3 G* X  x. c" k5 X7 @            Intent intent = new Intent(FLAG_CONNECTION_CHANGE);8 l! }: \; w; d$ s2 n' M
                getApplicationContext().sendBroadcast(intent);) f. u' M' h' k+ k
            }1 M% y& |8 W- E* H0 [
        };- }- b. q4 h* J6 L; v3 s- c9 S
    }
    , i& Q9 I  c% u% a2 k上面的代码是对BaseProduct、Aircraft和Camera类进行实例化,在后续使用中不用再去进行重复的实例化工作,减少内存的消耗。
    & ?( q; Y& i& c4 J; d$ a6 K" J@layout(R.layout.activity_registration)
    * A, O0 q7 T! F% z9 c3 c+ fpublic class RegistrationActivity extends BaseActivity implements View.OnClickListener{$ ]" E" [/ G$ N& a$ {
        private static final String TAG = RegistrationActivity.class.getName();/ P! s  a* \  Z5 x0 x  n" E! _. z
        private AtomicBoolean isRegistrationInProgress = new AtomicBoolean(false);
    8 W+ Z; p* k& v( @    private static final String[] permissions = new String[]{' b, W& W; c% P9 Y
                Manifest.permission.BLUETOOTH,  c  I, d6 t: L
                Manifest.permission.BLUETOOTH_ADMIN,
    ; Q) D) q( U# K, q; m: |1 A            Manifest.permission.VIBRATE,1 r- T# ]" {* B$ I$ i
                Manifest.permission.INTERNET," E# A+ N6 H# L3 d- W- e6 T  S
                Manifest.permission.ACCESS_WIFI_STATE,
    2 ?. @9 `# D+ Q  T  g3 `+ P) P            Manifest.permission.ACCESS_COARSE_LOCATION,
    : r; b- `# Z: H) E/ F            Manifest.permission.ACCESS_NETWORK_STATE,. d+ u. v9 r" X: ]$ \# j
                Manifest.permission.ACCESS_FINE_LOCATION,
    2 Z8 g) }  |3 _/ g8 O            Manifest.permission.CHANGE_WIFI_STATE,' _4 ^' W' @5 x5 \$ u6 I
                Manifest.permission.RECORD_AUDIO,
    9 G3 }- C0 x3 n% O3 B0 X# N            Manifest.permission.WRITE_EXTERNAL_STORAGE,( k0 @) w3 f& U9 u  e
                Manifest.permission.READ_EXTERNAL_STORAGE,: q4 U" t1 m" G' b+ Y; N
                Manifest.permission.READ_PHONE_STATE,
    0 M2 Y; y& \6 v" B; l& `7 _    };
    5 _5 g( s# k2 b' _! H  @1 s+ C7 h0 A. e2 \! ?2 G5 g
        @Override
    . Y, G( f8 q( Z! B& d    public void initViews() {
    7 F  }& [3 d+ i1 o        isPermission();3 ^& `8 m. v( b1 L8 j
            IntentFilter filter = new IntentFilter();
    2 O( p; V! s+ g1 {* S        filter.addAction(ReceiverApplication.FLAG_CONNECTION_CHANGE);+ F, B4 p0 G7 ~* I: K! ^
            registerReceiver(mReceiver, filter);
    & C' g5 O  o$ x    }  L1 b0 Y' @) Q" d& b, `
        @Override
      ~7 S  A) c: u3 ]5 m; ^# R$ I/ |/ R    public void initDatas() {
    5 z& ]% E4 M7 k% f        startSDKRegistration();
    , v% ~* o/ C& ?: d    }$ Y% Y, [9 @/ q* q
        @Override
    " O( i, i7 q7 Y) }    protected void requestData() {
    * [6 W  [! p1 _3 _: b9 F. Y% T8 c, s  U        8 a( f8 e. y; X) _
        }5 o8 V; r; _8 u* f* V) Z
    . I: k  a" U7 |
        @Override6 d+ h) ]& j  c- W$ N$ A6 l$ S3 S4 J  b7 `
        protected void onResume() {
    " ~. P+ o4 V" x+ h. j) J4 V        super.onResume();/ }' g  I$ Z7 m1 _
        }" Y4 f& j' @( n9 j
    . w5 D' c& A* k; u8 q/ A: H7 k
        private void isPermission() {3 t& ]- B5 r4 ?3 v. c
            requestRunTimePermission(permissions, new IPermission() {
    0 f' C5 d; o# B% }, n0 X7 a( B            @Override
      B) j, W5 a4 h7 B6 c0 {/ [            public void onGranted() {
    7 T7 M) W& ?+ x! p4 }            }. R: N9 `3 i& P* f
                @Override
    " w6 o+ w4 V; G4 v; G3 M1 J            public void onDenied(List deniedPermissions) {! ^1 q4 z6 X' E( S+ m  m  y" X% ~
                }
    ) H, G! b% I9 d  I7 x5 A. Y        });9 A6 G+ A. L  V
        }6 r) ^; E/ C! Q3 M; f3 w! G+ D
      
    ) ~; y9 w6 H, v3 B    //无人机首次注册+ t5 A7 r- C' z% G$ J
            private void startSDKRegistration() {
    6 f5 l/ X! L$ q/ q            if (isRegistrationInProgress.compareAndSet(false, true)) {# v' W' F4 z) J3 d
                    AsyncTask.execute(new Runnable() {
    ) L3 q! s8 i& T& ~  S5 S% [: O! ?                    @Override; @  w3 d( Q1 N) ]
                        public void run() {3 {4 V; ~6 p" R: I
    //                      showToasts("注册中,请等待...");
    / B' j% w  t' H                        DJISDKManager.getInstance().registerApp(getApplicationContext(), new DJISDKManager.SDKManagerCallback() {
    & i; k7 T: O( Y5 l5 |5 V                            @Override$ s% M; h% A$ S
                                public void onRegister(DJIError djiError) {6 [1 a: N0 f: a. P6 j/ u
                                    if (djiError == DJISDKError.REGISTRATION_SUCCESS) {3 d2 C6 T8 M/ }7 U# k- p
                                        DJILog.e("App 注册", DJISDKError.REGISTRATION_SUCCESS.getDescription());) w7 v9 J3 B2 C: F+ s7 w2 h0 h
                                        DJISDKManager.getInstance().startConnectionToProduct();0 ~& h" r7 }/ K" @; M
        //                                showToasts("注册成功");
    . W: [6 m( i4 \5 U2 O+ _$ r                                    loginAccount();
    ; Q: E; {4 j5 }! e! M, a                                } else {1 w* G  F5 n9 @' s* a: z/ B! d* K0 j
                                        showToasts("注册sdk失败,请检查网络是否可用");
    4 g& u+ R( P  y/ Z' ~0 M3 Z# F2 C                                }
    4 v5 B8 b, a! _- s. @1 U0 J0 j                                Log.v(TAG, djiError.getDescription());- s. }4 y) c# m
                                }, f0 \$ g' L" T$ n7 S+ S0 W# U7 F1 b
                                @Override$ H0 [4 W- T  b$ d0 F4 ?8 w
                                public void onProductDisconnect() {
    0 l% R- n0 u+ M0 |                                Log.d(TAG, "产品断开连接");
    4 e0 m- H* g* v7 a5 {; a    //                            showToasts("产品断开连接");) ^  }6 T! {: F5 i- t; c8 _
                                }# u; h" ?6 q- m: r# n. W) D
                                @Override6 v) `3 _) b" C. y
                                public void onProductConnect(BaseProduct baseProduct) {: I+ A6 j# J7 k! s# }, `
                                    Log.d(TAG, String.format("新产品连接:%s", baseProduct));
    $ Z4 j# I: y6 p    //                            showToasts("产品连接");
    ! L2 y8 o+ m- O                            }) `8 ~" `) X% y# J# ]
                                @Override
    ) \& W( _$ Q+ d                            public void onProductChanged(BaseProduct baseProduct) {
    8 v' E& h! c: b' @                            }
    ( Y# o/ s, o" W$ F+ _                            @Override
    ; |8 |& {1 Q) G  [( J                            public void onComponentChange(BaseProduct.ComponentKey componentKey, BaseComponent oldComponent,
    + L/ V" B+ X4 k! E! _+ k' L' N. r                                                          BaseComponent newComponent) {* p, c+ k8 F  z- H+ |7 ?  E9 v
                                    if (newComponent != null) {
    ) V& ^& H1 t6 C3 s" h                                    newComponent.setComponentListener(new BaseComponent.ComponentListener() {: Y$ x$ f+ O4 i$ T$ Y
                                            @Override
    & R8 j5 G& X0 J. p; p+ f                                        public void onConnectivityChange(boolean isConnected) {
    8 i. @+ |9 u  f3 {- U& z                                            Log.d(TAG, "组件连接已更改: " + isConnected);6 n+ I9 X  l2 ?$ k0 o* `$ t; L
                                            }
    ( \3 ^) R) _1 S0 o                                    });/ ~6 J8 f1 d0 @. g( Z0 Q
                                    }! ~! t* x* e- V1 ?0 b- c- e2 R
                                    Log.d(TAG, String.format("改变设备Key:%s, " + "旧设备:%s, " + "新设备:%s",6 Q( w# J* A9 T7 D2 Q* p
                                            componentKey, oldComponent, newComponent));
    9 K+ L0 ^) W1 z2 j( _' J/ M                            }% K* r( T- c7 r
                                @Override- H6 w8 N# c6 C$ D
                                public void onInitProcess(DJISDKInitEvent djisdkInitEvent, int i) {
    + N# W% C3 y7 b- c6 u- |                            }% j3 s) l" l; j" Z! S* j5 ~
                                @Override% I+ M: d+ D+ v' o9 `# ~7 c
                                public void onDatabaseDownloadProgress(long l, long l1) {
    4 N9 T- i& r  c                            }9 v7 u2 u# ]5 _2 ]9 \4 i/ h( Y
                            });( b! E1 L% F$ V4 a9 A5 F" z
                        }1 S# Q- Q% P2 B" q% q4 R+ k
                    });
    5 Y3 _8 N! [  {$ J, U+ U1 C$ W            }; L5 i! K" d1 U& \0 }
            }) @7 }+ `3 K+ I. M. q
        protected BroadcastReceiver mReceiver = new BroadcastReceiver() {  [8 T2 X" }4 b% V/ A2 G: g
            @Override
    + Q- O: _8 X- q5 p, l        public void onReceive(Context context, Intent intent) {$ j  G/ Q- y6 \* a5 @6 [3 e( ]2 k
                refreshSDKRelativeUI();
    . b* {* W& g9 L        }
    5 }+ \  `% H. a* F    };
    . V/ F) D9 N2 [    private void refreshSDKRelativeUI() {; ?# ?" p5 I+ `
            BaseProduct mProduct = ReceiverApplication.getProductInstance();
    7 ~$ l1 U+ D" ]/ T6 U: ]        if (null != mProduct && mProduct.isConnected()) {$ C2 \# p) G) q% D4 s9 o5 D6 r
                Log.v(TAG, "刷新SDK: True");2 }  }9 M0 v2 F: C$ h" v- T, H
                mButtonFlightTask.setEnabled(true);0 y: C$ T- f& S
                mButtonSettingRoute.setEnabled(true);9 F/ Y: P% ]6 I2 U  N
                mButtonFileManagement.setEnabled(true);5 e+ J4 |1 k& `* ?: a
            } else {
    6 O# j- V4 T8 B+ v- u1 c/ Q            Log.v(TAG, "刷新SDK: False");
    4 s. F  k! V7 D( u2 E' I//            mButtonOpen.setEnabled(false);$ w# U2 f, q+ B$ j6 ^  a
    //            mButtonSettingRoute.setEnabled(false);
      ^( }/ U4 D. M- z# y8 u4 L$ N//            mButtonFileManagement.setEnabled(false);% i. q$ H% w9 |2 h7 Z9 h, k
    //            startSDKRegistration();
    9 U. a& U- z7 c- k) c        }, M5 c8 f* a: B
        }9 R3 y5 F( Z) `3 D3 o1 {2 S8 I" ]6 @
        protected long exitTime;   //记录第一次点击时的时间9 C# T& u* X3 n% m5 y" d2 A$ `2 T
        @Override6 \6 {# @& Y; c: g/ ?  x& _
        public boolean onKeyDown(int keyCode, KeyEvent event) {# H3 ~7 ~8 y- X6 j, a" O
            if (keyCode == KeyEvent.KEYCODE_BACK
    $ g4 X% E# H  S( S4 V                && event.getAction() == KeyEvent.ACTION_DOWN) {
    9 U- M  [9 s& T            if ((System.currentTimeMillis() - exitTime) > 2000) {- p# f( o% Y6 F: z
                    showToast("再按一次退出程序");/ @# e( Z+ L4 _. @$ c6 T
                    exitTime = System.currentTimeMillis();3 a, [) q3 y! s3 T* {
                } else {
    ) B; o6 w. ]* v9 d- u$ B. H                RegistrationActivity.this.finish();
    3 x, t. G* K" E% R                System.exit(0);0 W0 e. i" z: s7 [- c' a
                }
    3 G/ u  s# ?( h            return true;3 `- T" a& D# _- |: o+ a; C
            }
    1 r1 [, n, W4 x0 ^( M4 r        return super.onKeyDown(keyCode, event);4 O2 g5 I/ ]) |. F; ~7 I7 P
        }
    ' |' F) v. P% x1 |; Y% v! r4 w7 n
            private void loginAccount() {- ?8 T& D7 r( q- X2 u0 k& F/ r1 \
                UserAccountManager.getInstance().logIntoDJIUserAccount(this, new CommonCallbacks.CompletionCallbackWith[U]() {
    6 c' t' Z' |$ |7 ]& ^2 X                @Override, C1 ]" V7 @8 y0 X! g6 ?! ]
                    public void onSuccess(UserAccountState userAccountState) {
    # X, a/ d1 ^6 Z' z7 \                    runOnUiThread(new Runnable() {& x5 b5 F, G* _# f6 ~9 c
                            @Override4 w& H) _' {# {  }, w: `' s
                            public void run() {, Z* t1 ~8 V+ w
                                mButtonFlightTask.setEnabled(true);( L7 n+ q1 j! a; s! n
                                mButtonSettingRoute.setEnabled(true);- C6 [( D) e" \: o/ b
                                mButtonFileManagement.setEnabled(true);
    ' M: ^$ e, J1 k- i3 C' Z                        }
    ( g- s; {+ X) E7 {                    });
    , {& @/ s1 M+ o3 R                }* F. {5 S( y9 n. e
                    @Override" @' g5 m; ~. M
                    public void onFailure(DJIError djiError) {/ G* k, B( G( O' F2 Y# X
                    }
    " A% d' m9 x' k            });
    0 Z7 K; T( s. ?( D- v/ O, G1 b        }
      V5 @/ t$ x2 t) H}
    8 w) `' ?/ V; E/ a* i+ g上面的代码就要进行第一次注册登录了,当然你不需要自己去设计登录注册页面,大疆会调取自己的登录注册页面供你使用。
    ; ?5 o' B, g' N8 I1 c

    pfqmgqdfgzx64011358750.png

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

    utpqdgqpfom64011358850.jpg

    utpqdgqpfom64011358850.jpg
    5 _4 P& l# D5 m2 y" H: a
    上面的工作完成后就可以在无人且宽阔的地方进行无人机飞行了。: i+ T* s' w6 A  @
    4* k$ n' |! k& x% Y# y2 x
    多媒体资源的操作4 h& X: J: |! [7 X0 \# i
    多媒体文件操作,主要为多媒体文件的获取、查看、删除、下载的操作3 V# Q+ I* K. B9 O( I
    同样创建多媒体功能文件FileManagementActivity及activity_file_management.xml; y( ^  s% b8 ?# G. ^+ u7 X3 S
    activity_file_management.xml* {. `4 x, K2 ]2 I- e, y
    LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"* S) l6 a. K4 f5 J8 r
        xmlns:tools="http://schemas.android.com/tools"
    3 [$ d- y7 |  Y8 [    android:layout_width="match_parent"! w+ {  O0 q  i) J0 _, `
        android:layout_height="match_parent"* |7 X8 ]3 ?$ Z  K* S$ @3 z; u6 z: d
        xmlns:custom="http://schemas.android.com/apk/res-auto"
    - g" [0 D" H9 z7 q, ?    tools:context=".ui.FileManagementActivity"1 I, a5 z+ N' i& U& y( V
        android:orientation="vertical"* a5 Y4 Q2 B+ B) _, O, S# r3 }  }
        android:background="@drawable/shape_corner_eight">
    4 V8 L+ j, j2 ^; ]    include layout="@layout/activity_toolbar": g  K9 Y" W0 `7 b
            android:id="@+id/layout_file">include>
    , q" {0 W! n" I& O8 q" I3 m- S    LinearLayout7 @3 {4 e6 {/ D5 ]9 S, n
            android:layout_width="match_parent"
    1 F# E4 d( a5 F, O2 d7 N        android:layout_height="match_parent"# k! ]( P, B6 e1 D0 {
            android:orientation="horizontal">$ T$ L* i/ w+ K* A5 H7 M% Y( C; @  H4 ^# u
            LinearLayout
    ; |7 P- t* L' }0 P            android:layout_width="250dp"
    / V% U0 K$ p% i" |2 U            android:layout_height="match_parent"( x( Y9 R! W9 B; t& h
                android:orientation="vertical"
    2 x+ T  k1 n  \2 D1 V! E            android:layout_marginLeft="15dp"4 @6 H" A1 M- R, w/ q
                android:layout_marginRight="15dp">0 }2 k' D; W3 g6 k% R' m
                RadioGroup
      @5 y6 n8 @' C% Z% ]( a5 B                android:id="@+id/rg_file_management"
    9 W6 A! N/ r. Q/ i- G6 G' |3 g) o                android:layout_width="match_parent"  G* R" V' d6 X9 J
                    android:layout_height="40dp"
    ' E  W  C8 m  |/ q/ t$ a8 H* \                android:orientation="horizontal"! g4 X* y) ^- E+ Z$ v5 n
                    android:background="#2B3141"9 g; ]. X) r* d: t
                    android:gravity="center">
    : w0 U1 M/ K3 \# u* v                RadioButton7 X- ]0 w; ^7 v' M) b
                        android:id="@+id/rb_file_all"
      k, k( V; A! W8 u, c3 b# o" Z6 V                    android:layout_width="0dp"+ W; b# ^+ R! g8 o) M" }9 x# K9 J
                        android:layout_height="match_parent"( ]& q9 h$ m) {1 J
                        android:layout_weight="1"
    2 s4 N* W  _, y$ `) ]" s1 R$ S1 o                    android:button="@null": U( h/ p- b' c4 \8 |! g
                        android:checked="true"7 m  z% J; l7 L: k0 A; a+ O1 @$ t
                        android:gravity="center", o% Z% X5 V, X+ i, g
                        android:text="全部": W% L3 B  G2 l: |" v6 ~
                        android:textColor="@drawable/nav_item_color_selector"
    ' Z( s+ y4 Z/ \! y5 ~6 ?  C                    android:textSize="18sp"( M: w+ K6 ~0 Q$ _% F$ C
                        tools:ignore="TouchTargetSizeCheck">RadioButton>- @, v. n1 v4 R' z
                    RadioButton. S- @3 _, {' X, F0 C
                        android:id="@+id/rb_file_photo"
    6 k. l( [3 F- }% q3 U                    android:layout_width="0dp"; O8 k: \# g+ F  W" O: `. Y# a
                        android:layout_height="match_parent"
    " a# L$ ~" G" b4 U; b1 h! S                    android:layout_weight="1"! [( h* o* p' F/ p  f3 S" z
                        android:button="@null"
      S' S0 O9 P9 ^  L; r                    android:gravity="center"
    9 J% i" e6 Z8 L) g: g: @                    android:text="照片"
    $ p5 |3 I0 B  }                    android:textColor="@drawable/nav_item_color_selector"
    / x( J' k4 `1 u0 l/ w                    android:textSize="18sp"
    # j  |' I8 v# K                    tools:ignore="TouchTargetSizeCheck">RadioButton>  k2 _* y% T/ w$ [" V
                    RadioButton
    6 ]7 y) c- C8 d/ M9 ]                    android:id="@+id/rb_file_video") x( {/ J+ J8 \
                        android:layout_width="0dp"
    $ ?  e  W" Q8 k                    android:layout_height="match_parent"
    5 K  l, g. |; L/ z: s& w8 _                    android:layout_weight="1"
    " D1 v' u7 h. m0 o  z                    android:button="@null"
    6 ~* F( U- z4 [) O                    android:gravity="center"
    0 {' B' m# E1 `, A$ V3 `8 @                    android:text="视频"( O7 @2 ~% L; o% B" V. B4 n  H" w# t
                        android:textColor="@drawable/nav_item_color_selector"" \1 x% j; [7 \# x& z  v
                        android:textSize="18sp"
    # ~$ H1 |( p- J( [                    tools:ignore="TouchTargetSizeCheck">RadioButton>  n  l- i: v0 l( X
                RadioGroup>$ I( c1 }; \4 B$ f
                androidx.recyclerview.widget.RecyclerView
    4 t4 E0 ~+ U  Q' ^7 y                android:id="@+id/rv_file_management"
    / ^- P+ z8 W1 r5 D                android:layout_width="match_parent"/ h& F0 X; k/ S, W  w
                    android:layout_height="0dp"
    3 ]) U' a8 Z0 f                android:layout_weight="1"
    # c5 ?! U+ |& V: {  Z# G) Q1 y. l                android:layout_marginTop="10dp">androidx.recyclerview.widget.RecyclerView>5 y$ P2 d7 c$ a, f1 L+ q
            LinearLayout>
    * o/ l! }( O' v9 e( E3 z. B3 ^4 O& K        RelativeLayout
    9 W/ C4 m% \9 d            android:layout_width="0dp"! x0 [4 ~* I1 `$ u/ n, `2 J# O
                android:layout_weight="2"
    . I3 b. \' a' f( c3 d8 [            android:layout_height="match_parent">6 Q# ]5 N+ k. X) U5 L  [8 G
                RelativeLayout
    ) s  S4 G3 L% @# z* n. t* J" j                android:layout_width="match_parent"3 B* Z" \7 @4 x( E0 I/ Y$ k' k  I. d
                    android:layout_height="match_parent">; o: Y5 |' G& b$ [8 h! P
                    dji.ux.widget.FPVWidget" f) Q+ D2 G  l5 X
                        android:id="@+id/FPVWidget"
    ' p& ~2 l5 D0 T- I9 n0 R  ~                    android:layout_width="match_parent"- `0 M" h6 X) L, [# E! L
                        android:layout_height="match_parent") w) k- l( F8 g  ^( t
                        android:layout_centerInParent="true"
    ; ^% O2 D5 M( ]! [% W/ h                    custom:sourceCameraNameVisibility="false" />
    1 N7 w' B1 i6 Y1 z: }, o7 t2 U1 w1 Y            RelativeLayout>
    2 p2 D4 X( `$ ?! q+ o            ImageView* _& X/ H' @! f# P
                    android:id="@+id/img_show"* n  A% E2 N! p0 k2 X8 s1 r: y1 c
                    android:layout_width="match_parent"3 w0 o  q  ~8 N2 g$ \+ Q( S
                    android:layout_height="match_parent"3 d/ v7 H) U  \) K% q. s
                    android:scaleType="fitXY"% G% h+ T, z# P! Z: q* E* C7 O( [
                    android:visibility="invisible">ImageView>6 F' ~7 r$ X/ o7 S8 C, Q
                LinearLayout9 s, P) n. B* h: @/ |# N! F
                    android:id="@+id/ll_video_btn"* T) \  j1 o, Q9 B
                    android:layout_width="match_parent"
    - O+ |( m4 k; \                android:layout_height="50dp"* j! h( f2 }$ V
                    android:orientation="horizontal"
    2 W, M% A' a, O6 p                android:gravity="center"9 p  J& d  _, `2 D7 L+ ^8 h1 T) z  i$ O
                    android:layout_marginBottom="15dp"% b0 k; Q7 j* g" V" S. E
                    android:layout_alignParentBottom="true"
    1 p7 A1 c  \8 W) U                android:visibility="gone">
    # Z/ p; y/ v( }7 y( H" K                ImageView
    ! }. Z6 H! q$ C# U' s0 s                    android:id="@+id/img_video_pause"5 h1 G* M0 Z4 W. T/ v" N5 k
                        android:layout_width="35dp"' q8 |9 S; Q% w. G
                        android:layout_height="35dp"+ ?# i' \5 M6 z8 \
                        android:src="@drawable/background_stop_selector">ImageView>
    ' d. b4 K8 {( t6 C% x% P5 k                ImageView
    , z# _) I* M- z0 `                    android:id="@+id/img_video_play"/ G/ Q) @+ Q' I# X
                        android:layout_width="45dp"
    ( O( u$ T2 d2 }4 W  I. N                    android:layout_height="45dp"+ e8 E8 B! h8 }7 i( d  B
                        android:layout_marginLeft="20dp"3 H: S2 k# F1 @! E5 M, o& [
                        android:src="@drawable/background_palyer_selector">ImageView>3 C7 v- h( J4 X4 F+ i! _
                    ImageView
    ' W% {( f# I  w# U3 X- P/ z8 P0 ]                    android:id="@+id/img_video_stop"
    7 g- f; b5 Q' Z8 e                    android:layout_width="35dp"3 j# h4 g% Q, {4 W/ c) b
                        android:layout_height="35dp"4 e  m8 s" D( }" C; f# V% a
                        android:layout_marginLeft="20dp"
    - b# m2 \) h7 V: Y2 j                    android:src="@mipmap/ic_reset_36dp">ImageView>
    ( [& b6 J$ ?2 r( \            LinearLayout>6 F+ Z+ T  ^  C! |  ]/ d
            RelativeLayout>" D7 I3 {6 P  N* ~% k2 Q7 N4 z
        LinearLayout>0 s! m' J/ v4 s' @3 _! t
    LinearLayout>8 M+ G* h* Q- V7 o
    FileManagementActivity# i& c( e3 [/ K* @0 Z( H* S
    @Layout(R.layout.activity_file_management)' k1 f$ a  ~8 v6 k. b4 c+ I; `, M0 K/ H
    public class FileManagementActivity extends BaseActivity implements View.OnClickListener {* `7 A* g" Z6 N1 c
        private static final String TAG = FileManagementActivity.class.getName();3 C4 d3 v, i* |" J3 D  ]) W2 Y
        @BindView(R.id.layout_file)) I" [1 K7 l& F
        View mViewLayoutToolbar;0 D1 x# q* o1 E: Y! @3 D. K/ H/ P
        @BindView(R.id.tv_toolbar_title)
    , W! e" b/ S  {% ?7 |    TextView mTextViewToolbarTitle;7 [9 F: x- J: j3 s" J/ {9 B% g' b
        @BindView(R.id.ll_file)
    : M& S; x$ e$ {    LinearLayout mLinearLayout;# r# U# M' N; e, g
        @BindView(R.id.rg_file_management)
    ) I; @3 }+ i& a8 t    RadioGroup mRadioGroup;$ M$ i2 l' y! G3 t
        @BindView(R.id.rv_file_management)
    ) _+ Q+ |) t& ^# ?* G. `" O: B5 q    RecyclerView mRecyclerView;& t# y+ ~+ m+ y2 v+ W  J0 D; L
        @BindView(R.id.img_show)5 C/ X1 f8 }/ O+ w/ |& S" o
        ImageView mImageView;) |) k& D7 Y8 S$ E
        @BindView(R.id.ll_video_btn)) T5 M! m3 T( S6 `9 I4 T
        LinearLayout mLinearLayoutVideo;
    * x) L) ~3 V( f( w    @BindView(R.id.img_video_play)' l8 ^) Q9 l# V# Q
        ImageView mImageViewVideoPlay;) Y8 E5 u1 S6 R, J0 O  O
        @BindView(R.id.img_video_pause)
    % s1 L2 }& D; `9 Z1 G: w: Y) h    ImageView mImageViewVideoPause;
    # h; C) D8 L) s4 i' _: N. R" B    private FileListAdapter mListAdapter;0 X! h) J! \5 O, E( ~7 K7 y( W0 W
        private List List = new ArrayList();
    ( T0 f  y% k( e5 u6 |    private List mediaFileList = new ArrayList();5 n" Y* {/ ~2 x' O
        private MediaManager mMediaManager;% z5 r! v3 r# z& H
        private MediaManager.FileListState currentFileListState = MediaManager.FileListState.UNKNOWN;
    4 y8 S3 [7 ^2 V4 |, k    private MediaManager.VideoPlaybackState state;
    3 n. s" M, S+ C$ w, e8 y6 l, k    private ProgressDialog mLoadingDialog;1 K+ Y& ]2 e7 u  z  q6 o! L
        private ProgressDialog mDownloadDialog;
      I2 {# f- b  ]+ G    private FetchMediaTaskScheduler scheduler;4 j; g7 L2 W. q: y. u* T
        private int lastClickViewIndex = -1;
    / Z. ~3 }1 m( O    private int currentProgress = -1;+ ~/ }! p5 t3 d# l# j, Y: o
        private String SavePath = "";9 t  q3 V8 G6 f5 [% {. k0 r
        private View lastClickView;
    ' B- L0 u3 d8 V" b- l- X    private boolean isResume = false;# [( |, F/ ^2 e8 q
        private SFTPUtils sftp;
    7 t+ n4 K3 ]$ X# h    private SettingsDefinitions.StorageLocation storageLocation;
    $ _: \' l0 H6 [- p( k. L. X    @Override" B/ @4 g  `9 x1 P- ]) `$ V2 a
        public void initViews() {
    0 z% W8 C# ]$ H# E6 G: s; t' z1 B        mLinearLayout.setVisibility(View.VISIBLE);
    3 m2 F9 M, C, H, V        mTextViewToolbarTitle.setText("文件管理");
    1 P7 @: \7 q5 S        mImageViewVideoPlay.setEnabled(true);( J+ x, b8 M, L7 W+ x
            mImageViewVideoPause.setEnabled(false);
    ! b" e& \- G0 Q- T% x0 \9 I        mRadioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
    7 J9 b' Z: |( k            @Override+ D5 Y' u$ H/ {: L' Y8 J
                public void onCheckedChanged(RadioGroup group, int checkedId) {
    2 R' s) ?' z3 h% q9 {                List.clear();
    ) j) U1 \* ^) e" F9 n& Z8 c                mediaFileList.clear();
    ; i; x0 V# g2 J8 ]6 T% d8 Q1 t                switch (checkedId) {
    * u0 L# |% K& T8 R+ E# B4 v                    case R.id.rb_file_all:
    - a$ a1 q4 ]  \                        getFileList(0);4 k+ ^% u+ q; h3 y+ P# }! ^  y
                            mListAdapter.notifyDataSetChanged();
    * I( [; i5 L& k/ i$ B$ v9 B                        break;
    6 I" ]7 |* ?& o9 r" Y0 y                    case R.id.rb_file_photo:
    6 i2 {9 h3 q# d) J9 `$ n, G* _                        getFileList(1);
    1 y9 \7 q2 H0 @- o, b/ e' l% |# Y9 I                        mListAdapter.notifyDataSetChanged();
    % l+ O- \7 P! }* u                        break;
    % r- `, X1 T) n' i8 l                    case R.id.rb_file_video:: o# f' @9 T; Q% {  M0 P
                            getFileList(2);, F5 i8 B2 h8 [# ~9 X6 d' J7 w
                            mListAdapter.notifyDataSetChanged();
    + k/ I8 x, m3 s$ E/ H. m. y& Q                        break;
    & ]  e) {( J1 R; R4 n                }$ R, u; C0 [/ H5 y& E8 N* o# G: G4 s$ w
                }
    # u- h! B' S! o; Q1 L2 Q2 S        });% Z. D$ D3 Q% q
            LinearLayoutManager layoutManager = new LinearLayoutManager(FileManagementActivity.this, RecyclerView.VERTICAL, false);
    ' U8 O% w9 h) a' k. I: }' R        mRecyclerView.setLayoutManager(layoutManager);( i, d7 k  R- Z' c0 l5 t* j
            //Init FileListAdapter
    ; Y$ R- P+ x& o' T6 m, }8 u        mListAdapter = new FileListAdapter();% R" O# D- |6 p7 P5 E1 y
            mRecyclerView.setAdapter(mListAdapter);# U( n* Z; g1 d* j, ~3 p
            //Init Loading Dialog
      U) X; i+ O9 ~3 X( \        mLoadingDialog = new ProgressDialog(FileManagementActivity.this);3 Z5 r5 w# t1 G, W
            mLoadingDialog.setMessage("请等待...");
    : {% v/ c* ]% G- ^( A( b        mLoadingDialog.setCanceledOnTouchOutside(false);4 ~7 P* F/ ?" v" a  o
            mLoadingDialog.setCancelable(false);
    % D- H, I& B' q- t. j        //Init Download Dialog* ]- ]3 i; V' |" q2 X2 ?/ a% {$ u
            mDownloadDialog = new ProgressDialog(FileManagementActivity.this);
    , u4 F7 |2 G$ B3 ?  [; ^        mDownloadDialog.setTitle("下载中...");
    ' F; S2 @) D' |4 @4 V        mDownloadDialog.setIcon(android.R.drawable.ic_dialog_info);
    % r7 K- v& _2 Z- M4 K        mDownloadDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
    ; E- \& u: d( ~5 r# V& m0 z4 X        mDownloadDialog.setCanceledOnTouchOutside(false);
    " g8 X) O: I( x5 a/ N3 [$ x        mDownloadDialog.setCancelable(true);
    : M- q& V( i6 D- W! l4 ?        mDownloadDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
    7 t- x/ n# B7 @" U' o; v! _# d            @Override
    8 [4 ^! T3 |+ W7 L            public void onCancel(DialogInterface dialog) {: i- o6 {3 k$ c( P
                    if (mMediaManager != null) {
    ; [3 b; ^4 v! p1 K0 T                    mMediaManager.exitMediaDownloading();
    0 f: \( z, j/ f+ {                }2 W' ]+ I; l3 j9 e+ a. J" ?
                }* ~8 o+ j* {5 p" {/ A$ Z$ h4 J5 |
            });3 S  e7 y' p& S+ U
            sftp = new SFTPUtils("49.4.79.249","uav","uavHHch@YREC.cn");
    0 ~  f. P; b/ i/ P        ReceiverApplication.getAircraftInstance().getCamera().setStorageStateCallBack(new StorageState.Callback() {
    # P5 L) b5 ^" v, L9 G. U            @Override
    5 G- ?, W0 K" w+ l            public void onUpdate(@NonNull @NotNull StorageState storageState) {
    2 }+ U* \. r7 d  C4 u6 w+ Q                if(storageState.isInserted()) {
    , ^! t, J9 i2 ~5 s5 Z                    storageLocation = SettingsDefinitions.StorageLocation.SDCARD;4 [  O2 w7 \: [$ X) ?! m
                        ReceiverApplication.getAircraftInstance().getCamera().setStorageLocation(SettingsDefinitions.StorageLocation.SDCARD, new CommonCallbacks.CompletionCallback() {
      e: D' ]/ Y/ G0 H8 @6 O                        @Override
    7 m, ?; |. y9 y* a7 j% r, `5 E$ H                        public void onResult(DJIError djiError) {
    / K! w( o1 c: E( C) X                        }
    3 Z! @- p9 u/ d- W                    });! a5 M/ G' b2 L
                    } else {
      ^1 O- i4 \' d6 o2 F                    storageLocation = SettingsDefinitions.StorageLocation.INTERNAL_STORAGE;
    ; B: p  ]% T% B                    ReceiverApplication.getAircraftInstance().getCamera().setStorageLocation(SettingsDefinitions.StorageLocation.INTERNAL_STORAGE, new CommonCallbacks.CompletionCallback() {) _0 \# N% @" O6 F3 s! }" N, B
                            @Override
    5 ~3 C+ o: m9 n/ q8 z                        public void onResult(DJIError djiError) {
    " D1 S% w  E1 }3 D                        }
    # {8 N% r- F  D# ~8 i* a                    });
    # N" P" @7 p' @% v" x- q; L; `                }" L0 s/ F. o$ z7 N& ]6 j  G
                }
    , y& H; W* B9 x        });: O. z, [: ]" H: p* L
        }2 b. W8 x- n( A/ a) z9 ^7 a
        @Override
    * l4 Q, m3 W/ z5 m; q# b8 C1 [& y+ W    public void initDatas() {6 |- A, E3 _4 F1 p" e
        }
    ; C9 V5 {2 q% L/ w$ t- A    @Override
    # R5 y; I/ W: V3 g  l+ \6 ?. F* e    protected void requestData() {
    ' F4 m, g* M7 Q! r+ V& k2 K) b, Z    }
    - u' k/ f. N: m$ H$ ~# Y/ u/ `    @Override+ D' f; N& A5 A( M# [% \' O! q
        public void onComplete(String url, String jsonStr) {
    , @! y5 m1 z% W) c  H' P0 _        super.onComplete(url, jsonStr);
    ' H1 z  d& K) C        switch (url){! s4 l) M9 @4 x7 r' n* D/ j
                case POST_VIDEO_INFO:
    & |/ H" J0 d8 l) i                break;5 q0 n  J! {) k, S+ `
                default:' [# ~- x5 B( r1 e6 ~
                    getVideoJson(jsonStr);; S; y4 W2 v5 R! O
                    break;; d) R  s! g* r& N+ A
            }6 z* g" t3 {+ {4 T3 I
        }
    3 l7 p5 L0 ]/ @  K, ^% \    private void getVideoJson(String jsonStr) {2 @& ?8 l/ ]. t  w5 J( N  w
            VideoModule module = GsonUtil.GsonToBean(jsonStr,VideoModule.class);
    8 E+ W) o2 ~" J) `( Z; A. i        if (module.getCode() == 200 && module.getRows().size() == 1){
    2 S" O6 |% h6 Y' B' y9 ]            runOnUiThread(new Runnable() {
    / a5 F! l5 F7 n                @Override
    ( a! t" W/ K  i- Z                public void run() {
    $ e& A! M/ _( p9 e" y                    UpdateFileModule fileModule = new UpdateFileModule(module.getRows().get(0).getId(),"/mnt/uavFtpFolder/"+module.getRows().get(0).getFileName());
    " ?( i" B7 T% ~2 b                    http.getHttp(POST_VIDEO_INFO,"PUT",GsonUtil.GsonString(fileModule));
    , v' s/ ~% N1 a                }
    6 _2 Y" b/ \$ ?# `0 u) ~4 T$ v" F* `            });
    ) }2 Z# h8 L1 z        }
    8 N  H' t) O0 H! f( a: P  E! D    }2 W. h) y3 p, F9 t4 X$ A+ b
        @Override
    3 N4 w3 A6 ]6 r4 c9 O: C  t    protected void onResume() {& t- S/ T: t+ _) \% ^$ I
            super.onResume();3 v1 e' Z1 V% V
            initMediaManager();6 L6 W9 G% b8 D+ _
        }
    " y8 p2 `% V! Z' L! m# b( Z. p9 Z6 G    @Override3 S/ O5 z. d1 F. ^2 v( S
        protected void onPause() {% E/ l6 |7 K- e* Q
            super.onPause();& G' {8 r& W$ t
        }
    : y- w! r' r* i+ v* N0 k2 d    @Override* e% _/ x1 D6 P
        protected void onStop() {
    8 `7 U! J( t5 e- S- |        super.onStop();
    , D# R) c+ S9 N5 u+ A$ N    }3 {/ }( R# H. C$ @5 H

    ! C, t2 V( s+ I( ^    @Override- Y5 {; A3 M% G1 Z  U
        protected void onDestroy() {
    5 b. B0 r6 I2 X( d6 i; q1 Z        lastClickView = null;4 o5 C* Z% ]$ q' O. U. u
            if (mMediaManager != null) {% Z, T6 |1 U$ P  E# R1 `
                mMediaManager.stop(null);
    6 s$ M) p2 u; e* @: z            mMediaManager.removeFileListStateCallback(this.updateFileListStateListener);  y' O2 c/ C3 h) V
                mMediaManager.exitMediaDownloading();
    4 V# O2 N+ q, E; r2 x7 ]            if (scheduler != null) {
    / {& e5 V3 q% j' B8 s: F                scheduler.removeAllTasks();
    ) w, h. I. D# v" p            }' m7 y; q: v3 Q  _6 V
            }
    - \+ w  D/ Y* h5 p0 J        if (isMavicAir2() || isM300()) {% Y# x2 d( z- e" i, a
                if (ReceiverApplication.getCameraInstance() != null) {
    ; J6 W& e' |/ L  z! }" ~                ReceiverApplication.getCameraInstance().exitPlayback(djiError -> {
    ! H1 V3 v" e1 w5 ~. C# M: C                    if (djiError != null) {
    ! p1 `1 {  ?4 q! {( c                        ReceiverApplication.getCameraInstance().setFlatMode(SettingsDefinitions.FlatCameraMode.PHOTO_SINGLE, djiError1 -> {3 T2 I$ L& g5 r; D( ^; Y- }- x, D. G+ l# l
                                if (djiError1 != null) {
    , m% ~  g( O0 c6 J% [' ^$ z2 K# [                                showToasts("设置单张拍照模式失败. " + djiError1.getDescription());+ W) c2 P" b2 [: J7 ]4 h( b0 }
                                }
    ; E/ f* \) X! s* c* A( w2 V+ c                        });
    3 S# A$ d4 M0 B0 k- D                    }% S' |& j+ ]. `- X8 Q* N' j
                    });1 L! `9 |% X, `3 H
                } else {
    2 ^3 n7 V' G  K                ReceiverApplication.getCameraInstance().setMode(SettingsDefinitions.CameraMode.SHOOT_PHOTO, djiError -> {
    # O: F& {8 ~% h                    if (djiError != null) {
    + D2 K+ c8 k% _9 {. r( S) {0 y                        showToasts("设置拍照模式失败. " + djiError.getDescription());
    0 {# j) _" C% G$ n5 U+ e/ e                    }" X* @' g0 J; s8 K' T6 {2 [( G* T
                    });
    - T/ w! Z- v1 H& X' s            }
    ! C7 E6 G- _' k0 E        }
    ! \% O8 z8 ~) I. P/ K+ ~- [        if (mediaFileList != null) {; j+ D& I( k7 q
                //            List.clear();! {4 o/ H9 S3 n" N# y$ h5 T
                mediaFileList.clear();0 N2 ~( {2 j. _
            }2 e; J3 P* H% p2 u. s" g  b: c5 J
            super.onDestroy();
    9 C4 C" a; U1 b) j) }- b2 w5 @7 j    }$ j0 u3 P% G9 c. [. l( w4 L
        private void showProgressDialogs() {7 t. [5 m* \6 {& I2 y
            runOnUiThread(new Runnable() {
    7 M8 i' {" A! \3 i$ v            public void run() {
    , P# n9 ]- j) ^: y& e                if (mLoadingDialog != null) {
    5 @; L/ A: ]; g7 z- I9 ^6 m1 k                    mLoadingDialog.show();( e9 j( G9 F0 q
                    }0 O7 c- D+ ?- P3 ^2 o6 E! j
                }
    5 |+ X* ]: w1 E" r% e# k6 [) w7 L        });
    0 t# ], [" W$ L    }
    8 b" b. B) R3 S# I; l, c    private void hideProgressDialog() {
    4 T; Y7 h& u3 ]! J; i) A        runOnUiThread(new Runnable() {
    # ?  o2 m" ?% e* |            public void run() {9 F( r1 J# J$ N) Z
                    if (null != mLoadingDialog && mLoadingDialog.isShowing()) {. s2 ?% {- ]; r7 W  n
                        mLoadingDialog.dismiss();+ B) F! n! j9 L: A5 w8 C% B
                    }( }4 r* [$ [# @$ H6 J
                }
    ' v/ N4 D& d) f$ \        });
    . p8 F5 Z  b9 O4 l0 s, D; [2 y    }
    4 |1 X3 z! @& ?+ b9 G$ I    private void ShowDownloadProgressDialog() {
    ! @6 \- {* i' d  |  D/ r, p( c" e        if (mDownloadDialog != null) {
    : M2 {6 l1 m8 O/ Q            runOnUiThread(new Runnable() {
    1 ^2 O: Y$ Y, c9 \                public void run() {/ \& `$ K; E7 D$ |7 d1 S1 G
                        mDownloadDialog.incrementProgressBy(-mDownloadDialog.getProgress());3 H- e0 q+ \3 @! R: @( I1 \5 T
                        mDownloadDialog.show();& ]0 u4 L' n9 n" L% _
                    }( g: a6 d+ _2 e2 S
                });4 Q. T* |+ v$ v* X' S- A2 h
            }
    # _: Q; e3 h  A    }
    9 a4 F, j# E+ M* `6 r( M    private void HideDownloadProgressDialog() {
    # k- C2 z7 x- I  z        if (null != mDownloadDialog && mDownloadDialog.isShowing()) {
    , {8 V$ ~) `1 o5 R4 J8 r* w; A. K0 O            runOnUiThread(new Runnable() {# r% }& q. p' y4 H3 m
                    public void run() {
    2 b  j% V$ x  {1 n, V                    mDownloadDialog.dismiss();
    2 }" }: ^5 T! ^- \8 x' }                }
    # N7 ?* D  k6 Q0 M6 ^7 a            });
    * E" \( Q2 [5 Y+ o. h+ M        }
    : M. K7 U6 G5 r2 H9 z    }4 z2 \8 d/ {7 N) x8 X& m9 {0 a( p
        private void initMediaManager() {6 f$ E$ ^9 R1 B. F. x, y6 c# R
            if (ReceiverApplication.getProductInstance() == null) {7 H: O% r$ T1 r. h. ]" q7 B
                mediaFileList.clear();
    5 s- P, V( t4 B& f            mListAdapter.notifyDataSetChanged();! R% B% G7 ]4 O
                DJILog.e(TAG, "设备已断开");, [6 |' U& M9 _/ Z, [  b$ X% }
                return;
    * B$ r+ Q! D. V6 `) \        } else {
    3 @, k3 c" n0 A7 n1 R; ^            if (null != ReceiverApplication.getCameraInstance() && ReceiverApplication.getCameraInstance().isMediaDownloadModeSupported()) {3 }  _! E3 V5 v8 t# H) z5 D
                    mMediaManager = ReceiverApplication.getCameraInstance().getMediaManager();
    ' z& W' U, ?; `2 q6 \                if (null != mMediaManager) {1 h, V% Q. G- F3 s  P' u; P! f& x
                        mMediaManager.addUpdateFileListStateListener(this.updateFileListStateListener);, z. i# W. K; Y1 B
                        mMediaManager.addMediaUpdatedVideoPlaybackStateListener(new MediaManager.VideoPlaybackStateListener() {3 K% N: S" J$ t" h. J( x; B& ~4 K
                            @Override
    ( o! W# |. C- q9 {/ i                        public void onUpdate(MediaManager.VideoPlaybackState videoPlaybackState) {
    7 m$ u2 J$ F' B6 n5 r, L                            state = videoPlaybackState;
    * y+ `* j4 B9 G                            if (videoPlaybackState.getPlaybackStatus() == MediaFile.VideoPlaybackStatus.STOPPED){
    6 \$ X) B& G7 q7 E$ U# D' m                                runOnUiThread(new Runnable() {
    3 Q7 e& J5 L& t- f' R* o- X                                    @Override
      Z: A$ V1 E" p3 M/ _* E) ?                                    public void run() {0 L- B  v: K1 ]
    //                                        mImageViewVideoPlay.setEnabled(true);& k6 X! @8 b) e& E) S- y
    //                                        mImageViewVideoPause.setEnabled(false);$ r4 ^6 c6 D: v: o$ P
                                        }0 m$ H; j1 v9 Y
                                    });
    $ ]* z3 ?# G) K5 `                            }# K' E" E1 W* Q5 a. [
                            }3 o. i9 L$ z3 }5 i7 H
                        });1 U$ j4 Q" G# v) a
                        if (isMavicAir2() || isM300()) {
    * v/ }% t# v; ~$ p6 D                        ReceiverApplication.getCameraInstance().enterPlayback(djiError -> {
    ! l( g: X* ~! ^                            if (djiError == null) {3 [7 x2 ~: x5 ?( n0 P
                                    DJILog.e(TAG, "设置cameraMode成功");
    ) W" B5 L6 D! @1 n' E5 v: V                                showProgressDialogs();
    7 n. m/ y0 K' ]5 K0 g  E4 o1 H( N                                getFileList(0);: @9 ?3 W8 W) s; H
                                } else {
    0 D3 W# U8 h) Z( {! @, ?1 M                                showToasts("设置cameraMode失败");
    0 A, W, N3 |! L; P- a: F5 v8 r& ?                            }
    + H3 S! _9 u: t% P# R3 g                        });1 w& Q& M0 a: e$ H' |5 W
                        } else {
    " W( G6 A3 q4 Z) r1 @7 J, V                        ReceiverApplication.getCameraInstance().setMode(SettingsDefinitions.CameraMode.MEDIA_DOWNLOAD, error -> {( j8 `: D2 ]' @/ n+ \8 w3 m
                                if (error == null) {
    + W# i% n2 |# C" k7 f& `1 y6 m& ]                                DJILog.e(TAG, "设置cameraMode成功");
    / N6 D- [& ~9 l! q                                showProgressDialogs();5 `( v# j# Z4 U) L; J
                                    getFileList(0);8 U# B0 E) v) e
                                } else {% \& ^0 B% d9 D7 }& S- a( z
                                    showToasts("设置cameraMode失败");, b9 O, _7 }3 j1 g% i, j' H5 b
                                }% P7 @# l. Q& S+ ^$ S: ?
                            });% l" y. O9 h& U. M6 g
                        }' @/ N; a5 x0 B" s( A8 M3 Z
                        if (mMediaManager.isVideoPlaybackSupported()) {! W0 J0 G% e& }5 {& [
                            DJILog.e(TAG, "摄像头支持视频播放!");
    ' j/ P0 \- R4 q2 F                    } else {
    9 ?3 |5 r, ?# l# q& H                        showToasts("摄像头不支持视频播放!");
    ) t, T% C! r0 ~) D, v. p( T4 G                    }9 d" J. `, o  i" g, U$ `
                        scheduler = mMediaManager.getScheduler();
    # |4 I# s# E2 `/ L+ J, s                }& J: V& t  R. D$ b
                } else if (null != ReceiverApplication.getCameraInstance()
      D: H% c- j7 S) @1 ]3 b- I                    && !ReceiverApplication.getCameraInstance().isMediaDownloadModeSupported()) {
    - U- r; f  E" h# z, d                showToasts("不支持媒体下载模式");
    6 R: e) D2 D4 e5 r            }
    8 ?$ G( O5 t8 H0 J        }
    * }" ^. J7 I. O) }9 H' J# @- Q        return;
    3 I# Y; S. ]6 P# y3 O% k1 Y2 {    }
    % h9 v$ j- w) l- Y/ V6 C" Q    private void getFileList(int index) {
    8 S9 y, i$ Y3 U! B        mMediaManager = ReceiverApplication.getCameraInstance().getMediaManager();- J0 W) t. n: X- e3 v
            if (mMediaManager != null) {
    $ B9 K6 u0 J3 [/ \% K5 A7 x, B2 R6 W            if ((currentFileListState == MediaManager.FileListState.SYNCING) || (currentFileListState == MediaManager.FileListState.DELETING)) {
    6 O* P! _# t4 o# [) T                DJILog.e(TAG, "媒体管理器正忙.");( p3 }* c5 C4 ~
                } else {. y6 Y" u4 _) d
                    mMediaManager.refreshFileListOfStorageLocation(storageLocation, djiError -> {7 \) }6 S* I3 G
    //                mMediaManager.refreshFileListOfStorageLocation(SettingsDefinitions.StorageLocation.SDCARD, djiError -> {3 k2 Q& J, {7 |2 i+ f6 w2 U! Y
                        if (null == djiError) {
    ( J% o2 C; }% ^                        hideProgressDialog();% W% D7 Z/ C2 ]+ `8 `" t$ j
                            //Reset data
    ! Y* A/ Y4 _4 R. [. H% r                        if (currentFileListState != MediaManager.FileListState.INCOMPLETE) {& [9 f9 h7 H. [3 D3 q" O- n. {
                                List.clear();0 V) t. l: T$ \$ n3 n& y+ i1 |9 Q( J
                                mediaFileList.clear();
    & D* m, U) e& H" U- B' h  W                            lastClickViewIndex = -1;9 l' a" Z- ?" }3 U
                            }( S& R! M% _* u7 p
    //                        List = mMediaManager.getSDCardFileListSnapshot();. o9 G8 q, d9 D4 o
    //                        List = mMediaManager.getInternalStorageFileListSnapshot();
    # i9 B: l5 e0 s) Z' N  b: e2 T                        if (storageLocation == SettingsDefinitions.StorageLocation.SDCARD) {) l0 I( W# Y, e$ [, `' r8 o6 J* o
                                List = mMediaManager.getSDCardFileListSnapshot();
    9 P) x9 r( F0 N& Y. p. ^                        } else {5 s3 A: C1 ?2 N; y" |
                                List = mMediaManager.getInternalStorageFileListSnapshot();0 j" `8 l+ M/ h5 R6 ?
                            }1 d: v4 Z1 @& S0 A% U! E6 [
                            switch (index) {
    5 z  a* b  n4 g4 F2 F* \% ^9 i                            case 0:4 {% o/ D: h. w4 T7 s
                                    for (int i = 0; i break;
    / q! ^' H) W+ {! k                            case 1:
    ; t# R+ A" U) F% I1 e                                for (int i = 0; i if (List.get(i).getMediaType() == MediaFile.MediaType.JPEG) {
    8 c. D/ Z& |' }                                        mediaFileList.add(List.get(i));
    ( k0 t4 P: r- A" `5 ]2 _: w" ?, T                                        MyLog.d("图片名称:"+List.get(i).getFileName());
    ) d7 \* @  k$ d" v4 K) k                                    }
    ) H8 J  x- r8 `+ z                                }
    1 \. L0 I2 {, C9 b2 b                                break;
    # ~& {5 O+ T" p: T! e  d                            case 2:. v) c- z6 U) s8 |
                                    for (int i = 0; i if ((List.get(i).getMediaType() == MediaFile.MediaType.MOV) || (List.get(i).getMediaType() == MediaFile.MediaType.MP4)) {  ]( a! `" q$ t
                                            mediaFileList.add(List.get(i));. a* w; _# ]# D/ P
                                            MyLog.d("视频名称:"+List.get(i).getFileName());
    2 @; S" d6 q. A. Y0 b% R( L. q                                    }
    * |2 U6 M3 i4 r6 p7 D: K                                }& }) E. U" R. W6 S( d* }$ I
                                    break;% }' q2 f2 e, e4 P4 H5 m  v
                            }1 k  ~! g8 m$ ~5 n- X+ J
                            if (mediaFileList != null) {. G4 S  a) t# ~" C% v
                                Collections.sort(mediaFileList, (lhs, rhs) -> {
    ) v9 {. ^1 d/ _7 T, u  H                                if (lhs.getTimeCreated() return 1;3 P. ^1 n( ^6 ?2 n0 P3 Q+ r( l0 {
                                    } else if (lhs.getTimeCreated() > rhs.getTimeCreated()) {0 a1 \9 d: X5 w$ |
                                        return -1;" R* q3 @  ]+ E" o  L3 x8 k$ U
                                    }
    ' i6 P6 X8 x; z                                return 0;$ u" j# A) Y, S3 l( T2 w
                                });5 w  S1 t6 y' L: B$ f
                            }/ N* N, g. M9 C- V/ n/ w# H- G
                            scheduler.resume(error -> {8 v  t' C" ?* C9 x/ q
                                if (error == null) {+ c$ ]# ~% |" u; `1 h9 Q
                                    getThumbnails();* X/ i0 A. m3 k$ _
                                }
    0 _* w5 D3 D! |/ Z, M! j8 P% ^                        });! ^, v! [. @% ]; I2 H" G7 a6 x1 n
                        } else {9 y* ?+ j9 |$ y
                            hideProgressDialog();: l7 ]) M1 O0 j6 ^
                            showToasts("获取媒体文件列表失败:" + djiError.getDescription());9 m# P/ }. g7 \( ?& e, `% F' F, M
                        }
    ! m: M3 s# e+ g) G) `                });) d% E. {2 |" F# u
                }
    ! ^" @5 D1 k0 T        }6 m: j* |; u; n& H
        }
    * c8 x' J' t7 c, p2 s; k$ L- B$ q6 n    private void getThumbnails() {# R1 K* i$ P1 t% [9 v7 Z
            if (mediaFileList.size() 0) {
    % x& U5 q* P$ O            showToasts("没有用于下载缩略图的文件信息");# q5 l$ ~6 d0 h* W
                return;
    6 z# W0 Q7 T# q  H% H" L        }
    3 {; o$ I$ ?' R& y        for (int i = 0; i private FetchMediaTask.Callback taskCallback = new FetchMediaTask.Callback() {1 n* I. Y9 X( E8 R
            @Override
    2 L0 I; s. P: \1 w        public void onUpdate(MediaFile file, FetchMediaTaskContent option, DJIError error) {6 X1 l1 z2 U9 P" ?
                if (null == error) {9 \+ {7 j0 a# y( D4 Z8 X" V4 D
                    if (option == FetchMediaTaskContent.PREVIEW) {6 J- b2 s  t& T6 q( I, a! N0 z6 m0 w9 |
                        runOnUiThread(new Runnable() {
    0 O9 I& h3 w. v' Q! `" V3 l                        public void run() {
    " E4 \  @( y8 F; m. ]& D3 b7 ]                            mListAdapter.notifyDataSetChanged();9 n4 ~) E; n' B/ N9 b$ m
                            }
    7 @* [3 f2 }' n                    });
    : B1 f+ S! t5 Y                }; T  s& p. j; h5 k$ S
                    if (option == FetchMediaTaskContent.THUMBNAIL) {8 f8 R" X( w( u7 o9 w4 k
                        runOnUiThread(new Runnable() {
    " k0 R3 L; ]- a                        public void run() {/ g' `/ K! j3 q- ^, i% h8 Q
                                mListAdapter.notifyDataSetChanged();
    : X$ H9 G/ J. v1 B( y                        }* X1 N- n, q1 `: q, k6 C
                        });& y! |! P* ?, c& M3 b. a* M
                    }7 I9 o8 n  o& A0 k: ^2 v% P
                } else {
    4 x% m# |6 y: J                DJILog.e(TAG, "获取媒体任务失败" + error.getDescription());4 n( V, K0 h3 L0 |! I8 T7 k7 S
                }' Q2 P3 z5 ?1 O8 |
            }
    ' D& v- p0 {+ T9 k' o    };: d# U% w) ^. W! {( }) X, T. B: R' W
        private void getThumbnailByIndex(final int index) {
    , l1 b, h2 n% p2 w1 d        FetchMediaTask task = new FetchMediaTask(mediaFileList.get(index), FetchMediaTaskContent.THUMBNAIL, taskCallback);
    - Z( d5 ?8 ^1 a' h: d# y+ r$ p        scheduler.moveTaskToEnd(task);. s- }7 w$ }& l3 G( X$ z2 ^
        }
    6 [6 U0 F5 E! i    class ItemHolder extends RecyclerView.ViewHolder {  G9 H3 A* U9 M- M! Q, B' B2 v1 k$ G
            ImageView thumbnail_img;. l6 x6 {" o4 P, [. V% s  ^
            TextView file_name;
    1 l* E- p7 d6 V        TextView file_type;5 d: W; ?* C. s$ A' _
            TextView file_size;
    * }5 p8 {! O7 u' i& D( O, C        TextView file_time;
    . C$ a, A* }6 _  y' \        public ItemHolder(View itemView) {2 p0 a3 Q- y7 W( ]+ R) k
                super(itemView);/ C+ i5 B& U+ |7 [. x) e' J5 t& p
                this.thumbnail_img = (ImageView) itemView.findViewById(R.id.filethumbnail);
    3 m, a  F) ]7 {1 K& h3 I$ R) [: V            this.file_name = (TextView) itemView.findViewById(R.id.filename);. ~3 {' v- G2 w& v  d0 M' Z% [
                this.file_type = (TextView) itemView.findViewById(R.id.filetype);% }1 G4 n# N+ v
                this.file_size = (TextView) itemView.findViewById(R.id.fileSize);$ v- w" y# ~% z# g
                this.file_time = (TextView) itemView.findViewById(R.id.filetime);
    3 N' n6 M' K: f  |4 v3 F0 Q        }2 w2 r2 y; B6 R: H. q( {, c
        }# h! ]3 M( _# U: F8 E* F% v
        private class FileListAdapter extends RecyclerView.AdapterItemHolder> {
    9 @. m/ L4 U7 N        @Override
    " L: R) R' O# V0 ~        public int getItemcount() {+ N) E3 `5 {- q. x
                if (mediaFileList != null) {* y1 C* _5 w2 |) K5 o& n( d
                    return mediaFileList.size();
    ) ^1 n: Q5 W) `  b2 K# S, F- F            }
    # I) ^* b; f: E5 V8 j$ a            return 0;4 i1 a+ C% M7 ]6 D6 d- `5 p
            }. H4 C$ L. T. M0 W
            @Override
    8 j+ ]2 F/ [! ^6 G        public ItemHolder onCreateViewHolder(ViewGroup parent, int viewType) {; _3 b  a! v. x7 T9 u
                View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.media_info_item, parent, false);3 K; {' Y7 b( s" m
                return new ItemHolder(view);
    $ f, h4 X! `+ y        }. }5 P5 W2 @5 Y
            @Override
    + J  ]3 |& E: W" s" b        public void onBindViewHolder(ItemHolder mItemHolder, final int index) {1 @- e4 L! r# [% N
                final MediaFile mediaFile = mediaFileList.get(index);) |, R. l) ]3 I% h
                if (mediaFile != null) {- [. H8 A& ?$ R. c
                    if (mediaFile.getMediaType() != MediaFile.MediaType.MOV && mediaFile.getMediaType() != MediaFile.MediaType.MP4) {2 E4 o2 e# k* T1 }
                        mItemHolder.file_time.setVisibility(View.GONE);7 a& z( M, L; m
                    } else {! b% r- i9 {$ l* Q7 ^: }1 P5 Q- I/ j# O
                        mItemHolder.file_time.setVisibility(View.VISIBLE);
    " P' c; b% `5 U, G! d& J  F, p                    mItemHolder.file_time.setText(mediaFile.getDurationInSeconds() + " s");
    0 |; N, A) z( f8 l4 d  ~                }
      u+ M8 H+ V  e                mItemHolder.file_name.setText(mediaFile.getFileName());
    8 K: e& L( P- w; a3 U                mItemHolder.file_type.setText(mediaFile.getMediaType().name());) J. j0 D9 V8 M  J" g! p0 `% w
                    mItemHolder.file_size.setText(String.format("%.2f", (double) (mediaFile.getFileSize() / 1048576d)) + " MB");
    5 ]% E- \" U. i! A                mItemHolder.thumbnail_img.setImageBitmap(mediaFile.getThumbnail());" A$ x) J9 {* G
                    mItemHolder.thumbnail_img.setTag(mediaFile);
    5 u- E6 x! C  _8 {7 l$ V/ j. |                mItemHolder.itemView.setTag(index);
    5 ^4 y/ y$ m8 t8 R1 ^) E: H0 R                if (lastClickViewIndex == index) {
    , B! d' t5 ?) u, |6 S" k/ K8 _, N5 L                    mItemHolder.itemView.setSelected(true);
    ' T/ V4 y9 n/ @4 }                } else {
    " x/ A! b6 l. L( F/ S                    mItemHolder.itemView.setSelected(false);7 Z1 f4 I" [- \# Z
                    }& A9 b* z$ G$ Z+ B
                    mItemHolder.itemView.setOnClickListener(itemViewOnClickListener);
      c6 P2 K3 ^& Z- Y) |; f) j. ^5 Q" Q1 T            }
    8 d& G/ w7 Y! I4 `: X: H        }8 T/ D; |9 p8 N6 m
        }7 L  J7 ]& L6 [% [% f
        private View.OnClickListener itemViewOnClickListener = new View.OnClickListener() {
    , {% z, m+ g3 z+ W% s! T% r6 X        @Override- U( W5 M5 T5 ?" ~( r& E
            public void onClick(View v) {- u' X9 X6 W# f" @; x+ u8 {5 @8 {
                lastClickViewIndex = (int) (v.getTag());2 Z& Z! a8 O6 O4 D
                if (lastClickView != null && lastClickView != v) {
    - |3 }  ?2 f, Z8 S; _9 `                lastClickView.setSelected(false);
    " T! |! F' b) z* |, B            }
    / ^/ A, e% r! y4 G            v.setSelected(true);
    9 K, i5 a5 G2 S) X            lastClickView = v;9 Q% O# Y$ M- c# d
                MediaFile selectedMedia = mediaFileList.get(lastClickViewIndex);
    0 B1 {$ N" k# l, u            if (selectedMedia != null && mMediaManager != null) {
    * T. h" @: I* s                addMediaTask(selectedMedia);
    6 O0 k# ^/ X% U* [% N            }
    ) R; u0 _2 S; J% J- o- d        }2 P5 x  O1 n/ }  a
        };6 m3 T- E# t7 g  [" k& H
        private void addMediaTask(final MediaFile mediaFile) {
    0 T4 s/ n: P4 s3 U% o( |/ Z        final FetchMediaTaskScheduler scheduler = mMediaManager.getScheduler();
    # K7 s( y; c2 N" a7 S        final FetchMediaTask task =
    0 ?8 O* e6 x9 y: b+ S& z- o* r                new FetchMediaTask(mediaFile, FetchMediaTaskContent.PREVIEW, new FetchMediaTask.Callback() {) }5 l/ ^  P0 D0 _% y+ Q8 S8 R! l
                        @Override7 C( x& A4 d  z
                        public void onUpdate(final MediaFile mediaFile, FetchMediaTaskContent fetchMediaTaskContent, DJIError error) {  p9 O9 h1 U- E0 D6 M8 c, C. S* x" H
                            if (null == error) {
    8 C$ _  S5 U6 @2 i' m. U                            if (mediaFile.getPreview() != null) {8 Y7 u. B! m  g8 J" D9 W, Y
                                    runOnUiThread(new Runnable() {- L; J" U1 f! `6 L" T
                                        @Override
    9 L. M% D: J6 v: n6 y& {' ]1 _                                    public void run() {, F; k$ f; S5 Z( k& d8 \
                                            final Bitmap previewBitmap = mediaFile.getPreview();+ W2 h6 V/ N5 M1 e
                                            mImageView.setVisibility(View.VISIBLE);6 b; J2 V3 Y$ W& ^& U9 c: _
                                            mImageView.setImageBitmap(previewBitmap);6 t& w( g! d" |* p' d9 Q7 w
                                            if (mediaFile.getMediaType() == MediaFile.MediaType.MP4){; ^) v% ?2 I! B  @- U) i
                                                mLinearLayoutVideo.setVisibility(View.VISIBLE);
    4 k6 `  j  W2 k/ J                                        }else {
    & i' m9 l$ k5 N8 N) q* l                                            mLinearLayoutVideo.setVisibility(View.GONE);
    9 u7 L1 m9 m# U5 e$ ~. O                                        }
    ' k7 X$ P: _; F2 o2 n: |& [                                    }5 A3 _) y- Y8 N
                                    });
    & X6 Z+ s+ S# D  h2 N6 z                            } else {
    - ?( I; q; T4 U6 g                                showToasts("没有图像bitmap!");7 ~8 u) d; {5 \% k4 g$ s3 Q/ T/ `
                                }
    9 S8 S% w! H3 c% g$ ^                        } else {
    ; N7 R9 g& ?+ q+ a                            showToasts("查找图像内容失败: " + error.getDescription());6 P9 c& m. j" C+ @* l0 E, u
                            }
    ) z& c% Z# u# @! @/ P$ r                    }
    7 A- p5 X: y: P( i                });
    4 N, b  t9 M8 p. s/ y        scheduler.resume(error -> {, e2 e5 @$ G* T
                if (error == null) {0 m2 M9 J$ s4 {+ p5 r3 r- p
                    scheduler.moveTaskToNext(task);
    " R; F+ b3 T2 ~! U: [% C8 M            } else {  c5 o2 j# Z9 v2 a2 [( f) @
                    showToasts("恢复计划程序失败: " + error.getDescription());
    / K  y! h. F! P7 Q( {            }: L/ [4 ]% u: a" d' p6 O/ b
            });! l6 N: }) m+ Q) [0 h" h
        }$ x; i& Y- Q1 R0 x/ k/ v7 E7 o0 k
        //Listeners4 E6 u& k* \% O& `9 z) T
        private MediaManager.FileListStateListener updateFileListStateListener = state -> currentFileListState = state;+ z7 f" C% n( j3 C4 A

    ' q( v) ]- q, N% z) e    private void deleteFileByIndex(final int index) {
    7 L* j. K; r  S0 A) U5 W5 _        ArrayList fileToDelete = new ArrayList();
    ( J- a- w9 j+ T6 V        if (mediaFileList.size() > index) {
    ' W1 O* y- N, \            fileToDelete.add(mediaFileList.get(index));
    . O3 @% Y4 M1 y            mMediaManager.deleteFiles(fileToDelete, new CommonCallbacks.CompletionCallbackWithTwoParam, DJICameraError>() {, g; d5 f+ F5 f  O' ]% j, s
                    @Override
    / j: K( i; v7 N  [, P$ a5 _                public void onSuccess(List x, DJICameraError y) {5 y9 d6 O. f# w# F. i. ?
                        DJILog.e(TAG, "Delete file success");
    ( }1 J+ p, F8 A, ~# Z2 p  J9 s                    runOnUiThread(new Runnable() {
    # o. l% W! R6 t- q                        public void run() {$ q. W# N9 z! Q9 y3 u
                                mediaFileList.remove(index);, i) o, Y) L  N& [. a
                                //Reset select view/ o7 M& s) R. y
                                lastClickViewIndex = -1;: g: D: i( D! e/ N  _
                                lastClickView = null;# \$ O# Q5 s+ {9 m. A/ }! Z: G- V
                                //Update recyclerView
    ' o+ z4 _' D' Z1 ?                            mListAdapter.notifyDataSetChanged();- Q/ U9 C1 _2 O3 Z
                            }
    - M, Z3 B) g$ U% Y                    });+ p) K7 y4 a2 P+ G3 l
                    }; {/ u9 V7 p: M2 _3 Z
                    @Override
    - y, o$ Z  l5 o: D                public void onFailure(DJIError error) {
    8 _2 [0 D; C, `                    showToasts("删除失败");$ G6 ~, P' d, U4 K! ~
                    }) z, b) S" S2 J/ i% J. _
                });0 @5 |7 J- L6 Q: m! T8 z
            }
    4 d* a2 j/ C+ ^- t6 h7 E* Q2 R    }
    ; ?# W4 S0 _: P5 ^9 b4 H    private void downloadFileByIndex(final int index) {
    2 ~' m3 {5 L$ o% g/ N  l        if ((mediaFileList.get(index).getMediaType() == MediaFile.MediaType.PANORAMA)
    ; C& r6 @& {( @7 R                || (mediaFileList.get(index).getMediaType() == MediaFile.MediaType.SHALLOW_FOCUS)) {8 U( Z; \, }4 v8 a3 ?
                return;
    ) n: l) s7 X: g! @        }
    % c( @# ?4 z& U7 W. v7 |        if ((mediaFileList.get(index).getMediaType() == MediaFile.MediaType.MOV) || (mediaFileList.get(index).getMediaType() == MediaFile.MediaType.MP4)) {# y4 a, {1 [' v* \. |' m
                SavePath = MyStatic.FLY_FILE_VIDEO;
    1 ^/ X  x' B2 v9 H/ o! G3 @0 F9 \/ {        } else if (mediaFileList.get(index).getMediaType() == MediaFile.MediaType.JPEG) {; v8 `* b- L+ H" ~7 D4 g  h6 n
                SavePath = MyStatic.FLY_FILE_PHOTO;
    0 B' ?! ~1 V) c        }
      M/ R7 O6 i% B% U& K! ]$ u2 j4 Z        File destDir = new File(FileUtil.checkDirPath(SavePath));
    1 w9 X7 e% T/ _1 k+ N. S+ O        mediaFileList.get(index).fetchFileData(destDir,null, new DownloadListener() {/ ~6 }0 C, G( j3 Y8 `! h! G
                @Override9 U0 `5 P, t/ u
                public void onFailure(DJIError error) {
    6 b3 H$ \9 u% m9 I7 j; ?3 p                HideDownloadProgressDialog();7 W* V8 k9 q( k
                    showToasts("下载失败" + error.getDescription());
    % [1 S& f2 L8 }, H3 a  C                currentProgress = -1;
    & _$ I* a3 }8 a* i8 p$ k            }
    2 Z; L6 D9 R0 I, w$ t            @Override# z. t& X: T# _" J* c% b. m4 Z
                public void onProgress(long total, long current) {
    3 }3 r1 ^: t& m. o2 S* `3 }            }
    ) {4 g, B& W* q3 P            @Override  j8 D% E6 o" j! E8 S1 H
                public void onRateUpdate(long total, long current, long persize) {
    , ^% ~3 C% z0 R                int tmpProgress = (int) (1.0 * current / total * 100);
    + [+ z) i/ u# Z6 A                if (tmpProgress != currentProgress) {' Q+ g3 a" ]$ ^( {/ B
                        mDownloadDialog.setProgress(tmpProgress);; m0 c9 w1 L- T" z8 {7 \1 M
                        currentProgress = tmpProgress;
    7 t0 Q$ W; B2 v4 h( K; T1 a9 D                }" }, z0 r0 N7 K' e$ s
                }
    7 D* D4 o8 _" z2 V2 _' ^# E            @Override
    " J6 ~: c9 ?! _            public void onRealtimeDataUpdate(byte[] bytes, long l, boolean b) {5 [* N+ q$ V* ~  u4 N
                }( D2 g9 X  ?9 J" N% F) G# V- s% D
                @Override- g" w- p2 g6 j2 F4 B
                public void onStart() {- {4 A  R9 T2 K
                    currentProgress = -1;
    6 k+ B  ^% q) R! h, r& \4 g                ShowDownloadProgressDialog();
    + A+ s7 y: M8 P# ^            }/ E; ^$ }( p( f* u# U4 ~
                @Override
    9 \# {9 f9 V- A5 M4 E/ X  d6 c            public void onSuccess(String filePath) {, a  o$ a4 I& K" x( }9 t, l
                    HideDownloadProgressDialog();
    9 g& i, A( u% U! ?                showToasts("下载成功" + ":" + filePath);* K' o6 C9 z$ F# Z. {0 S. J
                    currentProgress = -1;' E% |3 y& D8 k
                }& q) i% E+ [2 G2 X  g
            });
    - o- t7 a. S* _//        mediaFileList.get(index).fetchFileByteData(0, new DownloadListener() {6 B; k+ Y( A' i  P) k
    //            @Override/ [0 v  D3 Q  G, f
    //            public void onStart() {
    * |/ r: i; [0 U7 o//                currentProgress = -1;
    4 q6 L) }( t% {0 f! d& P//                ShowDownloadProgressDialog();
    # X+ p" T2 K# x+ ?8 D//            }2 M0 C0 q9 F2 f% G
    //4 l+ f! z# l7 n4 F/ i
    //            @Override
    , I( Z: e$ o: P  }" ]" H$ z+ x1 R//            public void onRateUpdate(long total, long current, long persize) {
    , A& h/ K8 ~3 e. ~) S//                int tmpProgress = (int) (1.0 * current / total * 100);
    , B# W5 G' z) n2 p//                if (tmpProgress != currentProgress) {
    2 u, Q2 V: z/ T//                    mDownloadDialog.setProgress(tmpProgress);
    $ C" a! J$ g, V7 S5 S: a' P//                    currentProgress = tmpProgress;
    " R% W. E8 Z  _. R7 M3 `//                }
    ; {1 B& z+ d9 D5 O; K//            }
    5 X# D3 c" Y8 P0 ~5 u8 u//
    4 E/ R8 ]2 X# R8 `//            @Override6 t5 c; h2 I1 o+ L" j
    //            public void onRealtimeDataUpdate(byte[] bytes, long l, boolean b) {
    , j+ s" C# n, L, m$ U2 f: }//                byteToFile(bytes, FileUtil.checkDirPath(SavePath)+mediaFileList.get(index).getFileName());
    7 [3 U' q) [2 t# X& f% f' a//            }, f4 |' D, N5 G
    //
    & |  E5 f2 [/ t1 r; m+ t- [; }//            @Override
    ) }" u9 C3 n, p. S//            public void onProgress(long l, long l1) {
    5 A' S4 _# H$ G, [+ r* P9 G//
    1 E0 Q6 Z$ w* W//            }, W4 ?# T+ O7 |" v# O) @1 q
    //; I2 e1 |: F8 w. v4 P8 p! ^
    //            @Override8 h0 r% t' n6 ^( H5 u
    //            public void onSuccess(String s) {
    9 Y6 s5 t! m' ~1 O* }/ z9 [//                HideDownloadProgressDialog();# m# `/ \1 ^' ~' M) B
    //                showToasts("下载成功" + ":" + s);
      A! M5 f/ l0 D8 x% T4 D7 l) C6 }//                currentProgress = -1;" L8 s" F. Q9 g0 I  o
    //            }
    2 O5 h  n* F3 P//
    3 _2 l0 n9 c( x1 g& I/ f) ^//            @Override
    - G3 y4 D2 A; M6 C  {  H//            public void onFailure(DJIError djiError) {
    + N( f$ l0 Z0 P1 b$ ~//
    0 @$ G9 o8 L3 q* o//            }7 L+ B5 C' M% w7 x, T
    //        });
    1 o( ^  p+ L! `    }! H; y/ Y$ q: Z* |9 R' ?1 C
        public static void byteToFile(byte[] bytes, String path)$ H8 L0 a& f! h# z( X! R3 w
        {0 [, J+ n6 r3 L  `+ J1 ^$ s
            try
    & D% U' z2 e% G1 _) o        {' [1 x! u. N$ g% F4 @% [, }+ B6 ^- D
                // 根据绝对路径初始化文件0 n+ F$ `/ _9 X* ^
                File localFile = new File(path);5 r* ~# h' g: u) E1 {# i
                if (!localFile.exists())
    / H: b+ f  z& N/ y: U            {; g  V8 \/ x, y7 X- W% U* L
                    localFile.createNewFile();
    ( P" I5 v1 k7 c! \            }
    ' b( |$ g6 K( |            // 输出流
    5 k1 K5 z! u# T; c+ p3 P+ C            OutputStream os = new FileOutputStream(localFile);
    8 p- ^/ `# U1 v# |( Z3 K( i/ Y( I4 S( x            os.write(bytes);- `4 k3 A* r$ s* ~  l+ n8 `' r3 Y7 }
                os.close();- L: k: Z) z2 p& m/ R* e8 J* z% Y
            }$ _1 x3 T0 l0 V  }9 M" V
            catch (Exception e)
    $ x# {- B$ l6 p" Z  O        {
    $ m! \6 b. g% g% Y: n# K            e.printStackTrace();
    5 J( g  D: k( b* H1 u! X        }
    1 K: ^; L7 C$ w% y    }- x' x5 e7 l! s" @/ C
        private void playVideo() {
    6 J( U1 p/ a0 y- g. x' K$ e$ H        mImageView.setVisibility(View.INVISIBLE);* x# ^2 u8 L+ Z0 \, f; Z" W2 |# I3 J
            MediaFile selectedMediaFile = mediaFileList.get(lastClickViewIndex);
    + ?' T. s8 f2 p) S        if ((selectedMediaFile.getMediaType() == MediaFile.MediaType.MOV) || (selectedMediaFile.getMediaType() == MediaFile.MediaType.MP4)) {
    $ D7 A' D- f7 [$ S- N1 t            mMediaManager.playVideoMediaFile(selectedMediaFile, error -> {+ s# @+ A: b; r( F) `! o' Y
                    if (null != error) {& O" b6 \) }! a) W" Y) v& y
                        showToasts("播放失败 " + error.getDescription());1 U* T2 |8 x* L) U9 x
                    } else {0 d6 h. O" [2 K, |7 J: H+ `
                        DJILog.e(TAG, "播放成功");
    ' W( `9 s* o- r7 h' r# N                    runOnUiThread(new Runnable() {% y0 A: [. }- \% E+ I
                            @Override
    " a; g, J5 r2 l                        public void run() {9 F9 _0 `; @; ]/ @' C$ L+ l- x
                                mImageViewVideoPlay.setEnabled(false);
    + {/ W$ k% E$ o( q# `% Z                            mImageViewVideoPause.setEnabled(true);
    / l! G, L1 ?5 L2 ]4 Q                        }  M2 z7 e- P' B
                        });' a7 S! H  {, i* ^3 I) M3 y
                    }
      H. w1 o2 N+ q. q# e            });! v( q. M5 B# x) F2 x
            }  H* D# t, x9 R* N: b& {
        }
    ) n% H, Q, ]9 ]& x' T" ]6 x; f2 |6 G    @OnClick({R.id.img_back, R.id.img_delete, R.id.img_download, R.id.img_upload, R.id.img_video_play,# H7 I  P3 I8 B( i1 ~
                R.id.img_video_pause, R.id.img_video_stop})
    9 r3 Q1 V" y1 u# h% l- t  l    @Override
    " ~# c* F1 T: r# @! ^    public void onClick(View v) {
    ; Q8 P" n9 q8 S+ s! ?        switch (v.getId()) {! C& ~2 J/ N, \/ N. B
                case R.id.img_back:
    ! i: n$ M7 g2 c5 K5 l2 I                FileManagementActivity.this.finish();' ^& |' m! f! G
                    break;
    ! `: \( m3 A) f. Y* }( v  [            case R.id.img_delete:9 i$ L$ M" y% F5 D% |9 n
                    if (lastClickViewIndex >= 0) {
    2 T2 z$ [) l( z  V! B( d                    deleteFileByIndex(lastClickViewIndex);
    ) K' L6 D" U, l' i                } else {
    & r2 l2 P0 {( }# b4 q1 g                    showToasts("请先选择文件。");
    4 e( r7 U# S+ H; z6 {                }
    3 j" P/ z: F% o1 P# G0 d* b                break;/ `" [, R8 w7 T* Y0 C
                case R.id.img_download:
      M, W2 P% T, x: ?0 D                if (lastClickViewIndex >= 0) {
    % [& M  \  h* z% Z3 {                    downloadFileByIndex(lastClickViewIndex);
    / Q3 t) d5 _% ]9 @                } else {
    3 u1 N, I2 B1 N                    showToasts("请先选择文件。");
    6 v" L0 y- P( _) g+ }+ R2 e) t4 U                }
    / A5 M3 y0 w( D- F; `8 Z+ s; x5 R                break;4 j. b. g' h, ^  [9 Z5 G: l' d
                case R.id.img_upload:
    ; t; T& M7 V, k0 I! l+ H                if (lastClickViewIndex >= 0) {
    & n. }5 W! b3 y) q                    uploadFileByIndex(lastClickViewIndex);
    & |. R, I2 p3 J$ l6 A  c( G* i5 E4 s& g                } else {
    # q0 D7 c! a+ {                    showToasts("请先选择文件。");( }# \/ i( W9 v" q: \  @. i9 O# f
                    }
    ( I: s5 c' K- f- r; }+ K. P                break;' i1 n' k* m' L
                case R.id.img_video_play:0 {( }% G$ @) Q4 y) K
                    if (state.getPlaybackStatus() == MediaFile.VideoPlaybackStatus.STOPPED){; X- @' T  k: A5 E/ Y; C+ v
                        playVideo();2 z1 @9 d9 J1 G3 B
                    }else if (state.getPlaybackStatus() == MediaFile.VideoPlaybackStatus.PAUSED){' b: E- ?8 e1 K
                        mMediaManager.resume(error -> {( M* z, j; T: p: H( z: i
                            if (null != error) {
    $ s5 T+ \6 I. K) F0 E                            showToasts("继续播放失败:" + error.getDescription());5 d- g: J! P- `
                            } else {8 N  x! u: ^( b" V2 X9 F
                                DJILog.e(TAG, "继续播放成功");
    ) R5 U9 h5 S; u. {# c# P                            runOnUiThread(new Runnable() {
    ) {3 [: i4 M$ X1 i5 n. k+ R                                @Override
    . h* V! l9 F$ \% y" K+ N                                public void run() {% z4 B; L1 o6 N' \9 ]% _
                                        mImageViewVideoPlay.setEnabled(false);
      y% M- G4 _: Y# H* [                                    mImageViewVideoPause.setEnabled(true);
    3 A. U# k5 ?2 o1 b2 d                                }2 `/ O+ C. I1 G2 l! f3 g
                                });
    3 e7 L) o1 K$ Q# X                        }5 @$ y% ^5 a- S
                        });* u; z" w5 a' y, T4 S  ]% y$ }
                    }. N5 W6 U) A, g! ~! c
                    break;4 _. `$ A6 F% Y: q  X
                case R.id.img_video_pause:; g7 X: Z' K( O' t; E0 q
                    mMediaManager.pause(error -> {
    3 V9 l& O1 Q$ r7 W: x! y                    if (null != error) {
      J/ |0 |% a: w( b3 h                        showToasts("暂停播放失败:" + error.getDescription());
    . s& R% a1 Q1 g# V                    } else {
    ; E) |" A# R! i                        DJILog.e(TAG, "暂停播放成功");
    8 M5 Y( E, X/ ]3 K% g( y                        runOnUiThread(new Runnable() {/ ^& |! Q4 `7 _8 T
                                @Override
    " F* N3 J* @0 E                            public void run() {3 e8 L' h6 I( V2 y0 B" `& g
                                    mImageViewVideoPlay.setEnabled(true);
    ) d$ Y! l8 [1 h2 w6 s* J                                mImageViewVideoPause.setEnabled(false);2 l6 p& p0 h0 i  ~# G: X
                                }
    - x/ p) o$ m# \1 E                        });* \0 {( Y8 h( F- J0 O
                        }4 ?" D# l# a7 \. p
                    });
    ) h8 m' Y  b4 x) ?, O. [) @6 y0 C                break;
    , z% R' Z& {2 ], a& C  {            case R.id.img_video_stop:
    4 B% a6 W- L. f1 ~+ l$ P) T                mMediaManager.stop(error -> {% H5 S7 Q* v; L* z. }
                        if (null != error) {: u( _1 c9 u# @+ o" q
                            showToasts("停止播放失败:" + error.getDescription());7 V( L8 J" r  Y; @  [
                        } else {+ ?  _2 h0 e) l' t1 Z
                            DJILog.e(TAG, "停止播放成功");
    9 S; j% A& x4 V6 u; N, E* a                    }6 E! n9 o1 [! o9 e: _
                    });0 j$ H/ g: V# q# W) \
                    break;
    6 ?7 f. F' D2 u7 N8 i  l+ Q        }
    ' p: l4 h( {) w# X/ P/ `1 S    }
    # I! W5 \% m) l$ b, c' [; ~0 z3 c2 G    private void uploadFileByIndex(int index) {4 b) f9 F0 [. [" _! A0 W/ y
            if ((mediaFileList.get(index).getMediaType() == MediaFile.MediaType.MOV) || (mediaFileList.get(index).getMediaType() == MediaFile.MediaType.MP4)) {
    6 b6 a5 Q3 _4 n' G6 @. A/ g5 y            showProgressDialog("正在上传");
    * o, x( X' t) C0 _/ {" p- P& e            new Thread(new Runnable() {; J6 o0 d* o3 Y/ L" W/ @7 Q! S& C
                            @Override) ^% H1 |& J  Z- ]6 ]. C
                            public void run() {2 s7 E  |# O9 s8 q+ `5 A9 O$ ?
                                boolean isConnect = sftp.connect().isConnected();
    1 K: V' t/ i! `9 {! T. U" R% C                            if (isConnect){( L4 Z8 s2 f- S) d% G& G
                                    boolean isUpdate = sftp.uploadFile("/mnt/uavFtpFolder/",mediaFileList.get(index).getFileName(), FLY_FILE_VIDEO, mediaFileList.get(index).getFileName());) ?5 H7 I/ @' J) E6 a9 c5 ]6 O) J
                                    if (isUpdate){0 p# E$ F% x' o6 G- ~. E/ E
                                        runOnUiThread(new Runnable() {- z, L3 Y) A" c% Q
                                            @Override+ B, u# s$ ?0 ^4 Z  W9 U$ S* l7 |
                                            public void run() {
    ! s( j+ o; z7 e5 I  d                                            removeProgressDialog();1 W$ g* W- j/ K2 d2 w
                                                http.getHttp(GET_VIDEO_INFO+"?fileName="+mediaFileList.get(index).getFileName(),"GET");" e6 y/ D3 B& ]
                                            }5 Y/ }, {) E' V+ H3 X
                                        });: i/ B- P3 N' G
                                        sftp.disconnect();2 F+ w0 U3 J  L! u7 Q0 R: g* M6 _- y1 u
                                    }else {
    ) W4 a* U. G; w$ Z- a4 o                                    runOnUiThread(new Runnable() {
    ) y. f7 |$ }% q& H! [8 g                                        @Override5 R3 y9 X* e4 M& ?2 U
                                            public void run() {
    " t9 w$ w) y/ _4 D$ M5 P* q) O                                            showErrorTip("上传失败");. q' h% }% N- u2 z7 T
                                                removeProgressDialog();
    7 e" {6 u* I% T0 H                                        }" J& U8 [5 N) L
                                        });
    ! Z. D# C3 ^% }0 ~/ Q' K- ?( C                                }: `9 E+ c9 v1 Y
                                }else {4 E/ B5 b" i+ [; D
                                    runOnUiThread(new Runnable() {, d& v* u6 d: p# |' U+ [" Y
                                        @Override
    0 v- |: m. M( F0 }, X9 Z                                    public void run() {  G( x  T4 X  P: T" N% t) }+ n
                                            showErrorTip("服务器连接失败");) A1 {4 d' T/ W) q5 u0 l+ s
                                            removeProgressDialog();
    " e: Z$ J. W: D% y+ J9 t( s                                    }
    9 V7 q. D* V7 N" U* L                                });' x5 ]; I* Y0 E' B8 N
                                }$ g, i: U; w  f1 i# `, G
                            }* w6 n' o0 N, k: k  ^
                        }).start();. i2 p9 k. z/ k% d$ I1 K& V
            }else {
      h- v  o: g& S1 K            showToasts("当前仅支持视频上传,请选择视频文件!");$ S! q/ Y) Y; E% s# ~
            }% }: s0 o& b$ B( _# D* O7 @
        }0 A! T: B& D. y2 `
        private boolean isMavicAir2() {
    4 x4 m9 u1 L, S' ?7 Q3 \        BaseProduct baseProduct = ReceiverApplication.getProductInstance();
    + ?9 X, {5 S$ x# Z  Y/ ]& d        if (baseProduct != null) {
    2 R; P  I+ A* l' Y! H0 u2 J- K/ P% l            return baseProduct.getModel() == Model.MAVIC_AIR_2;. x3 u/ [) e) {& a# O# q# E# g
            }
    2 C7 O% a6 q8 C0 E, i! i        return false;2 S1 c1 k% p' p. _- I- F6 G
        }/ Q# o9 x" t. a
        private boolean isM300() {4 t* D, ^- o1 a  c
            BaseProduct baseProduct = ReceiverApplication.getProductInstance();
    # q( [- x5 H/ w3 C+ H        if (baseProduct != null) {9 i8 }$ P3 c, a" o) N  Y1 W
                return baseProduct.getModel() == Model.MATRICE_300_RTK;
    * |" k7 `9 q- s% ~$ I6 S$ n, K        }0 ], g" q' [  x8 T$ i
            return false;
    / m9 B" i5 S7 X2 ?$ a# R5 W    }  _* n" H# n3 |% G8 k
    }
    / _$ P, Z9 D% s1 x7 m9 ^% {运行后界面如下:( _, J# j, y1 N/ w

    jbk4phmi3so64011358950.jpg

    jbk4phmi3so64011358950.jpg

    . k; w% f9 ~3 g7 _) k$ V; L8 b8 [/ e$ o; z6 K4 G

    v5wq2lnnpdq64011359050.png

    v5wq2lnnpdq64011359050.png
    7 y, X8 w8 r3 w( Z
    往期推荐LabVIEW OCR 实现车牌识别. o4 }. g2 V) \* b
    和12岁小同志搞创客开发:有意思的激光切割技术5 o# ^2 \8 A$ R3 q* F3 k' i
    JavaScript+TensorFlow.js让你在视频中瞬间消失) S. _! Y. x6 }
    使用OpenCV测量图像中物体之间的距离$ d1 I* D. B( h0 z( \* r% R
    全网仅此一篇:工业级压力传感器设计及实现
    $ l+ u4 F: Z4 A9 ?/ @! C6 S! E
    4 v8 p: x+ B5 B; A$ b

    jvdg1ytc4o564011359150.jpg

    jvdg1ytc4o564011359150.jpg

    ! W8 e/ a: v) K! ~1 Z& }# ?

    mw3bqzgjnuv64011359250.gif

    mw3bqzgjnuv64011359250.gif

    * K' X' {" u1 z( z/ B点击阅读原文,更精彩~
  • 回复

    使用道具 举报

    发表回复

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

    本版积分规则


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