电子产业一站式赋能平台

PCB联盟网

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

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

[复制链接]

1001

主题

1001

帖子

8803

积分

高级会员

Rank: 5Rank: 5

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

0lshyu0if0e64011358650.gif

0lshyu0if0e64011358650.gif
$ _" w  O1 D' [3 I7 x
点击上方蓝色字体,关注我们
9 O8 F& u  [" f3 Z- j3 {. w: P1 |+ ?4 I0 X* j7 L# g. i+ [
上一篇文章(基于Mobile SDK V4版固件开发大疆无人机手机端遥控器(1))因为时间原因介绍了一部分内容,如果已经完成上一篇内容的操作就可以进行下面功能方面的制作了。自己开发的APP功能不是很多,但是已经将大疆无人机的常用功能进行了结合,同大家一起进行学习~
5 ?* C2 ~8 v" B( S4 F1- U. ]& J7 i" n" z
应用程序激活与绑定. c7 H% D5 u: {1 i$ \) a! S
如果在中国使用DJI飞行器固件,则需要使用该用户的DJI帐户激活控制DJI飞行器的移动应用程序。这将确保大疆能根据飞行器的地理位置和用户个人资料,为飞行器配置正确的地理空间信息和飞行功能集。激活系统的主要是:% E, t% n: ?2 _! M, y
  • 中国用户必须在每三个月至少登录一次DJI帐户以遍激活应用程序。
  • 激活信息将存储在应用程序中,直到用户注销为止。
  • 登录DJI帐号需要连接互联网。
  • 在中国境外,SDK会自动激活应用程序,无需用户登录。
  • 另外,中国用户必须将飞机绑定到DJI官方app中的用户帐户。这仅需要一次。如果未激活应用程序,未绑定飞机(如果需要)或使用旧版SDK(
    9 w9 u0 x0 n! ]; K

    ' U) N) Z9 {! K, W% }2
    * k  h7 C3 n  Z7 V5 _9 }  t为应用程序创建UI编写MApplication、ReceiverApplication和RegistrationActivity文件(此处粘贴部分代码)。
    9 E: [& ~- b& K, ^2 D! Upublic class MApplication extends MultiDexApplication {- @/ A+ X9 i( x8 F( o' ^
        private ReceiverApplication receiverApplication;
    ) G; Z' q5 O- r* L    @Override
    # R' [4 l8 S& W" Y/ X4 @    protected void attachBaseContext(Context paramContext) {
    # X: D3 f: F1 \, y* X9 H0 t        super.attachBaseContext(paramContext);
    9 S/ W! j# ~+ ~( w: I        CrashHandler.getInstance().init(this);
    ) k. m2 j4 l: J- L        Helper.install(MApplication.this);4 m! l# f* v" ~6 D0 o7 @
            if (receiverApplication == null) {
    2 D, I& a. V7 [) H            receiverApplication = new ReceiverApplication();
    ; _* O8 Q+ \  l2 Q! m            receiverApplication.setContext(this);" R0 Y( ^/ j$ i+ [" R% j7 T9 k
            }
    ! ~6 J9 V$ ?! Y& e4 p& @    }$ B' X5 x" u- v& G
        @Override  D: E. z5 [$ j7 A1 N' b% D) V/ q- k
        public void onCreate() {/ _2 C3 }6 a) J. a
            super.onCreate();
    $ r: g% `2 N5 _4 Y4 {  o1 K        receiverApplication.onCreate();
    2 ^7 P3 e3 m: V$ K% g    }: v: y+ b' a0 j- U7 ~! h
    }
    - A- u+ Q4 p- A上面的代码实现了绑定当前APP,将后续需要用到的类函数封装到ReceiverApplication 中,在ReceiverApplication 中也能够进行账户登录的操作。/ l$ L0 ~8 w5 K' f) A) i
    public class ReceiverApplication extends MultiDexApplication {
    : M$ t: W9 _' n9 G' }2 ~    public static final String FLAG_CONNECTION_CHANGE = "activation_connection_change";. c. L2 {) G4 S6 [
        private static BaseProduct mProduct;
    " ~% N1 ^% g& b$ {    public Handler mHandler;
    3 }8 G+ c2 _8 w# O/ \% \    private Application instance;4 T. ~+ I! m" e1 S2 B$ d" ]3 e
        public void setContext(Application application) {
    ; L5 V, G" B. k; V0 k1 A        instance = application;5 B+ S! Y% b9 d0 N/ }4 ]
        }' N- s# C$ `8 I% C" E& m; P
        @Override
    : [) z3 X7 l2 F- k) I  n5 X/ f    protected void attachBaseContext(Context base) {$ n. Y  e0 o$ M4 K- A1 k+ u; c
            super.attachBaseContext(base);  g: C9 g" q" ]# s2 H
            Helper.install(this);) Q$ e2 ]/ ?, ^7 c" ~2 S) m/ f- I; p
        }- c( Z( r( q: {5 a/ \% J
        @Override
    - w3 `9 w+ D. n! m/ o+ d1 k8 h    public Context getApplicationContext() {
    4 h% w1 M, w8 {        return instance;
    " t! e/ n- F7 }$ @8 o    }
    * u8 Y* G& f& u$ _( }) ~    public ReceiverApplication() {
    / X: y8 X; k, R    }! _, h& P' P% @  c  T" @
        /**
    & `1 b" q0 p' o/ }     * This function is used to get the instance of DJIBaseProduct.
    4 q: R" }0 ?0 `0 [9 s6 A     * If no product is connected, it returns null.
    * b6 s( b% k) Y( g3 p# |9 Z7 u     */) [" d4 P* C1 b/ B1 i
        public static synchronized BaseProduct getProductInstance() {
    8 K% W0 F0 V7 V7 K, z: g0 l$ n2 H        if (null == mProduct) {
    ! v4 e% j( c" }9 x  K. A            mProduct = DJISDKManager.getInstance().getProduct();
    / H" H( E0 C$ o        }
    1 D3 I; m5 N' U; Q        return mProduct;
    : w$ [2 r1 s2 \" X    }& ^$ L+ S% }+ `: P* z
        public static synchronized Aircraft getAircraftInstance() {
    9 e  C% |0 H0 {. m% ~; `) o1 l        if (!isAircraftConnected()) return null;
    8 H- A1 b! X4 O5 y        return (Aircraft) getProductInstance();
    $ y; Y* j, H) f9 H, S. O* _8 Z) N    }
    3 N- |: C" O2 c- k0 b    public static synchronized Camera getCameraInstance() {
    . x5 N5 O' U, f        if (getProductInstance() == null) return null;
    6 j5 p+ z/ ]; Q& H        Camera camera = null;
    - @( y2 R9 H" A. S: q        if (getProductInstance() instanceof Aircraft){
    : s7 S, d. X+ W7 E. Q            camera = ((Aircraft) getProductInstance()).getCamera();
    $ s' b, u/ Y2 p        } else if (getProductInstance() instanceof HandHeld) {( }6 |0 i8 o# Q- T- l
                camera = ((HandHeld) getProductInstance()).getCamera();
    7 s1 r. X' s3 e& F1 o        }" K& b7 g+ a) ?+ k- \4 c
            return camera;
    % H/ @1 F5 @: T' F$ E    }/ S3 s4 a% c# [
        public static boolean isAircraftConnected() {* z7 A" {; L- T' f$ q: Y
            return getProductInstance() != null && getProductInstance() instanceof Aircraft;
    ) ^) z1 p4 ]" `/ |8 s% W. t    }
    9 E  N$ n6 a) H' X9 _* ]8 `    public static boolean isHandHeldConnected() {( C7 ?1 l. J8 x; O  ?
            return getProductInstance() != null && getProductInstance() instanceof HandHeld;
    * {$ j+ F1 o. d# H    }
    & q6 d+ l/ w- K) ?    public static boolean isProductModuleAvailable() {+ E/ W8 ?" f$ ^" n( ~
            return (null != ReceiverApplication.getProductInstance());' w! ^1 [' ?# r
        }( z% X# v+ K* v% W0 k4 J
        public static boolean isCameraModuleAvailable() {
    6 T. C% R: x4 }2 V  k3 o" t7 U7 \0 @9 k        return isProductModuleAvailable() &&4 g' u/ h* w5 G: w$ p: b8 _
                    (null != ReceiverApplication.getProductInstance().getCamera());+ m* ~  f' I% K' w3 i$ S9 r0 g" L
        }; d% @7 v# M$ ]
        public static boolean isPlaybackAvailable() {0 e+ [; z- j; h5 C( Q6 y7 Y6 \
            return isCameraModuleAvailable() &&
    . ~! m. b: u, s. p+ g* f                (null != ReceiverApplication.getProductInstance().getCamera().getPlaybackManager());
    4 O0 }, F2 L( N9 s- }( K9 z# S& ^" E    }# z" e. j7 q/ |2 N5 ?# x
        @Override/ b8 d; H9 q- I
        public void onCreate() {
    0 ]) f: ^% {8 n  b5 \; |' I        super.onCreate();; h. g4 Q/ n) S  d
            mHandler = new Handler(Looper.getMainLooper());' w2 h% W( r$ z; e7 R3 _! F; p
            /**- d, _, ]+ d" U5 Y2 Z
             * When starting SDK services, an instance of interface DJISDKManager.DJISDKManagerCallback will be used to listen to
    6 n4 b9 Z+ E5 k8 ]3 [         * the SDK Registration result and the product changing.* K. s6 ^* l) I( `
             */! X8 V$ l% t" o! P
            //Listens to the SDK registration result* u- @0 ?3 I' _' e4 ~) Q
            DJISDKManager.SDKManagerCallback mDJISDKManagerCallback = new DJISDKManager.SDKManagerCallback() {' f5 D/ h0 F8 t8 Z/ {
                //Listens to the SDK registration result
    # o2 a, q/ t5 K1 X            @Override% Q& ]* D3 Y! Y  c
                public void onRegister(DJIError error) {
    / t& [1 r* h! Q                if (error == DJISDKError.REGISTRATION_SUCCESS) {3 {) t, W0 [" W3 n
                        Handler handler = new Handler(Looper.getMainLooper());" ?& x* G7 p( w" \
                        handler.post(new Runnable() {9 T* _/ h9 Z9 n( q2 W
                            @Override# m3 i; P+ D$ ^, B# p8 C
                            public void run() {9 L' E; I$ Z8 {$ I& `% E3 E" J
    //                            ToastUtils.showToast(getApplicationContext(), "注册成功");
    . Z! m9 }# F9 s$ C//                            Toast.makeText(getApplicationContext(), "注册成功", Toast.LENGTH_LONG).show();0 x# U1 v* @; |* X" q& i
    //                            loginAccount();# z0 B6 \/ Z* |) W, r2 ]9 h7 Q
                            }
    - C& l/ m9 X9 t4 Y: r& V+ L2 q1 I                    });
    & p, p% ^7 U' A6 D                    DJISDKManager.getInstance().startConnectionToProduct();+ D" ~# D) \! u& }, r- K: d
                    } else {8 b8 U8 j, Y0 E& i
                        Handler handler = new Handler(Looper.getMainLooper());
    4 f6 z3 C' Z. p) S5 w1 C8 P                    handler.post(new Runnable() {
      m9 k- C0 [2 [; K                        @Override
    # n/ O7 M! y* m  Q' V  A8 a$ R                        public void run() {. T; D+ m# D2 B5 {# w: k* C) ]
    //                            ToastUtils.showToast(getApplicationContext(), "注册sdk失败,请检查网络是否可用");
    ( A' x8 W% k. l# z2 b% x//                            Toast.makeText(getApplicationContext(), "注册sdk失败,请检查网络是否可用", Toast.LENGTH_LONG).show();6 W; O- ~% P0 u1 k6 k
                            }
    . O8 r5 e5 P& u4 w: b% J# J2 ~                    });" ~5 Y7 |3 b( ^% m* v
                    }
    ; B3 J, q+ h. {2 c3 y0 L9 y                Log.e("TAG", error.toString());
    6 ?8 h& b1 Z, z0 ^* V: i! z# ^            }' }: k. B' x; |& X8 X- w
                @Override
    8 x- H: I* e1 R) M            public void onProductDisconnect() {
    * y2 D8 ?$ e6 Y. p( U$ N5 t                Log.d("TAG", "设备连接");
    1 Z  C$ {$ x) _  q# ~! E                notifyStatusChange();
    ) N6 h6 ?# J6 `. }            }7 U. Y7 F0 @8 M8 f5 i1 \3 g( F
                @Override
    ( Y) e) y, I) }* \3 g9 {# }; O            public void onProductConnect(BaseProduct baseProduct) {. B+ {* q3 I! g7 R6 [) D4 Z" b& N
                    Log.d("TAG", String.format("新设备连接:%s", baseProduct));
    " i- F6 W1 ^: n: {2 S5 f5 r                notifyStatusChange();* i7 @1 t, z! w  |  l6 g" ]
                }. ~8 ~/ a5 c. z. y
                @Override
    5 l- ^, I9 g/ @- z2 _* U. n            public void onProductChanged(BaseProduct baseProduct) {
    7 w8 T. U5 e" U9 M            }( X# l3 ]/ u% e' y6 T  N
                @Override) C, G# Q. P; M7 X( G# \3 q5 Z
                public void onComponentChange(BaseProduct.ComponentKey componentKey, BaseComponent oldComponent,( Y8 A* f/ @' h$ J+ c6 V
                                              BaseComponent newComponent) {
    3 `. R3 o' f% j6 r0 U. C; C                if (newComponent != null) {  Q2 }4 q, y1 J( z4 G- F: g5 _; Y
                        newComponent.setComponentListener(new BaseComponent.ComponentListener() {* ^( Y4 G6 u4 U7 e  q  d: o
                            @Override
    + x! |+ W1 G4 a' V0 l                        public void onConnectivityChange(boolean isConnected) {" |. u1 p. z4 D. f* H- }7 d
                                Log.d("TAG", "设备连接已更改: " + isConnected);4 L  R& n5 {" _  ?; @+ f7 l
                                notifyStatusChange();
    3 u# _: |. n; X                        }
    - ^( O7 O4 w0 D: m$ C                    });1 m) h  h( ^  `3 S
                    }' M9 X8 W+ W/ _: J5 }
                    Log.d("TAG",
    7 ]9 o7 J8 ?( S5 ?7 O7 ^                        String.format("设备改变 key:%s, 旧设备:%s, 新设备:%s",
    - O, j; @' t, ~; [4 u9 O: d9 E* |6 \& n                                componentKey,: s. v. H- f4 v2 _% x4 v4 q! g
                                    oldComponent,
    0 u3 {! x. w7 Y0 |. Q                                newComponent));
    ; s$ W6 l. T- p" ~- I( j- [            }
    4 C; `# t5 s; |. G. N/ c# |( O            @Override
    + o/ S. ?3 Q* U( f* W            public void onInitProcess(DJISDKInitEvent djisdkInitEvent, int i) {
    ) Z0 j  v- F& j* v; j$ l2 s$ G            }+ M9 l! P0 z3 N5 `( r: W
                @Override
    ) |- f7 h* |. T, x  I. W, ~            public void onDatabaseDownloadProgress(long l, long l1) {, Z  Z/ l- j3 O, n4 n0 z. _
                }8 {/ n# x2 z2 v1 b5 A& g' \
            };, F6 l) s; T( T5 E+ ^8 ?; N) E
            //Check the permissions before registering the application for android system 6.0 above.  o  g% R! Z/ L, P: O; _" v
            int permissionCheck = ContextCompat.checkSelfPermission(getApplicationContext(), android.Manifest.permission.WRITE_EXTERNAL_STORAGE);
    6 K& Q; w+ H; N# g0 D5 {        int permissionCheck2 = ContextCompat.checkSelfPermission(getApplicationContext(), android.Manifest.permission.READ_PHONE_STATE);9 W( B7 A9 f6 S: O
            if (Build.VERSION.SDK_INT 0 && permissionCheck2 == 0)) {
    ! j: o0 u) C) c9 v            //This is used to start SDK services and initiate SDK.
    3 @  {. J, }* k            DJISDKManager.getInstance().registerApp(getApplicationContext(), mDJISDKManagerCallback);3 p5 e" P; O1 \
    //            ToastUtils.showToast(getApplicationContext(), "正在注册,请等待...");# [- W* j9 V4 R8 X
    //            Toast.makeText(getApplicationContext(), "正在注册,请等待...", Toast.LENGTH_LONG).show();& q  t+ q4 x# S" e. A1 w2 N/ ?
            } else {
    1 \- a7 C' C. E' v//            ToastUtils.showToast(getApplicationContext(), "请检查是否授予了权限");! y" ]% v' S& o; f6 R/ ~
    //            Toast.makeText(getApplicationContext(), "请检查是否授予了权限。", Toast.LENGTH_LONG).show();3 [5 ^* Q1 V; _
            }* u1 R5 H$ d) p# \2 j! \
        }
    - u+ t. o2 |7 r* {    private void notifyStatusChange() {0 b' y: s; H' v; @; {
            mHandler.removeCallbacks(updateRunnable);1 N' G3 t/ G3 }: ~( M6 s
            mHandler.postDelayed(updateRunnable, 500);
    & G3 e6 ~; N3 K    }. H6 p7 m! {' K2 _. ?5 |
        private Runnable updateRunnable = new Runnable() {
    , K" A$ h! @1 S* `) Q        @Override
    5 r3 j9 Y0 i( g# l& S) k( w        public void run() {
    ; e4 U, B/ p5 z7 B  W$ `            Intent intent = new Intent(FLAG_CONNECTION_CHANGE);
    . C% F3 q5 ^" B7 [# i0 E! K9 ^            getApplicationContext().sendBroadcast(intent);
    . E( [* b' a- t        }
    & |# T! B* {" N7 G& l  `    };
    - d1 d' J. r9 h9 I$ r+ M}
    ) T. A  p8 |, b; {1 Q* w上面的代码是对BaseProduct、Aircraft和Camera类进行实例化,在后续使用中不用再去进行重复的实例化工作,减少内存的消耗。
    ; Z* L7 V( g$ W2 D% A( M5 j8 E; S@layout(R.layout.activity_registration)6 o, }' N$ W) S9 z
    public class RegistrationActivity extends BaseActivity implements View.OnClickListener{( n4 `0 R, ?/ p  ?1 ^4 Y3 V
        private static final String TAG = RegistrationActivity.class.getName();: O$ @7 J1 l) ^3 P3 h$ A
        private AtomicBoolean isRegistrationInProgress = new AtomicBoolean(false);
    + p: e; O: H4 o& ^) @; N    private static final String[] permissions = new String[]{* S6 s: J8 g8 q( W. R2 C  y
                Manifest.permission.BLUETOOTH,
    * r, Q' `9 k: C0 W* X! @# W: A9 }8 O            Manifest.permission.BLUETOOTH_ADMIN,
    6 p" X- Q" k# M; H            Manifest.permission.VIBRATE,
    # G  d& P- g4 p' u, o5 T) s  `            Manifest.permission.INTERNET,
    + t( B# D4 [( u* H# x9 ^* }5 u            Manifest.permission.ACCESS_WIFI_STATE,; t/ \, M8 l" U( b' O
                Manifest.permission.ACCESS_COARSE_LOCATION,
    3 ~: D7 n* Z/ R+ I- i  }            Manifest.permission.ACCESS_NETWORK_STATE,
    , U; l4 I+ B; G; @6 v            Manifest.permission.ACCESS_FINE_LOCATION,
    ; L9 s6 R: b5 f) o  b            Manifest.permission.CHANGE_WIFI_STATE,; n0 Q6 F+ t4 g6 S& }
                Manifest.permission.RECORD_AUDIO,
    % x: c+ B7 ?( z1 Y' j/ V. q, J9 x" U            Manifest.permission.WRITE_EXTERNAL_STORAGE,
    9 Y* w3 C8 g. \% W& Y) B            Manifest.permission.READ_EXTERNAL_STORAGE,' \, T4 ~- a: Z, ~  x
                Manifest.permission.READ_PHONE_STATE,4 q" ]0 z  C9 X
        };
    ( B# W- D) E8 e( G$ L
    8 ]5 D! {8 k) U! `+ {    @Override/ n7 Z6 C; ?2 x; U+ F- X
        public void initViews() {" d2 ]7 q* ^9 s6 ?& e4 w8 C4 c
            isPermission();
    9 r$ T; e4 x2 r$ A; c, i) c        IntentFilter filter = new IntentFilter();
    ( G7 T. k9 h! [        filter.addAction(ReceiverApplication.FLAG_CONNECTION_CHANGE);3 |3 G  n* d( H( B' [+ @
            registerReceiver(mReceiver, filter);
    4 _: b$ y; P- ^$ g" b5 W    }
    ( b" y$ c5 w( Y  w3 N- n2 L9 [    @Override
    / ~  r( O1 J- Y+ _" C, C" Q7 R    public void initDatas() {2 n" m! Y3 w/ r4 }
            startSDKRegistration();
    , I; E* `# [% d& T* u) X    }. t- A; h# N4 p& q3 e
        @Override
    ! n4 ~( Z4 M. [( f5 f0 x    protected void requestData() {
    - j$ h( N/ w9 G8 J. I; K) v8 }. x        
    " M7 r# X1 A: a1 ~5 U! K8 G+ N- Q+ m    }4 h8 {) R) s' ]! J
      r9 U( p7 _1 x7 ^  x' L, @
        @Override* L' E- P- N! a
        protected void onResume() {) H  a- t! T% w
            super.onResume();$ R/ w6 r" D5 b) M  \1 A8 P2 T
        }3 ~2 \' N0 j' O+ z
    3 Y& e3 s% Y# H6 V
        private void isPermission() {9 @5 D5 Z" X2 P1 j. A& ~
            requestRunTimePermission(permissions, new IPermission() {
    0 E/ b/ e  R4 l+ E1 E            @Override
    * Z" V7 `- t( K, Z2 H            public void onGranted() {
    3 s/ z) O8 {6 d# J6 r2 R& q            }7 c  l! w! h, K6 d8 [
                @Override
    5 q/ l: |9 b- J* [' M: K0 h            public void onDenied(List deniedPermissions) {' |6 r6 V8 `% ?
                }" V& h% L' j' @' r
            });! _( o1 A7 P$ c( U
        }
    . q% p  I/ }! O. P# n  
    + U/ e& R# H. M9 c    //无人机首次注册! z# ]! a, V1 O2 N! O9 w& b
            private void startSDKRegistration() {
    5 D' J/ C4 K7 K' a% p            if (isRegistrationInProgress.compareAndSet(false, true)) {
    3 {0 ]4 X5 W( W- |' H2 A3 O                AsyncTask.execute(new Runnable() {
    % Q& \, T! Z$ X. N                    @Override
    ( L: b9 G' x7 {                    public void run() {
    6 A4 w5 X0 C7 J  F4 k//                      showToasts("注册中,请等待...");: V+ @) B( \& ]. ~* p+ [% D) L/ C
                            DJISDKManager.getInstance().registerApp(getApplicationContext(), new DJISDKManager.SDKManagerCallback() {  R& P% ^4 r6 I
                                @Override
    # a1 k; j( r( `                            public void onRegister(DJIError djiError) {
    : J6 h9 c/ a$ H% J8 T/ k; w                                if (djiError == DJISDKError.REGISTRATION_SUCCESS) {+ u0 r3 `1 X! R+ Y7 R! Q
                                        DJILog.e("App 注册", DJISDKError.REGISTRATION_SUCCESS.getDescription());
      e) d8 A# {! H8 m7 |4 O                                    DJISDKManager.getInstance().startConnectionToProduct();
    4 J/ V6 f6 ~* X& ^! y+ @" m    //                                showToasts("注册成功");
    2 R$ @) j& y" M0 T5 D                                    loginAccount();1 b# h/ q8 r0 f9 u" P
                                    } else {- ~4 ?2 _; s9 a' \- N: x
                                        showToasts("注册sdk失败,请检查网络是否可用");
    9 I! `  R" ~: z5 I  L- c0 Q" J                                }
    4 e0 c2 O/ A1 r0 @                                Log.v(TAG, djiError.getDescription());* [/ F) n! S; B1 C
                                }' N$ J: R. X& u: }- @% E) J0 o
                                @Override
    $ |  g- n5 L5 S0 {                            public void onProductDisconnect() {: D# `0 L1 v! [8 Y# `4 x
                                    Log.d(TAG, "产品断开连接");6 g* s5 w# m7 W- \2 t4 I- _4 W" }
        //                            showToasts("产品断开连接");  s2 P' P( g. z
                                }1 {! b8 }, o, f$ \" P
                                @Override
    9 H: g8 W5 o2 ~: F0 i: Q$ b                            public void onProductConnect(BaseProduct baseProduct) {* F9 E( E8 y, J
                                    Log.d(TAG, String.format("新产品连接:%s", baseProduct));& O2 f$ A0 W5 {' W
        //                            showToasts("产品连接");6 x( \; n: I# q5 `+ C
                                }6 }! W5 q# j$ w1 T/ D0 J" N
                                @Override
    . M& l7 }8 |2 r                            public void onProductChanged(BaseProduct baseProduct) {7 G1 j# w/ V- }
                                }
    4 {6 j% f* f5 z1 K1 f3 I                            @Override0 x1 o$ n" Z5 s- D
                                public void onComponentChange(BaseProduct.ComponentKey componentKey, BaseComponent oldComponent,
    9 p, {9 |" `+ x- U# X                                                          BaseComponent newComponent) {
    & t( R* @$ t  f7 o                                if (newComponent != null) {3 _8 O9 V) v/ b1 e$ Y9 w
                                        newComponent.setComponentListener(new BaseComponent.ComponentListener() {/ ?  v  T5 e; S$ Y, H8 ~9 Y2 o
                                            @Override9 `5 ^& s/ T7 R. j
                                            public void onConnectivityChange(boolean isConnected) {
    ' E! q" Q4 p: B+ r                                            Log.d(TAG, "组件连接已更改: " + isConnected);
    ) W& N: W3 y' U3 Q* t, v' F0 e                                        }! ]2 s& f) i2 d+ b0 c7 m1 r& }
                                        });
      I! J9 p% z0 v& G                                }
    ( s7 I+ J1 B# B0 ]# Q                                Log.d(TAG, String.format("改变设备Key:%s, " + "旧设备:%s, " + "新设备:%s",% _. I$ j' J" z' H; p, W- h
                                            componentKey, oldComponent, newComponent));
    0 N( t  C. p, B                            }
    ) ^( ?4 x% A, L                            @Override4 ?$ @- Z3 s% n" ~* X, z" i& K
                                public void onInitProcess(DJISDKInitEvent djisdkInitEvent, int i) {$ A! o( V/ I* w. h# _& [& i+ ~4 H
                                }
    ' ?( m. i( c3 d: U( `                            @Override. b! u1 c2 @3 Z/ w$ s4 `& t1 o
                                public void onDatabaseDownloadProgress(long l, long l1) {1 X* Y3 S9 v4 f% W& ^% Y; A$ e5 r
                                }( x. L6 X; c4 f+ L1 |2 `% L
                            });
    : {( b% n+ y6 ?* G7 V                    }. V; _, Z9 w+ f2 D' l7 }5 {
                    });+ v& Z% u. t, @; u: u0 _4 s
                }# z, x& Z! u! m. |$ M7 u6 I7 X# B
            }
    & e5 X: j1 x' B$ G: }    protected BroadcastReceiver mReceiver = new BroadcastReceiver() {9 O0 N1 K% V  {8 q( ?/ }1 f* l1 w
            @Override- i( J& ?; j3 O, a) r
            public void onReceive(Context context, Intent intent) {
    3 O! e/ F$ c* m/ M5 ^7 L            refreshSDKRelativeUI();# K$ ?, t8 e+ c( w2 `7 ]: \4 c
            }
    0 D. }2 k8 Q$ y* s9 l6 ]  g; j    };) ~% J! m5 J# R. d
        private void refreshSDKRelativeUI() {
    * w  ?* }- ?" K/ `  T        BaseProduct mProduct = ReceiverApplication.getProductInstance();
    " I# s0 Q3 v8 Z0 O- W2 {        if (null != mProduct && mProduct.isConnected()) {$ h3 C) j7 a, A3 }
                Log.v(TAG, "刷新SDK: True");. ~. X. T5 _: L2 M6 s5 l
                mButtonFlightTask.setEnabled(true);
    & t) u) i8 V  N* R7 [            mButtonSettingRoute.setEnabled(true);
    7 ^3 K! M+ z/ v1 Z% L            mButtonFileManagement.setEnabled(true);& N3 k, W/ E' K
            } else {
    6 t& W. I6 I4 f5 t$ Z            Log.v(TAG, "刷新SDK: False");5 @( K& Q$ B5 k# R! q$ q  j
    //            mButtonOpen.setEnabled(false);
    7 C! a2 n* s% x5 O3 M//            mButtonSettingRoute.setEnabled(false);' T/ l4 L! ~3 m; I: N
    //            mButtonFileManagement.setEnabled(false);: x" R5 Z$ u# O, d) l& p2 M
    //            startSDKRegistration();
    * r0 L) E+ ]; G: F+ V- o        }- P/ S( u/ Y; ?! }
        }
    4 o0 ?/ f: E2 h$ R* Y- C3 l    protected long exitTime;   //记录第一次点击时的时间
    & h" b9 B5 Y, i& M  v" O    @Override0 D9 N- k0 T, Z: ?/ u; m
        public boolean onKeyDown(int keyCode, KeyEvent event) {3 A# C! i3 t2 K
            if (keyCode == KeyEvent.KEYCODE_BACK4 O- u. H" ]8 e7 B( \0 {9 I: m& G
                    && event.getAction() == KeyEvent.ACTION_DOWN) {$ d* n2 ^. {& d. L
                if ((System.currentTimeMillis() - exitTime) > 2000) {; O* _% V# M; c' X9 X. Q' t/ b
                    showToast("再按一次退出程序");2 c" n1 m- P8 d. t; h/ F
                    exitTime = System.currentTimeMillis();; n5 Z! }& T/ C
                } else {( e; r% X8 d3 ~1 ]1 I9 B3 u  k
                    RegistrationActivity.this.finish();
    % q. f0 m/ X3 b) j% {                System.exit(0);7 V2 D! T/ h. @  i% _, X$ E/ |
                }
    - t# w8 I" v3 E  R            return true;
    + j& Z9 U9 h& \. G8 y        }$ h) [, F. P8 x! {" Y
            return super.onKeyDown(keyCode, event);
    & r- C" V( J  W# {6 w0 j9 R$ O' b    }
    $ ]( Y3 z3 [5 n3 W- e9 q/ @' o; [9 k9 M
            private void loginAccount() {3 `2 G% V+ |/ o1 P% {9 _7 @/ w0 j" A
                UserAccountManager.getInstance().logIntoDJIUserAccount(this, new CommonCallbacks.CompletionCallbackWith[U]() {( B" [; t$ g2 l. ?
                    @Override
    5 u6 Q1 H/ u" }2 `# |+ ?( _1 c                public void onSuccess(UserAccountState userAccountState) {0 H9 x" b2 L" `1 c7 G, f+ O# R' r
                        runOnUiThread(new Runnable() {
    - @$ `; E" D. `# j2 X2 X: S                        @Override
    ) h  R: r' b" G/ m* K                        public void run() {$ a- _* t- V  _7 i
                                mButtonFlightTask.setEnabled(true);- f. F, l' p, Y( i: p- \$ b
                                mButtonSettingRoute.setEnabled(true);/ C: f$ G2 l$ `. h
                                mButtonFileManagement.setEnabled(true);
    " P% m# T( b9 J9 c                        }
    3 f0 a$ W# y' E" K9 \3 k                    });2 p* ~6 |0 X  Q% E
                    }% y8 p! C% H" Q% H7 Y1 }; B) J
                    @Override( i: ~* `2 X" G0 U7 t
                    public void onFailure(DJIError djiError) {
    6 ?! _7 }+ b& k7 B; K9 {7 }2 q                }
    / q' E" T  N' i# C            });' y, I! D) N7 [0 n
            }$ X6 A2 }7 R, @8 V( ?4 A6 O. m
    }
    & L2 q" D* c4 _8 e. m上面的代码就要进行第一次注册登录了,当然你不需要自己去设计登录注册页面,大疆会调取自己的登录注册页面供你使用。
    ( ]" t" G$ J$ h6 j5 H" p

    pfqmgqdfgzx64011358750.png

    pfqmgqdfgzx64011358750.png

    ' l" R# S" `( h( K安装提示注册登录即可。
    , h- {4 V# q1 Q  s9 l上面的这些做完后,恭喜你!现在,您的移动应用程序和飞机可以在中国使用而没有任何问题。换句话说,您的应用程序现在可以看到飞机的视频流,并且飞行将不仅限于直径为100m和高度为30m的圆柱体区域。8 H, k8 x* \( K7 F! m- C$ w8 j
    3
    ) g& Z" ~: J9 f$ X9 P2 J( @- @5 x飞行界面使用
    7 u3 n/ e; b. g# w: j9 _虽然说可以正常飞行了,但是飞行需要设计飞行界面。那么创建一下飞行界面的UI及逻辑处理文件。逻辑处理文件中包含了获取飞机的实时姿态信息,代码中有注释内容,描述的内容就不多说了。
    ) b3 q- n/ R  Y1 C
    0 `8 T3 v- L/ x导入UX SDK依赖, y5 h4 j# y. Y  `% p2 p3 {! ?7 w
    上一节有说过集成部分,其中内容有导入UxSDk 的操作,这里再顺便提一下。再build.gradle文件中加入implementation "com.dji:dji-uxsdk:4.16"依赖,等待安装即可。5 m3 C5 X% e! K* L3 U6 e5 ^& F

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

    utpqdgqpfom64011358850.jpg

    utpqdgqpfom64011358850.jpg

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

    jbk4phmi3so64011358950.jpg

    jbk4phmi3so64011358950.jpg

    ' R9 Q% H$ a$ {* b% \
      p7 `, i0 }# i$ b+ J8 x7 n4 {

    v5wq2lnnpdq64011359050.png

    v5wq2lnnpdq64011359050.png
    5 D- k% K. ^0 x. o3 t3 k& [. L
    往期推荐LabVIEW OCR 实现车牌识别% j7 _' V  h$ e) c8 F
    和12岁小同志搞创客开发:有意思的激光切割技术
    6 R7 H0 s, Y, HJavaScript+TensorFlow.js让你在视频中瞬间消失
      J) z* e4 a4 E2 ^5 N使用OpenCV测量图像中物体之间的距离- Y# p7 U# i+ v+ C% e9 M
    全网仅此一篇:工业级压力传感器设计及实现" t; C( T; U! G5 S7 u

    & P* ~1 j) F) i5 X

    jvdg1ytc4o564011359150.jpg

    jvdg1ytc4o564011359150.jpg
    " Q; E9 G$ g% S% b. m

    mw3bqzgjnuv64011359250.gif

    mw3bqzgjnuv64011359250.gif
    6 K# F- d* t* ~9 U$ }2 y- O( ]
    点击阅读原文,更精彩~
  • 回复

    使用道具 举报

    发表回复

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

    本版积分规则


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