电子产业一站式赋能平台

PCB联盟网

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

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

[复制链接]

840

主题

840

帖子

6491

积分

高级会员

Rank: 5Rank: 5

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

tuvqh5dfafc6406117254.gif

tuvqh5dfafc6406117254.gif

0 j6 M3 y4 l' c0 e点击上方蓝色字体,关注我们- Z; }7 D7 t6 }0 W

( f; U1 j. D- x: H5 e+ B上一篇文章(基于Mobile SDK V4版固件开发大疆无人机手机端遥控器(1))因为时间原因介绍了一部分内容,如果已经完成上一篇内容的操作就可以进行下面功能方面的制作了。自己开发的APP功能不是很多,但是已经将大疆无人机的常用功能进行了结合,同大家一起进行学习~
1 Z% Z/ ]9 b' E12 t9 v: D( d- T! T1 y. F* L
应用程序激活与绑定
" K# r7 l6 ^- c9 m如果在中国使用DJI飞行器固件,则需要使用该用户的DJI帐户激活控制DJI飞行器的移动应用程序。这将确保大疆能根据飞行器的地理位置和用户个人资料,为飞行器配置正确的地理空间信息和飞行功能集。激活系统的主要是:
* p8 X( }) g/ s; Y
  • 中国用户必须在每三个月至少登录一次DJI帐户以遍激活应用程序。
  • 激活信息将存储在应用程序中,直到用户注销为止。
  • 登录DJI帐号需要连接互联网。
  • 在中国境外,SDK会自动激活应用程序,无需用户登录。
  • 另外,中国用户必须将飞机绑定到DJI官方app中的用户帐户。这仅需要一次。如果未激活应用程序,未绑定飞机(如果需要)或使用旧版SDK(6 R8 \" c) M0 S! O+ s; m) T

    * a7 U; h! @% q* k8 W2
    , H2 B) E$ l. j, a为应用程序创建UI编写MApplication、ReceiverApplication和RegistrationActivity文件(此处粘贴部分代码)。# }. \9 V9 L$ U5 a% A3 D7 t' D
    public class MApplication extends MultiDexApplication {  P* \: H" {& l- J3 x" S) M
        private ReceiverApplication receiverApplication;' ^; p- X/ s% C7 k
        @Override
    9 a3 g2 Z' u9 P6 v    protected void attachBaseContext(Context paramContext) {
    8 z; w) a6 f# i& ?) K  b$ q        super.attachBaseContext(paramContext);
    3 m6 }9 |0 E  Y; I& x. f" j' q3 R        CrashHandler.getInstance().init(this);
    " o% D% p6 c2 l8 W1 M. a2 G        Helper.install(MApplication.this);
    9 i+ `3 X- W9 Y& \$ B5 i+ g        if (receiverApplication == null) {+ E1 |; y1 u# q' F$ {
                receiverApplication = new ReceiverApplication();8 q" J1 ?6 ~. E0 h
                receiverApplication.setContext(this);5 n! l( y/ p( C- m  B
            }! d$ q. @# h0 z; \
        }: S/ [6 ~0 z% L, z. }* w
        @Override) ~3 L1 e1 S8 j# }% p
        public void onCreate() {
    ! n5 Y+ j: i: v$ w" T. y$ Q& T        super.onCreate();, {/ O- z8 m. Z$ W  }5 k# P
            receiverApplication.onCreate();
    $ n# O) x" m5 ~" z+ }* }    }4 v$ R% F  n. s2 K
    }) [4 m6 f7 d$ ^! H
    上面的代码实现了绑定当前APP,将后续需要用到的类函数封装到ReceiverApplication 中,在ReceiverApplication 中也能够进行账户登录的操作。
    ) d6 s- t! J5 I4 ~public class ReceiverApplication extends MultiDexApplication {1 c' V8 w8 L" S9 C( [2 c
        public static final String FLAG_CONNECTION_CHANGE = "activation_connection_change";
    : v" a) K' b8 }% C    private static BaseProduct mProduct;* M1 T; `5 Z# a5 W, F4 b
        public Handler mHandler;1 `- {' T9 f) [
        private Application instance;# R4 f( M! F4 x% G* q/ `7 L% w
        public void setContext(Application application) {
    1 Z9 u7 @6 ^3 A  Y9 n5 a        instance = application;
    " b4 w1 E4 h3 O    }
    , _# r" u/ W# F5 H! C' D3 e; @8 D    @Override5 F* J) T2 s7 U2 c* K2 w6 ]
        protected void attachBaseContext(Context base) {  ~' S9 }* M  H8 }. f' b5 R: A
            super.attachBaseContext(base);
    9 f; p- A5 `+ M2 C8 k1 @        Helper.install(this);, [" Z) J- G" M3 S& G
        }
    4 t& v% Z( l6 \" R    @Override
    ; L6 T8 z6 O# B    public Context getApplicationContext() {4 i0 q/ n: n/ H! }) R( ^
            return instance;
      O2 _; p; e  O- Z$ _$ R; n    }2 z; E" r) W0 P2 F. \) h' A
        public ReceiverApplication() {
    9 @+ V% w  u- w' `    }
    % g5 R" r* q% d% d& ]. G" u$ R% b    /**
    / {! E* W2 Y" t3 K" _1 V     * This function is used to get the instance of DJIBaseProduct." K/ s& o1 I& i2 H
         * If no product is connected, it returns null.
    + D$ m" O) w" ]8 ~     */
    # u1 _' P- Q' x! i    public static synchronized BaseProduct getProductInstance() {
    4 r2 L  ]" t6 u4 w% ]- ]- L! J        if (null == mProduct) {- e. y7 D6 U# ^! N
                mProduct = DJISDKManager.getInstance().getProduct();
    $ Y: E0 M: v" @4 D  s5 d        }
    / J" }2 L$ n2 X4 S& ], U7 n        return mProduct;
    ) G9 }/ ]6 m8 s5 {6 p- \  q9 _2 x    }
    % z9 |9 j! n7 m& I0 ]    public static synchronized Aircraft getAircraftInstance() {6 k, y6 X, S& B7 F2 x0 P- Q- N
            if (!isAircraftConnected()) return null;
    3 i0 ?7 o* E, H% _7 l& N8 s        return (Aircraft) getProductInstance();0 S5 B4 E6 r' g; P! }+ s
        }: J( w. C. d1 V% n* o2 v) B: w
        public static synchronized Camera getCameraInstance() {
    1 k2 h0 r: Y: l0 L        if (getProductInstance() == null) return null;% [+ P8 W  N( h
            Camera camera = null;
    & ^8 Z( ?6 z2 v3 ~        if (getProductInstance() instanceof Aircraft){( b5 N- ]9 K+ r; J  H! W
                camera = ((Aircraft) getProductInstance()).getCamera();# V9 K# g, {4 e, I  h
            } else if (getProductInstance() instanceof HandHeld) {2 q5 r* S. H3 W2 q" d3 K% w
                camera = ((HandHeld) getProductInstance()).getCamera();0 {1 D- U' q2 r: T/ |: \: t
            }, J# J( @7 K7 }0 Q
            return camera;1 y1 |$ O" `$ X3 x4 h
        }+ b( a( N% o* g, G
        public static boolean isAircraftConnected() {/ k, F( t; M+ @
            return getProductInstance() != null && getProductInstance() instanceof Aircraft;
    : D" A% f, Q5 w. u! c    }1 c1 J; M: H0 i
        public static boolean isHandHeldConnected() {
    6 R2 Y) d; h! Z, N- v; L1 i        return getProductInstance() != null && getProductInstance() instanceof HandHeld;0 i+ I$ T" t  z" b  g( Y; h3 N- U
        }) r5 ~9 U9 n2 H/ r$ G
        public static boolean isProductModuleAvailable() {  R; D/ K: r, V- P" L0 V
            return (null != ReceiverApplication.getProductInstance());$ H9 g" q) L2 {4 m
        }
    5 |" ^5 q8 W, T* f$ I& ?' y0 }+ ^! X    public static boolean isCameraModuleAvailable() {
    " T1 ?  P$ r& [$ k( m        return isProductModuleAvailable() &&8 _" Z; q& V2 @( p9 u
                    (null != ReceiverApplication.getProductInstance().getCamera());
    0 F) q( a5 @5 K  ~8 `    }
    * e8 f& H5 Q( r, {, a  b7 e1 I0 w4 L    public static boolean isPlaybackAvailable() {
    8 Y0 r) Q( f' S. U. o        return isCameraModuleAvailable() &&1 j3 D# m! y1 r2 R6 m- c4 k+ \
                    (null != ReceiverApplication.getProductInstance().getCamera().getPlaybackManager());
    * R+ ?- P4 u) K+ u: [7 e3 y    }
    , V; [, z4 p/ L0 r( E8 T2 W    @Override/ y: J- H6 n  H2 ~% O+ V" }
        public void onCreate() {
    / s1 Y; O5 Y1 Z. P        super.onCreate();8 f, d+ l' v! s
            mHandler = new Handler(Looper.getMainLooper());8 `- G- [& _* x! F" H
            /**
    $ [- {2 N  u9 \         * When starting SDK services, an instance of interface DJISDKManager.DJISDKManagerCallback will be used to listen to
    / h: A) e. [6 M! n2 Y         * the SDK Registration result and the product changing.
    0 h% S" v7 o, D/ k$ }! S         */6 U: k+ R0 Q, q5 p* Y5 U( C
            //Listens to the SDK registration result
    ! q' V, m; |0 }5 c0 ?# O% r7 x        DJISDKManager.SDKManagerCallback mDJISDKManagerCallback = new DJISDKManager.SDKManagerCallback() {
    9 a* z0 `( v( T  V/ x            //Listens to the SDK registration result4 V  b; ^: N4 F/ q* \! e
                @Override) u; k, W8 O5 m
                public void onRegister(DJIError error) {! ~; O/ `! Z6 F  D
                    if (error == DJISDKError.REGISTRATION_SUCCESS) {" o2 x& B( u' s/ E
                        Handler handler = new Handler(Looper.getMainLooper());. x* P0 {/ t7 G: J5 r* S* C
                        handler.post(new Runnable() {+ @; d) ~# p) @# m
                            @Override) ]: Z7 O' c7 d- @  M
                            public void run() {
    ! p: Z8 [- F$ r8 ?  c* {//                            ToastUtils.showToast(getApplicationContext(), "注册成功");; n) W7 _4 F" z  D! i: K/ M) t$ f+ R
    //                            Toast.makeText(getApplicationContext(), "注册成功", Toast.LENGTH_LONG).show();- B# I7 N: o. r$ M0 T# ^7 J
    //                            loginAccount();
    % h  W3 n& ?2 ]$ W2 O3 l* X, B) D                        }/ G2 V9 r. m% K
                        });7 S3 l5 E# K4 h9 @
                        DJISDKManager.getInstance().startConnectionToProduct();; i9 ~4 C) B7 h  D
                    } else {, [: }) W, D* [1 ~$ n( `
                        Handler handler = new Handler(Looper.getMainLooper());& o& B* a' n5 `' Y0 c$ X" R* S
                        handler.post(new Runnable() {! D+ @4 e2 M8 H3 i7 Z1 W& g( H. w) {
                            @Override/ [6 [  l- |+ E$ ]- [3 c
                            public void run() {. z) m# j% o; y
    //                            ToastUtils.showToast(getApplicationContext(), "注册sdk失败,请检查网络是否可用");
    $ H1 O' W' F2 Q//                            Toast.makeText(getApplicationContext(), "注册sdk失败,请检查网络是否可用", Toast.LENGTH_LONG).show();6 ~: ]4 b( X+ F" ^: H, j3 ]
                            }
    & `" L" i( E% t/ k                    });
    4 a- b+ h* U1 C' f8 B( y                }3 z+ X6 d8 b" v* u) h% A) O
                    Log.e("TAG", error.toString());
    ; m" t+ T1 u+ [/ f0 ?" }2 V            }
      E0 b; F# R, o/ I# U2 H3 N            @Override
    , S  h7 E$ T$ E: b' [; ?            public void onProductDisconnect() {
    0 D$ Z8 W) D. p+ g+ q                Log.d("TAG", "设备连接");0 j2 Y6 N1 \1 ~$ z) n7 i' x, B8 ~! J9 v
                    notifyStatusChange();
    : Q: d; \4 T7 F3 g0 U            }
    ! z1 s/ u& j+ z- ]3 j. M            @Override
    " q  c, V6 `1 @% a2 U  k8 L            public void onProductConnect(BaseProduct baseProduct) {
    * Z* E* ~' h- T                Log.d("TAG", String.format("新设备连接:%s", baseProduct));, w, c7 l" A; s/ E
                    notifyStatusChange();
    7 {, Z/ H! L3 l# f* z* }0 Q- T            }
    3 G6 T5 _6 |- @, U7 ]! M, V, a            @Override3 O; `0 m, f5 ]. y
                public void onProductChanged(BaseProduct baseProduct) {
    6 H0 k5 n2 [0 @% g! Q            }4 x% v! z& ?5 g3 x# O7 j
                @Override
    7 S* Q! g7 _$ T" p. H/ Q2 s            public void onComponentChange(BaseProduct.ComponentKey componentKey, BaseComponent oldComponent,. M5 ^# U' L: w# X8 G( ^
                                              BaseComponent newComponent) {
    8 j) T' O4 C+ X0 H6 b2 P                if (newComponent != null) {
    1 Q  x. K: m' `1 j  }                    newComponent.setComponentListener(new BaseComponent.ComponentListener() {
    9 R0 G6 B( C- ?  \) ~3 f                        @Override
    ' g3 n- L6 S0 n! c- a4 v5 z                        public void onConnectivityChange(boolean isConnected) {
    - ?7 X+ u+ x, _+ {7 ~                            Log.d("TAG", "设备连接已更改: " + isConnected);
    8 F+ [) I1 x7 S0 h) G1 s                            notifyStatusChange();
    ) c7 E* h# \9 L6 n9 j                        }" t+ @& L8 v1 r! t+ Y- b
                        });4 f/ L7 F% L: p  {! Q, a
                    }
    ! U8 V% A9 E, s5 _+ \                Log.d("TAG",
    0 j! e  K9 z. y- G. A                        String.format("设备改变 key:%s, 旧设备:%s, 新设备:%s",) R) m; T; }7 A; t# [, a9 t
                                    componentKey,) q. p" u3 C( c
                                    oldComponent,
      P/ X) W) @4 C' @! L# H' T# Z# z                                newComponent));
    ' u- n  N1 \- ^) k            }1 U5 P. V5 f6 P' C3 [8 I  l4 E" u7 X
                @Override
      {4 @4 j& P+ j/ U. v) @+ V- ~1 d            public void onInitProcess(DJISDKInitEvent djisdkInitEvent, int i) {3 D( g/ D7 ^' d. \1 S3 l. W* R
                }1 n/ M; U+ A" i! l: k% ?  X, t8 t/ W
                @Override* B& j3 ^& T9 z6 m7 k5 C) w
                public void onDatabaseDownloadProgress(long l, long l1) {0 N8 u: s0 Y0 y* {5 i! z
                }# Y6 Q+ x4 D. S. ?
            };0 q- T4 q, y  E- g3 n1 A7 K& S  B
            //Check the permissions before registering the application for android system 6.0 above.
    ( M3 @& T: r, r9 G, }        int permissionCheck = ContextCompat.checkSelfPermission(getApplicationContext(), android.Manifest.permission.WRITE_EXTERNAL_STORAGE);
    0 q8 Y8 D; F# S4 ]; \        int permissionCheck2 = ContextCompat.checkSelfPermission(getApplicationContext(), android.Manifest.permission.READ_PHONE_STATE);; D# t. n( \$ H2 U; J6 {, S( V
            if (Build.VERSION.SDK_INT 0 && permissionCheck2 == 0)) {& e: {/ J8 g- a  {& P
                //This is used to start SDK services and initiate SDK./ o1 ?; z' w* ]9 G4 |( H; r
                DJISDKManager.getInstance().registerApp(getApplicationContext(), mDJISDKManagerCallback);; a( s  ~. H, M, Z5 j. }! W/ `
    //            ToastUtils.showToast(getApplicationContext(), "正在注册,请等待...");9 `; O* [. N- X" @/ w/ Z1 q1 j
    //            Toast.makeText(getApplicationContext(), "正在注册,请等待...", Toast.LENGTH_LONG).show();
    * R; Y3 N! ~* A        } else {
    - b( i5 {3 o9 u- m0 G//            ToastUtils.showToast(getApplicationContext(), "请检查是否授予了权限");: a0 F9 M9 ~7 T6 n
    //            Toast.makeText(getApplicationContext(), "请检查是否授予了权限。", Toast.LENGTH_LONG).show();
    ! V8 U" ?5 x4 [' E7 D        }
    % p* f: b* n3 L4 Y: b    }& W1 \6 s6 x% s1 J
        private void notifyStatusChange() {/ c4 \% t1 d& t9 E
            mHandler.removeCallbacks(updateRunnable);) U9 E+ z0 \) @: `" r
            mHandler.postDelayed(updateRunnable, 500);
      D6 Q! f2 Q! `! w5 R    }
    % d; }, S/ A- ]# h4 V, L  L+ K    private Runnable updateRunnable = new Runnable() {+ ]$ k  W+ L- `6 }
            @Override. X# k% s6 Y) J# k! Z/ L+ Q
            public void run() {
    3 G9 r- [1 o) Y( D            Intent intent = new Intent(FLAG_CONNECTION_CHANGE);
    7 J, ]% U7 p8 r- m1 h; F5 r            getApplicationContext().sendBroadcast(intent);
    ' d0 Z5 H$ T" R3 s" {        }
    * j/ @9 e6 W- O. O' g    };' S1 r& z) T6 Z1 C1 ^
    }
    # M  B0 f, ^6 Q上面的代码是对BaseProduct、Aircraft和Camera类进行实例化,在后续使用中不用再去进行重复的实例化工作,减少内存的消耗。8 o! o+ ?& Z! X) K$ o$ A- Z* x7 l
    @layout(R.layout.activity_registration)
    , _; k# _: G6 O, L4 ^5 Tpublic class RegistrationActivity extends BaseActivity implements View.OnClickListener{8 i  J/ ~" a) y( E6 r! e7 w! L
        private static final String TAG = RegistrationActivity.class.getName();
    ! g( G5 R9 j+ t4 Y4 B' _    private AtomicBoolean isRegistrationInProgress = new AtomicBoolean(false);
    $ |* ]) r2 [4 U# O    private static final String[] permissions = new String[]{
    ! V8 q( h' n8 M. b( p            Manifest.permission.BLUETOOTH,, Z2 K% G3 S* G( \8 [+ L
                Manifest.permission.BLUETOOTH_ADMIN,
    3 M5 o! B: D* W! _( j! T: c4 R            Manifest.permission.VIBRATE,
    ' C3 t7 t, \% h8 _            Manifest.permission.INTERNET,( J. _0 Q4 r) G1 B
                Manifest.permission.ACCESS_WIFI_STATE,& F8 w. I1 B5 V0 D
                Manifest.permission.ACCESS_COARSE_LOCATION,
    # j0 ]/ B- {. h; X& O* f            Manifest.permission.ACCESS_NETWORK_STATE,( I+ j& z% i  k6 N; f
                Manifest.permission.ACCESS_FINE_LOCATION,
    $ `1 S" b6 {0 i- i! C4 ?* K            Manifest.permission.CHANGE_WIFI_STATE,
    7 Y  B# j; |/ }            Manifest.permission.RECORD_AUDIO,
    6 i4 A7 i: c- d            Manifest.permission.WRITE_EXTERNAL_STORAGE,* X1 L+ c$ a% S1 G
                Manifest.permission.READ_EXTERNAL_STORAGE,
    ) @0 H& k& ^& |4 u% E9 u, ~  U            Manifest.permission.READ_PHONE_STATE,) |1 e& D3 c: c1 n; |' {
        };$ Y- `9 @4 Y! q- M' }
    , a* x% u( S! J
        @Override" A) i6 H1 K- B- W. p0 N7 A9 r& A
        public void initViews() {4 r& U# S4 u4 D& ^% H. U# M
            isPermission();' u3 S* x& `8 x  x, k& x; [
            IntentFilter filter = new IntentFilter();
    % ^) v! z  |$ M& N- F3 K        filter.addAction(ReceiverApplication.FLAG_CONNECTION_CHANGE);
    * R. b- Y) k" w9 f* m& _        registerReceiver(mReceiver, filter);' h: X9 u5 ?  H, G% ]" \( l
        }
    5 C. M- d1 k- V. H) U. \/ p+ y    @Override$ H* ^3 h- R! a0 f( l" V) h4 A; c
        public void initDatas() {
    4 @( Z$ I& T+ ]+ r, m" P        startSDKRegistration();
    " M4 i- A/ @& m' u7 P& ^    }! _, g/ u' v6 K! @  i0 p( V! q+ c* N
        @Override
    % J* C( \, D6 N9 n% `    protected void requestData() {9 D5 r  n: H2 @8 y1 a/ d2 s
            
    . }9 }, m& h9 x7 z! ~    }
    2 B6 g; e3 M/ N$ e- \/ h( V' P2 A
    ; Y( [0 O  F8 A+ n  c( |& C, d+ g    @Override4 h( L6 L. K5 t+ |0 o: g& i
        protected void onResume() {
    . j( Q6 v* L7 Z. I: F        super.onResume();& m1 K: u. U( w+ R: @
        }
    ' C8 U- ?+ h) }1 K' D$ q/ ]7 r! c4 E; `
        private void isPermission() {3 ~( S/ S, B9 Z5 Q) R0 c  z( U  |; g
            requestRunTimePermission(permissions, new IPermission() {! N3 @' q! r* b' o( G0 }
                @Override5 h7 o- L  ^# |' M+ q
                public void onGranted() {8 x+ v$ d2 q& \# W. j+ Z! l
                }+ {& m3 z' V6 V3 S
                @Override3 q3 |* q6 F+ ~) E# }
                public void onDenied(List deniedPermissions) {0 x& m- ~* M7 Z, d
                }
    & n# m3 T( W$ J) i( l0 Q        });
    9 ?. i7 ~/ ^8 O6 w6 v    }
    " x6 r3 @* G9 ~+ G  
    # \5 D# r$ c& ^: ~* g% R5 T    //无人机首次注册9 q* Y# m3 G9 @! I0 G
            private void startSDKRegistration() {. n; x$ v) a7 k& N( i. t
                if (isRegistrationInProgress.compareAndSet(false, true)) {
    ; ^5 q" U8 O8 V                AsyncTask.execute(new Runnable() {
    3 ~' b6 \. o- E* t/ A                    @Override- }5 {2 s% M" `9 K: \  v8 K
                        public void run() {: K" K% \( P9 r8 t0 `% @
    //                      showToasts("注册中,请等待...");7 B/ {. Y; R) @
                            DJISDKManager.getInstance().registerApp(getApplicationContext(), new DJISDKManager.SDKManagerCallback() {  Q) ^5 @: E9 p  g
                                @Override
    ! \8 d% i' a6 p- y  s7 b' b  ?                            public void onRegister(DJIError djiError) {8 }/ A9 l# T% R  U0 `+ a
                                    if (djiError == DJISDKError.REGISTRATION_SUCCESS) {! C9 R, D: g1 \- D8 P, X' J
                                        DJILog.e("App 注册", DJISDKError.REGISTRATION_SUCCESS.getDescription());  W) C% u6 Q2 f6 O# Q! }, p# c
                                        DJISDKManager.getInstance().startConnectionToProduct();' V3 {  i1 y2 Y6 G5 k  B0 B' ~1 v
        //                                showToasts("注册成功");- _- t: @: i. g) a! ?% _) O$ e5 Y! y) `
                                        loginAccount();1 h  ^1 k7 Z+ H, L# S$ o* ^
                                    } else {, Q. S# O9 ~6 r. \
                                        showToasts("注册sdk失败,请检查网络是否可用");
    / u$ ?0 W( \' s) B% q/ \  h; F) y                                }9 F- @" d6 [. M
                                    Log.v(TAG, djiError.getDescription());
    # a6 ?  T% U' p' R3 A                            }. q) X8 m0 B; L7 a
                                @Override  _' ]4 B& B( y; [% l: o* b
                                public void onProductDisconnect() {
    9 d# R, F  s; x4 t% J' R0 T' O4 P                                Log.d(TAG, "产品断开连接");* S8 u% A; w: e" x3 e( q  O- M
        //                            showToasts("产品断开连接");
    . B$ }& m# t* |1 C1 C9 [% Q* P                            }) n& o- i& h' s; L
                                @Override
    " B3 _( _; r9 |, y$ n                            public void onProductConnect(BaseProduct baseProduct) {
    ! S6 Y8 q; N  D+ e9 I, l                                Log.d(TAG, String.format("新产品连接:%s", baseProduct));- m7 L3 o0 ]/ T! E! k+ S# A* k
        //                            showToasts("产品连接");* {4 _' [! [+ X  l* ^
                                }
    4 C' {( a. X3 S* F7 p                            @Override9 t+ v1 I6 O& k
                                public void onProductChanged(BaseProduct baseProduct) {
    - Q: i: j, O& t; R0 n2 h                            }
    " i% z5 d$ R1 v9 q6 s/ C                            @Override! o$ y$ w6 d1 W  P
                                public void onComponentChange(BaseProduct.ComponentKey componentKey, BaseComponent oldComponent,; C* {1 V6 [) \) g- H1 Z
                                                              BaseComponent newComponent) {1 n9 k: P8 C1 q/ ^) @4 N
                                    if (newComponent != null) {
    / y$ i- D+ j  X9 N) [                                    newComponent.setComponentListener(new BaseComponent.ComponentListener() {- S/ j- a- U0 C$ Z( \% V$ K
                                            @Override
    , |, i5 Y/ J* S                                        public void onConnectivityChange(boolean isConnected) {
    1 o$ L5 y4 H. Q7 l                                            Log.d(TAG, "组件连接已更改: " + isConnected);
    6 h" |8 @1 `( ?$ s* t                                        }
    ( v* @# r- s% l' Y                                    });
    $ e4 H* s( ]3 l4 f& d. Z& D4 o                                }* M7 h7 d4 d$ \; e2 I$ _% n
                                    Log.d(TAG, String.format("改变设备Key:%s, " + "旧设备:%s, " + "新设备:%s",9 d  N$ h9 R4 w" f( }
                                            componentKey, oldComponent, newComponent));1 j' q3 x* X5 ]# T. I4 k
                                }
    : R  M+ e, U+ e: r+ x2 B                            @Override$ A5 M) H6 w$ Z) k+ b/ M* ?3 e" y
                                public void onInitProcess(DJISDKInitEvent djisdkInitEvent, int i) {7 l8 b! G" l+ G( T4 H3 L+ \
                                }
    % l% G# W8 g4 D$ g' X: L                            @Override
    8 T0 n0 V' a+ z4 P3 F  D                            public void onDatabaseDownloadProgress(long l, long l1) {
    / T: ?6 g) h9 s7 n  ^/ C+ }: Z$ n                            }3 I& g0 x2 H4 n5 E+ w' p
                            });
    6 ~; g4 J5 A8 x2 v5 D: f7 _1 F                    }
    5 Y/ N2 U2 G, _4 D  Y/ m                });, y  P  j- W( a$ x
                }
    ' }4 D- B' V- e3 t        }) k. E* k1 X0 b" g
        protected BroadcastReceiver mReceiver = new BroadcastReceiver() {1 c/ {4 {7 w: A
            @Override
    # Z9 c7 c$ G' u# ]        public void onReceive(Context context, Intent intent) {; I2 o+ J2 b6 |5 J' \$ T
                refreshSDKRelativeUI();
    ; j' f9 s1 l: @$ g7 t6 U        }
    ; L) M4 u) d9 C8 n0 y( w    };
    / K( G7 t, i+ r# B' h    private void refreshSDKRelativeUI() {
    - t' |) [$ ~! S% J4 D        BaseProduct mProduct = ReceiverApplication.getProductInstance();
    ' W) i" D, a# c5 y/ _* c: r  {        if (null != mProduct && mProduct.isConnected()) {' Q8 I: P. R' p' d7 Z
                Log.v(TAG, "刷新SDK: True");- H6 R  I9 R# l2 Y' r9 }/ q
                mButtonFlightTask.setEnabled(true);
    , M" r! q; a, g6 U4 Q' `            mButtonSettingRoute.setEnabled(true);
    * w& z% w/ W9 F            mButtonFileManagement.setEnabled(true);
    % E1 Y' j( l! q7 q( K& s        } else {
    ! Y* r2 Q- _6 I; A" e4 W            Log.v(TAG, "刷新SDK: False");& c$ W* }, \% U9 F
    //            mButtonOpen.setEnabled(false);! f  s' X' S$ y- ?" ~1 |3 X% Z
    //            mButtonSettingRoute.setEnabled(false);
    ; ]+ L( P  K$ S//            mButtonFileManagement.setEnabled(false);7 Q3 A% u- M# X. F4 p7 i, w
    //            startSDKRegistration();
    # u2 ]  a9 I; S, G        }/ [  t% O! u9 g
        }4 B! e6 n  E: i, q
        protected long exitTime;   //记录第一次点击时的时间$ _: e4 x4 I+ o- J+ v# z: V9 b
        @Override
    7 Y' j9 r6 ~. }0 \, P8 E    public boolean onKeyDown(int keyCode, KeyEvent event) {
    $ Z8 }: W) x3 B        if (keyCode == KeyEvent.KEYCODE_BACK9 D. R: I8 {/ p: @
                    && event.getAction() == KeyEvent.ACTION_DOWN) {. V. ~$ C/ \1 ~. a/ k) q! D
                if ((System.currentTimeMillis() - exitTime) > 2000) {
    ( y5 M' R# I: S                showToast("再按一次退出程序");
    8 u8 ^* V/ ]8 {7 C                exitTime = System.currentTimeMillis();
    3 I9 G; z; y7 @7 B# h. [6 R4 w8 m            } else {  \( t' m& ^2 `; W# `! k
                    RegistrationActivity.this.finish();
    ! [+ p5 x$ \9 @                System.exit(0);
      ]% K. F7 Q: m            }' j/ p9 {" X: M7 ]1 H/ K: w
                return true;
    8 T% x! o2 _0 [/ O5 e" w+ p( j4 c        }8 t1 ^6 R9 G. r) g1 ~" ?
            return super.onKeyDown(keyCode, event);/ E3 t) e3 E) @% V
        }
    8 |5 A; X! g8 {$ y; `+ A% G
    , o, X. C- |: \2 R; W* `! F        private void loginAccount() {
    6 @; f5 H! k- g& H: o            UserAccountManager.getInstance().logIntoDJIUserAccount(this, new CommonCallbacks.CompletionCallbackWith[U]() {/ Y* J  f# a, X& a
                    @Override
    8 F1 x, a8 H9 X% o$ Y  ?9 d                public void onSuccess(UserAccountState userAccountState) {* e/ g9 Z4 Q% d; b  I
                        runOnUiThread(new Runnable() {
    : P9 d  x4 e8 c1 `# z& L                        @Override' O+ y4 j( I: x) m9 [# r6 m9 @
                            public void run() {
    - m1 X  B! d* Z! `0 z                            mButtonFlightTask.setEnabled(true);6 R% T4 ^& J8 P5 J. G
                                mButtonSettingRoute.setEnabled(true);! ]5 y* q+ [, I% ]/ ]4 t  C& C# J
                                mButtonFileManagement.setEnabled(true);
    ) }+ }; F- ^9 v( C& `                        }
    2 Y2 {: x+ r/ E3 b" j                    });: G$ w( l$ \0 E5 y% D7 c
                    }
    " Q2 W* l' Y- u0 r6 p* A1 I                @Override! P( ~* e- Y/ E$ Z& ^% p
                    public void onFailure(DJIError djiError) {
    8 t8 T) Z: F+ v( w9 q                }
    * l3 v/ y( }9 ]8 u5 j            });
    5 |1 P! l( U$ N" {+ b# d        }! ~/ f$ T* {2 N
    }3 D! l6 B8 |/ q6 W* D  S
    上面的代码就要进行第一次注册登录了,当然你不需要自己去设计登录注册页面,大疆会调取自己的登录注册页面供你使用。
    6 ]9 h: ~- L+ S( y% L( a, ~- i, Z

    b0cuun3oznz6406117354.png

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

    44z0q3cy2zr6406117454.jpg

    44z0q3cy2zr6406117454.jpg

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

    erlparwngkl6406117554.jpg

    erlparwngkl6406117554.jpg

    5 D7 y! H+ h' Q! r8 S- R$ f# q

    aamb1f3g2fw6406117654.png

    aamb1f3g2fw6406117654.png
    & q9 j$ Q# L2 n% P' q
    往期推荐LabVIEW OCR 实现车牌识别* h( j9 }. f: l- s
    和12岁小同志搞创客开发:有意思的激光切割技术, t2 b7 B- `  ?
    JavaScript+TensorFlow.js让你在视频中瞬间消失
    3 P  i( Z% V4 K7 I使用OpenCV测量图像中物体之间的距离
    7 a8 i) o4 O1 t. @8 X8 [  }全网仅此一篇:工业级压力传感器设计及实现0 D  Q# V$ S1 \  ~/ N

    1 ~9 y. _! K9 J' _. F

    2zmyv1n5at16406117754.jpg

    2zmyv1n5at16406117754.jpg
    1 b; A' z1 U  V* |0 j: Y" X) @( P

    hbeu2dpxc1x6406117854.gif

    hbeu2dpxc1x6406117854.gif

    + K9 \# X' t: f, T+ {- D) w点击阅读原文,更精彩~
  • 回复

    使用道具 举报

    发表回复

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

    本版积分规则


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