电子产业一站式赋能平台

PCB联盟网

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

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

[复制链接]

840

主题

840

帖子

6491

积分

高级会员

Rank: 5Rank: 5

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

omqaxwaojye64015955823.gif

omqaxwaojye64015955823.gif
5 C: C9 n  j3 K# z8 r
点击上方蓝色字体,关注我们& {) I- U, t: C& J
! K( R/ w2 G1 I% @7 ]9 n
上一篇文章(基于Mobile SDK V4版固件开发大疆无人机手机端遥控器(1))因为时间原因介绍了一部分内容,如果已经完成上一篇内容的操作就可以进行下面功能方面的制作了。自己开发的APP功能不是很多,但是已经将大疆无人机的常用功能进行了结合,同大家一起进行学习~+ U! h( D: v1 C/ g3 N4 |( ~
1
8 i6 C; x7 o8 A应用程序激活与绑定
/ U3 D) ~4 f2 ]9 ~  l9 H如果在中国使用DJI飞行器固件,则需要使用该用户的DJI帐户激活控制DJI飞行器的移动应用程序。这将确保大疆能根据飞行器的地理位置和用户个人资料,为飞行器配置正确的地理空间信息和飞行功能集。激活系统的主要是:
/ L* g! y( q: @9 [
  • 中国用户必须在每三个月至少登录一次DJI帐户以遍激活应用程序。
  • 激活信息将存储在应用程序中,直到用户注销为止。
  • 登录DJI帐号需要连接互联网。
  • 在中国境外,SDK会自动激活应用程序,无需用户登录。
  • 另外,中国用户必须将飞机绑定到DJI官方app中的用户帐户。这仅需要一次。如果未激活应用程序,未绑定飞机(如果需要)或使用旧版SDK(* [8 \* q- e" z8 N( [
    4 z% j6 [( _( H2 C1 q
    2! ^7 H- m- N$ E: g" L3 r" v
    为应用程序创建UI编写MApplication、ReceiverApplication和RegistrationActivity文件(此处粘贴部分代码)。
    + s% x' @/ \# U7 K) a: lpublic class MApplication extends MultiDexApplication {& u9 A7 S4 f8 L/ t3 Y
        private ReceiverApplication receiverApplication;1 r( J' S% Q" c+ M* B. H1 A
        @Override
    5 @' l3 m! p; a1 _( S' h8 z5 @( Z& n* p    protected void attachBaseContext(Context paramContext) {2 {' X' ]9 Q* \0 s! v! V. k7 k
            super.attachBaseContext(paramContext);3 Q0 Q0 q& c% g
            CrashHandler.getInstance().init(this);
    ( a* |! t  H- O% [7 J        Helper.install(MApplication.this);
    4 n! y2 @% `7 G, j        if (receiverApplication == null) {1 L  L  L1 L3 X$ ?5 t  ^6 F: H
                receiverApplication = new ReceiverApplication();* z8 [! R1 S0 ]; @8 {$ i6 M
                receiverApplication.setContext(this);3 z" {8 y* b( U% `) Z( D7 [% E
            }$ s3 B5 T1 F( `0 m+ y2 a' O
        }
    8 Z" S  d: Q) D/ q    @Override& z. R4 ?8 n# Q6 c; L4 k4 p
        public void onCreate() {9 p- F6 o6 h' P
            super.onCreate();
    # G- B  p2 E% A6 h2 m- y        receiverApplication.onCreate();
    $ Y8 ^' }( _7 C6 n& ?* B: t    }
    % P3 k3 B% F$ F1 ~2 q}
    " a9 s" @* j8 l/ }6 i7 g$ j  K上面的代码实现了绑定当前APP,将后续需要用到的类函数封装到ReceiverApplication 中,在ReceiverApplication 中也能够进行账户登录的操作。5 }! r1 h* g+ q* C! D8 }
    public class ReceiverApplication extends MultiDexApplication {* w# F2 W$ [9 @! t6 P: u' F
        public static final String FLAG_CONNECTION_CHANGE = "activation_connection_change";; K6 k1 g4 R0 K9 a- M
        private static BaseProduct mProduct;
    ( ?- W( S& L) ^8 j, l1 J    public Handler mHandler;4 D& D/ T- q& i
        private Application instance;/ H4 g7 o" v& L- f+ T2 X, G  R* C. K
        public void setContext(Application application) {
    ; K) O0 |( E7 x/ {/ ?' M        instance = application;( h( {. \: {6 d! p6 T
        }
    3 j8 }/ l' `) S" e9 R! g    @Override, i, n; `- t  h* T# E- x
        protected void attachBaseContext(Context base) {. S$ T/ _8 y1 _5 n3 m/ i
            super.attachBaseContext(base);
    : z& W. D" W0 i- S% d+ d9 X; [' S        Helper.install(this);) t' J' `, C) W
        }
    $ `2 o/ d$ C" m4 Z2 ]  y9 f    @Override
    " q4 h% B; A; H& T4 }    public Context getApplicationContext() {
    , e+ V: _4 O% }) Z! T1 X        return instance;7 u( Q( P9 W1 `( \4 Y
        }
    * @6 z5 K% b% Z9 c    public ReceiverApplication() {
    & N6 D- t9 g3 Z7 x: g    }
    : G( V6 L3 G) b    /**
    0 E5 b4 L4 l) V* X" G8 X% e3 j     * This function is used to get the instance of DJIBaseProduct.* O& s/ U' Y: ^% e6 \0 w6 l
         * If no product is connected, it returns null.1 p7 ]; o# |& {% z6 Y! u/ D
         */
    $ t, L7 D% r$ B6 |    public static synchronized BaseProduct getProductInstance() {1 n% _7 f, p1 g* S; r( F" q
            if (null == mProduct) {9 ^# w, T- e# h
                mProduct = DJISDKManager.getInstance().getProduct();
    9 X4 X4 D- ~" y" s! O# o        }
    8 @1 a5 |* _/ D        return mProduct;
    5 v8 j5 P; G6 Z# v    }
    2 T$ t1 A6 X8 V7 m! M5 }    public static synchronized Aircraft getAircraftInstance() {  X$ O+ j# g! u
            if (!isAircraftConnected()) return null;' t4 ?2 R( ?3 X/ }/ e# n
            return (Aircraft) getProductInstance();
    & G  l7 c5 ^) H- f6 p  s    }& x7 O* f: z" V
        public static synchronized Camera getCameraInstance() {! ]% B7 J  c( B* q$ Q
            if (getProductInstance() == null) return null;/ i5 F5 b* w& H
            Camera camera = null;: \# M4 q$ l  G) `6 C+ |* M% f# c
            if (getProductInstance() instanceof Aircraft){) Y) q9 Z/ K. p  {% t
                camera = ((Aircraft) getProductInstance()).getCamera();/ Q" H) [5 @- t& Y7 B& e6 w
            } else if (getProductInstance() instanceof HandHeld) {, E" K* c9 F5 t& d3 e- d
                camera = ((HandHeld) getProductInstance()).getCamera();8 R& Z6 ], ~0 c3 ?: i* A7 q
            }) N+ B. q/ C! J
            return camera;7 D6 R% Z1 ]) W/ o2 G
        }
    7 u: H" `9 m7 v( Z    public static boolean isAircraftConnected() {
    8 R' T" P% \: j4 `# s        return getProductInstance() != null && getProductInstance() instanceof Aircraft;- t. k( z& Y9 c7 K8 c5 T. }( l  S
        }3 s3 \5 b- b' g( O
        public static boolean isHandHeldConnected() {, Y3 c; {! ?+ ]) q1 a$ e' r
            return getProductInstance() != null && getProductInstance() instanceof HandHeld;% d' u$ u3 j2 _* ]/ D6 h
        }
    % p* j5 n0 L7 _7 e1 G# @- }$ A; o2 S! L* K" S    public static boolean isProductModuleAvailable() {
    $ K3 e$ w) z8 F7 T$ j, B1 e        return (null != ReceiverApplication.getProductInstance());
    . U& K+ Z4 ^) c    }
    ( M0 ~6 F9 N$ y! E. d; t    public static boolean isCameraModuleAvailable() {
    4 V- c6 ~2 ^9 M* Y. s/ B( B: E        return isProductModuleAvailable() &&  A0 j9 g8 I/ [) A& \9 W
                    (null != ReceiverApplication.getProductInstance().getCamera());
    + E/ _4 r; _# D& V& }# A5 s, P/ Z    }
    4 H, Q1 l1 y  f    public static boolean isPlaybackAvailable() {
    ) `: Z' O- N: O5 n3 P) g: e. h        return isCameraModuleAvailable() &&
    ' V9 I4 r7 f3 f. z2 ~9 v( F                (null != ReceiverApplication.getProductInstance().getCamera().getPlaybackManager());  X: S) s# p# `; `2 z  f
        }
    4 {: [: w& r7 X# y% N' s    @Override4 x' `2 N7 V; g% e- @
        public void onCreate() {6 n" q4 p2 }6 x9 ^/ o. o
            super.onCreate();
    ; Q9 p: C' A% D        mHandler = new Handler(Looper.getMainLooper());3 R4 I% w  P$ {" B  i: B: W  b: m
            /**
    . o0 g. e' o5 K, k! D         * When starting SDK services, an instance of interface DJISDKManager.DJISDKManagerCallback will be used to listen to: y7 G3 W# X, s' D' p4 w
             * the SDK Registration result and the product changing.0 W, @* l- Z+ K) E; t% X
             */
    - `" z* P, U* C3 I/ ]* G9 {" j        //Listens to the SDK registration result
    + X- s0 Z5 N9 J$ Q( J8 N0 k! p        DJISDKManager.SDKManagerCallback mDJISDKManagerCallback = new DJISDKManager.SDKManagerCallback() {
    + g5 P% N% m: n0 m# w8 ]2 Y            //Listens to the SDK registration result
      ^2 `' _: b- T# J            @Override
    2 M3 w8 A  F9 I" A' I            public void onRegister(DJIError error) {! v) H. Q- |- n5 I9 H
                    if (error == DJISDKError.REGISTRATION_SUCCESS) {9 C. J. J. g$ ]( P
                        Handler handler = new Handler(Looper.getMainLooper());! D# I. J4 ?4 B( K/ h
                        handler.post(new Runnable() {$ M) h! O/ O/ y3 f( l0 X
                            @Override# F* X( l1 J- A& Z& T1 h. @2 H2 w5 S
                            public void run() {, s( s- F% w& ?0 q$ V1 q; F# C- r
    //                            ToastUtils.showToast(getApplicationContext(), "注册成功");3 U" A: h' [8 E" e" c$ Z# @
    //                            Toast.makeText(getApplicationContext(), "注册成功", Toast.LENGTH_LONG).show();: E) g) `* s* a" K! e
    //                            loginAccount();
    + W) m5 Q) q- y. M' m                        }
    0 C" \' O8 |, {# {                    });3 F7 ]+ I5 k8 j% M. |' M: R% @/ L
                        DJISDKManager.getInstance().startConnectionToProduct();# m$ O0 a3 F3 w3 ?1 i
                    } else {7 T- a' r5 S- g3 M
                        Handler handler = new Handler(Looper.getMainLooper());/ o: R3 f' A  \4 P
                        handler.post(new Runnable() {
    9 n8 f2 y9 @+ S                        @Override' e+ ?; i& D/ m2 T! {
                            public void run() {
    * G' ~  t6 ]  C3 ]2 ~) I; D//                            ToastUtils.showToast(getApplicationContext(), "注册sdk失败,请检查网络是否可用");, D3 `/ ~' y$ Q7 V; Z- H& C5 G
    //                            Toast.makeText(getApplicationContext(), "注册sdk失败,请检查网络是否可用", Toast.LENGTH_LONG).show();
    + I" ~5 h, q: n+ i; V$ H: q                        }$ k) ^& b- L3 A5 Y, G- R: h
                        });- b" k/ [- l# B0 X* j
                    }
    0 R+ _# w' i7 T0 W4 j                Log.e("TAG", error.toString());
      L+ Z) b) l) ?+ M' Q* L0 K9 J! g% Z! d            }" `: \5 ]! x9 g, `
                @Override
    # Z9 {1 z" H2 J8 k3 \. ^) a            public void onProductDisconnect() {
    ' M" R7 h7 P) b: {4 ^' j                Log.d("TAG", "设备连接");
      o/ e! V. y9 O. X/ @" k% M                notifyStatusChange();
    . X% i+ x, y' R" v& q" L            }1 O% S4 H( b( t# G6 G; R
                @Override
    * t1 P9 j0 ]1 p: i- R            public void onProductConnect(BaseProduct baseProduct) {
    * B+ Y1 L5 |& y                Log.d("TAG", String.format("新设备连接:%s", baseProduct));
    6 s7 Q$ e6 _1 V                notifyStatusChange();
    $ C" v# g9 ]0 n1 ~& j+ b6 ?# c            }
    4 g  ]* x/ r1 H- @4 Q' O( Y: W; g            @Override* d* \1 E: ]6 I/ U$ k
                public void onProductChanged(BaseProduct baseProduct) {
    " F% A' m" K' c/ V% }" b            }+ {& ^3 C% Q. ^+ l& K7 i
                @Override7 v6 b( C! @( s
                public void onComponentChange(BaseProduct.ComponentKey componentKey, BaseComponent oldComponent,7 W4 N9 p1 t( _; B/ `
                                              BaseComponent newComponent) {/ b7 O- @+ E. _- ^' A8 F, \( r
                    if (newComponent != null) {2 X, r( @+ D; G" L2 e
                        newComponent.setComponentListener(new BaseComponent.ComponentListener() {
    & P5 u3 q- e" e6 W                        @Override% A+ S' m9 B0 U& M( _
                            public void onConnectivityChange(boolean isConnected) {  J& x7 E5 h7 I7 ^! @' [* m1 E( a
                                Log.d("TAG", "设备连接已更改: " + isConnected);
    % g) y1 j! x4 U' a# o* l$ B                            notifyStatusChange();
    ) F: O3 A1 C* F% S6 j% x0 z8 s9 _                        }
    ) N( a$ Z0 O- m: ^6 ?                    });1 S* }! S. H3 [& W8 v. }* c7 I
                    }
    , i- O- N7 F* n                Log.d("TAG",' V' Y/ E$ a! G! X8 s5 a/ k! I
                            String.format("设备改变 key:%s, 旧设备:%s, 新设备:%s",
    ( x( P& }" }. L1 x* m                                componentKey,
    / g0 d+ ?+ N4 t% H. `* J( d0 B# e                                oldComponent,
    1 M- v) e' e! f$ _! q                                newComponent));
    * U8 N4 e! V' S5 c4 o& r/ ?+ C            }* F# j! A) v( `/ Q
                @Override0 w) {0 l; d3 x, k  k
                public void onInitProcess(DJISDKInitEvent djisdkInitEvent, int i) {3 W# w3 ~! X! q) `
                }
    8 z! }, H2 S% G* i% T            @Override  e5 I$ F! ]% n: i! i- v# j% K7 c
                public void onDatabaseDownloadProgress(long l, long l1) {
    ; P: z' t4 J+ m            }- Z* q2 n& S4 m4 m, y
            };2 E/ Z2 p3 i* b9 Q, ^
            //Check the permissions before registering the application for android system 6.0 above." Z9 L6 F) `5 h- x4 |& X7 x
            int permissionCheck = ContextCompat.checkSelfPermission(getApplicationContext(), android.Manifest.permission.WRITE_EXTERNAL_STORAGE);  `; N; T. h7 j! J
            int permissionCheck2 = ContextCompat.checkSelfPermission(getApplicationContext(), android.Manifest.permission.READ_PHONE_STATE);
    . T2 `- c9 d3 B- _        if (Build.VERSION.SDK_INT 0 && permissionCheck2 == 0)) {( l/ U* c/ H/ W! S- f: p* e
                //This is used to start SDK services and initiate SDK.8 ~+ y" D9 ?; f2 @  _
                DJISDKManager.getInstance().registerApp(getApplicationContext(), mDJISDKManagerCallback);
    + _3 C; v$ ]/ G: u2 S2 X8 }  i//            ToastUtils.showToast(getApplicationContext(), "正在注册,请等待...");7 b5 R% _' ]  }) M* T
    //            Toast.makeText(getApplicationContext(), "正在注册,请等待...", Toast.LENGTH_LONG).show();* [1 C8 C3 a# e; b+ G# p
            } else {9 m: c. ]8 }& H
    //            ToastUtils.showToast(getApplicationContext(), "请检查是否授予了权限");
    ' b: \5 }3 N; K& G& ]5 q//            Toast.makeText(getApplicationContext(), "请检查是否授予了权限。", Toast.LENGTH_LONG).show();
    : k( X+ `/ a. S5 ]( r        }& X0 v( ]/ s/ u; _4 U" t8 N
        }- \4 G' A1 J+ T( k$ Y
        private void notifyStatusChange() {
    8 z2 b7 P1 d' |* O& L: ~  Y7 [/ M2 k) ]        mHandler.removeCallbacks(updateRunnable);7 W) K' T  _' v5 \9 `7 ]' k
            mHandler.postDelayed(updateRunnable, 500);
    : n% C; k* ]$ s- o    }
    ! s4 u5 Y' f% k% z    private Runnable updateRunnable = new Runnable() {
    & {+ @" l& ^/ Z) e+ P        @Override
    0 m' ^# e  k+ Y+ n6 u: |- K        public void run() {2 r. ~; E  o9 _* ^
                Intent intent = new Intent(FLAG_CONNECTION_CHANGE);
    # I, J: w! G, r! O; s1 t            getApplicationContext().sendBroadcast(intent);8 w- _4 W+ \/ ~' @: y3 {8 \0 F
            }5 A- |  W9 ~: h* D, @% K2 k
        };2 I" O5 c- F; j) S6 G
    }. k6 \4 q) r( l
    上面的代码是对BaseProduct、Aircraft和Camera类进行实例化,在后续使用中不用再去进行重复的实例化工作,减少内存的消耗。
    0 {3 o) e# Y1 M% O  D3 u: S@layout(R.layout.activity_registration)0 _! K$ l* c0 n: H, J% u
    public class RegistrationActivity extends BaseActivity implements View.OnClickListener{" Y; D) B$ N' \
        private static final String TAG = RegistrationActivity.class.getName();! y/ T3 _0 _" }& I- R
        private AtomicBoolean isRegistrationInProgress = new AtomicBoolean(false);/ p; M( D; ~+ X3 j2 n7 H
        private static final String[] permissions = new String[]{
    ! E4 [9 q1 f# P            Manifest.permission.BLUETOOTH,7 g6 t8 ]. ~; O
                Manifest.permission.BLUETOOTH_ADMIN,  N, M  f* |# M& U
                Manifest.permission.VIBRATE,4 `5 `- k& Y/ a0 R  T
                Manifest.permission.INTERNET,
    5 L2 R0 D- _- W) W4 T+ V6 {/ O            Manifest.permission.ACCESS_WIFI_STATE,
    . K; W- F5 I+ E5 z9 q$ {: v& x            Manifest.permission.ACCESS_COARSE_LOCATION,
    0 k. V2 y# I# t( H" Y            Manifest.permission.ACCESS_NETWORK_STATE,, J' F/ V+ B( U6 B# K
                Manifest.permission.ACCESS_FINE_LOCATION,5 x7 `4 t# r, ~* [: q: F/ W
                Manifest.permission.CHANGE_WIFI_STATE,. s: ]* X( Y6 G
                Manifest.permission.RECORD_AUDIO,+ B; X8 f3 E4 s. K, Y4 {8 p  i
                Manifest.permission.WRITE_EXTERNAL_STORAGE,$ S# b, ?5 H1 e( v
                Manifest.permission.READ_EXTERNAL_STORAGE,
    ) [* T6 @$ ~/ C            Manifest.permission.READ_PHONE_STATE,& n" D7 g6 G. D7 h. x/ v$ ~
        };
    + i. C; t, p/ I' d. T' @( d8 E
    3 G) x% F" T" |7 |/ E    @Override4 d+ Y/ i( m5 `, q. T# A
        public void initViews() {. O4 D* w( n2 N: m/ L: J
            isPermission();( \( V& u6 |1 ]; }" t
            IntentFilter filter = new IntentFilter();$ F/ s) m- ], b( d0 t
            filter.addAction(ReceiverApplication.FLAG_CONNECTION_CHANGE);! P% V# O% s3 W9 E$ c4 k
            registerReceiver(mReceiver, filter);
    / L0 f; X6 ~9 K/ M1 Q6 ?    }
    : Q  h% {/ X) ]! s7 U8 q    @Override
    ) |) z/ z( X3 q7 a) o( N) o/ [    public void initDatas() {  q7 D0 _2 i8 I9 j+ q! p, r
            startSDKRegistration();* I; y9 _; r, t% N# @
        }
      `& d9 N8 e; `" _4 B$ x: L) }    @Override( M/ b, m- h4 o  ?& p
        protected void requestData() {
    8 M8 O$ i& ^+ F; R        
    ) [4 z+ V% y. Y+ c    }( [' u& ]" @2 O; P

    9 z1 w2 k$ u& j" p9 u    @Override- Y# {2 N! ?2 n+ M) C. b2 p
        protected void onResume() {+ Q7 I  R6 \5 F9 z5 \0 g$ [
            super.onResume();' `  c/ j) u( D4 E4 o0 Q
        }+ \% K+ Z" I# y1 [9 h  r. K
    9 j. C6 d+ d3 J" R' H4 c- U
        private void isPermission() {7 ]& o# ]; y) G
            requestRunTimePermission(permissions, new IPermission() {6 s6 Z* \- I( r: a7 |
                @Override
    - c) j' ?* |0 l/ a- I            public void onGranted() {& ^& `9 }  ?- J0 P8 o9 @
                }& M  G  R8 k9 ^1 D
                @Override
    : R1 \& z! |2 c+ R: a            public void onDenied(List deniedPermissions) {
    - B8 T7 x8 h$ w1 G& S            }3 ~8 m6 G  f  I! u, ^0 S
            });
    6 c1 [. [2 o5 P8 S# n& l  f8 g! W+ }    }
    5 p& ]6 P% N  d  ' B; o0 G  Y+ ]% ~7 R7 [3 _' b
        //无人机首次注册
    8 g$ \3 P, h  @; q  d* z        private void startSDKRegistration() {
    . g. }2 G/ T/ z1 k4 s; `! F/ ^) {            if (isRegistrationInProgress.compareAndSet(false, true)) {% H+ B' @+ ~  I. ~. F0 C! W( I
                    AsyncTask.execute(new Runnable() {7 v0 W: ^" o) [' J
                        @Override  d8 b! G- k: d# |. R5 w+ ^) o
                        public void run() {9 D0 |9 Z/ B9 q/ h4 e
    //                      showToasts("注册中,请等待...");
    8 X2 X: W! G3 O1 u                        DJISDKManager.getInstance().registerApp(getApplicationContext(), new DJISDKManager.SDKManagerCallback() {  u1 h) X# u4 {5 V
                                @Override$ @) D6 T+ J' X; ~5 u
                                public void onRegister(DJIError djiError) {
    . O& L' g5 g' W+ t                                if (djiError == DJISDKError.REGISTRATION_SUCCESS) {
    / u/ T% v! v: H% m- y# i, E% H2 s( O                                    DJILog.e("App 注册", DJISDKError.REGISTRATION_SUCCESS.getDescription());
    % f+ i' B# e& X) w                                    DJISDKManager.getInstance().startConnectionToProduct();, N  r& c$ o9 L
        //                                showToasts("注册成功");
    ' w# s) Y" {2 q: r                                    loginAccount();
    2 V( I+ I- {7 v  u7 A7 I                                } else {
    6 ^* R* e( t. o                                    showToasts("注册sdk失败,请检查网络是否可用");
    : M1 ]0 T; z/ Z: o                                }
    & e- V4 O/ t: n/ @                                Log.v(TAG, djiError.getDescription());* L! C: w; a; b4 Y- U
                                }4 E3 ^% e. Y- ]
                                @Override
    5 \) M" X  |' C: H                            public void onProductDisconnect() {, @* g; D0 r; R( ], @1 K$ W
                                    Log.d(TAG, "产品断开连接");: ]- C0 X3 Q- O8 @  F
        //                            showToasts("产品断开连接");' q9 y9 ]. t( ~. U, Z
                                }& I) o0 M6 B! \4 j. J) }) ?* T
                                @Override
    ) o6 N3 l$ O/ F* d) a                            public void onProductConnect(BaseProduct baseProduct) {8 i/ B! e4 O! C, Q' p, C% o
                                    Log.d(TAG, String.format("新产品连接:%s", baseProduct));
    . d7 v' w3 i7 w* L* y' @# ~1 w    //                            showToasts("产品连接");9 A) x2 V3 s3 R7 l4 \1 y2 ]
                                }
    ' ]; g" C1 M2 X# i; E  m                            @Override! K2 e# r. T0 t4 n5 g/ N0 _7 b
                                public void onProductChanged(BaseProduct baseProduct) {1 D/ _* S. |6 m7 _& p, g
                                }" _, X9 V, ^( s
                                @Override
    6 A9 e9 J$ ]2 m$ j- w' Z                            public void onComponentChange(BaseProduct.ComponentKey componentKey, BaseComponent oldComponent,
    , x5 R; i- s' Q7 v# [1 ~                                                          BaseComponent newComponent) {
    2 U  L8 O  N; n# d, j                                if (newComponent != null) {$ O) w+ C) V4 @/ i( j
                                        newComponent.setComponentListener(new BaseComponent.ComponentListener() {4 a- ~: N5 [: d! S" V" y
                                            @Override
    % Q- B* v8 d+ f4 u* K, @6 z# H                                        public void onConnectivityChange(boolean isConnected) {6 [- a1 p. z/ Y0 {
                                                Log.d(TAG, "组件连接已更改: " + isConnected);
    2 l; E- T) j8 Y" S% ?! k: {                                        }& l* t* g5 b  ]+ |
                                        });
    " U+ O) {+ t) G: p3 F                                }% J' w. I2 i8 \, ?8 D. e/ z& C# l
                                    Log.d(TAG, String.format("改变设备Key:%s, " + "旧设备:%s, " + "新设备:%s",
    " _/ o, z2 I" T6 P% k                                        componentKey, oldComponent, newComponent));
    ) H0 i( r7 M& k* p: z                            }3 Z. l( K) @8 ]! E1 G! O& Y
                                @Override# |: d9 W" n8 N5 L" z1 [+ {9 d: P
                                public void onInitProcess(DJISDKInitEvent djisdkInitEvent, int i) {
    + N( y- ~, H  Z' d0 z6 p; F                            }
    % c+ g* T$ F3 n+ C                            @Override
    / T7 K" L- T3 x5 u4 ?                            public void onDatabaseDownloadProgress(long l, long l1) {
    1 E$ Y. C1 I: l) J                            }8 l. P8 V9 S4 g% r$ P
                            });: l6 s$ c! e' [9 F
                        }
    5 C. s5 M' q/ o1 t7 M. K! T5 B                });" V1 @) ^" {8 a% K) G! Q
                }
    ! W0 ?/ ^# |4 o' I- C" t- A- I        }6 f; j- C% t/ p" c" k+ Z: J
        protected BroadcastReceiver mReceiver = new BroadcastReceiver() {
    + Y6 c! A4 g  s0 {        @Override
    $ d5 n/ a2 T% G7 w        public void onReceive(Context context, Intent intent) {. _) R5 G: g7 E% f; z7 R% i
                refreshSDKRelativeUI();
    ( A. Q: N5 }% x$ g, \        }
    / R) z- [8 t/ C% @& W' _    };, R+ [3 S+ L0 R; o/ N, X
        private void refreshSDKRelativeUI() {; w- f1 R3 X! L1 k+ y$ h) Q! Z
            BaseProduct mProduct = ReceiverApplication.getProductInstance();/ D( X/ O6 G4 y0 S- O2 X% _
            if (null != mProduct && mProduct.isConnected()) {9 e% V* s. B9 z3 j1 f
                Log.v(TAG, "刷新SDK: True");) S- n+ H, w0 ~! j. ?' U; L
                mButtonFlightTask.setEnabled(true);6 M* o  P5 r& i
                mButtonSettingRoute.setEnabled(true);
    ) y' ~1 y" r6 z0 o# E7 w            mButtonFileManagement.setEnabled(true);! Z( a2 a8 F! o+ j
            } else {& a' y) `0 M! O; t" X% Q9 m
                Log.v(TAG, "刷新SDK: False");
    + o( U4 B3 j& C8 G( F//            mButtonOpen.setEnabled(false);% i# M9 ]% [5 j" Y; \( e( G1 r8 ]
    //            mButtonSettingRoute.setEnabled(false);
    5 g' |: n8 }# C, @& u& C//            mButtonFileManagement.setEnabled(false);
    . ^- B; W; @5 I* \& c4 o//            startSDKRegistration();$ A0 n7 U4 t0 ?, X
            }
    ! T$ W% w1 m. o4 i# S) p- p, V9 d    }0 n) _9 u; K1 O" i
        protected long exitTime;   //记录第一次点击时的时间2 I- K/ M3 v6 ~$ N
        @Override$ T' Y5 u. }& S! X% D* R9 B% l
        public boolean onKeyDown(int keyCode, KeyEvent event) {0 R# u/ V9 x7 b& G- s# B2 H
            if (keyCode == KeyEvent.KEYCODE_BACK) ?( ?! P% `' x3 u- C2 i& u
                    && event.getAction() == KeyEvent.ACTION_DOWN) {
    ' Z3 z/ V" U* C  U1 g  c            if ((System.currentTimeMillis() - exitTime) > 2000) {* N' T' D+ n+ y$ I) h2 h4 _2 T
                    showToast("再按一次退出程序");
    ( Y  z* i+ n, {2 j                exitTime = System.currentTimeMillis();
    ( F" q" n: O8 @) {/ _            } else {
    4 V( s" A1 w% K8 [% C' B                RegistrationActivity.this.finish();4 }$ w9 H: [' w1 |
                    System.exit(0);
    / @# z* h" S1 h- q+ _            }
    , G9 G' ~  J6 d9 ^            return true;
    7 j  G1 i. O# E; J5 M        }
    2 V3 T( [; [. {        return super.onKeyDown(keyCode, event);/ ~9 x* Q" G. x
        }
    7 ~& {+ c& @* |( c* R% C, v' r" e2 v
            private void loginAccount() {0 r1 a: k9 K+ p3 f/ F& V% O) V* b* H/ }. T
                UserAccountManager.getInstance().logIntoDJIUserAccount(this, new CommonCallbacks.CompletionCallbackWith[U]() {( `: J) m" s5 k/ Q  h
                    @Override& n. x/ Q- l; x. a
                    public void onSuccess(UserAccountState userAccountState) {: C8 g7 I' p& R# q3 B
                        runOnUiThread(new Runnable() {6 W  ^* y+ c8 F
                            @Override
    4 V/ ~' d( W, K' E; [. x                        public void run() {
    " O5 C5 w6 q$ R: @# o$ r% I                            mButtonFlightTask.setEnabled(true);
    9 y, G3 J. T  {( M0 h                            mButtonSettingRoute.setEnabled(true);
    1 k4 y7 v5 |; c; y7 H- E; J/ ~' T" w                            mButtonFileManagement.setEnabled(true);
    * j/ _. J  C. Y0 u! Q- l0 ~" u# }                        }
    % w: l3 s7 L. A4 S& s$ J8 C                    });
    ( O. q- U! C" Y0 L9 @                }
    5 [# O9 h2 P1 k' f                @Override
    1 [; @; c' F. }3 e9 C' E6 k                public void onFailure(DJIError djiError) {
    8 G( M6 Y) |% I; z( Q/ U                }, W- d7 i2 l5 \+ e" J
                });
    ! T# p8 {8 j3 F& c. [: w) s( }! \        }
    8 g* M' D/ P1 o$ \; D}: l+ I& h" ?$ x7 r4 b) |" c, a" u  H: A
    上面的代码就要进行第一次注册登录了,当然你不需要自己去设计登录注册页面,大疆会调取自己的登录注册页面供你使用。3 K$ L" o7 z( ]

    mk1fg5zkzzj64015955923.png

    mk1fg5zkzzj64015955923.png

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

    " c9 Y) _; I; O$ ^- j" S  c" H2 j4 x    //获取飞机信息、云台信息
    # w" \5 O4 z2 Z) d& @    protected BroadcastReceiver mReceiver = new BroadcastReceiver() {
    3 t  j9 O$ x' ^6 y5 H& l  d        @Override: ^5 L  ^: O, `0 o
            public void onReceive(Context context, Intent intent) {
    & `8 M! G- C& f" ^1 W4 T/ p. b8 _            BaseProduct mProduct = ReceiverApplication.getProductInstance();& y) |0 y4 e( ~3 U( ?
                if (null != mProduct && mProduct.isConnected()) {( j: S/ a1 w- V( L+ ]. s$ f
                    flyInformation(mProduct);2 j/ S% A0 l( t: u  o, C
                    batteryInformation(mProduct);
    * C( g) l; g% i  |                cameraInformation(mProduct);& w( z4 ?2 H0 i2 E9 C4 D" f
                    camera(mProduct);
    ; i+ b* \5 Z/ n8 H9 ]//                MobileRemote(mProduct);1 o6 C' b$ a0 ]. L; _& S2 M
                }
    : @+ D& a' l- l" L        }$ c0 l1 F7 R% C% W( A
        };: I5 o3 x- r2 z6 C% y/ Y
    //    private void MobileRemote(BaseProduct mProduct) {: B6 ~* H" W: [
    //        if (null != mProduct && mProduct.isConnected()) {
    6 X" M; e! T5 s//            mobileController = ((Aircraft) mProduct).getMobileRemoteController();
    9 `3 e- K' i0 M# {3 n4 p) g//        }* H% C! ]7 n$ N# f" M' N
    //    }
    9 E: i1 T* ~- d' L    //获取飞机信息5 G! _1 b1 z1 D% B5 N! Z0 k
        private void flyInformation(BaseProduct mProduct) {
    : w4 T6 }, ?) U2 s        if (null != mProduct && mProduct.isConnected()) {- s7 A# M0 |1 M4 t
                controller = ((Aircraft) mProduct).getFlightController();
    $ R8 F( I& d9 P! F; P, r        }
    $ G. z0 O% v8 c( u: w% N        if (controller != null) {3 X$ ?) }2 I& `( C! ]
                controller.setStateCallback(new FlightControllerState.Callback() {" P% r! w" C2 G( m5 t
                    @RequiresApi(api = Build.VERSION_CODES.O)/ t* ?. z! p4 H7 w9 D+ J, U/ ^
                    @Override
    ; y5 M, B: ]/ q' [                public void onUpdate(@NonNull FlightControllerState flightControllerState) {
    # I: q% g9 i5 K, x  _                    //纬度、经度、高度、俯仰角、滚转、偏航值、速度
    9 P6 g6 b0 I( w                    lat = flightControllerState.getAircraftLocation().getLatitude();* p5 w$ H" F# `. W" L
                        lon = flightControllerState.getAircraftLocation().getLongitude();- r4 L5 u( _  O8 C
                        high = flightControllerState.getAircraftLocation().getAltitude();
    2 J: x8 l% g$ ~; r+ g5 e5 ]; d                    attitude = flightControllerState.getAttitude();0 w' I' Z; y1 s' h1 E
                        pitch = attitude.pitch;& B2 o4 f1 j# B: V( y
                        roll = attitude.roll;- C' f, G" x% S7 l% R) |
                        yaw = attitude.yaw;5 ^1 b  ]. z/ u' w, f* T$ G
                        velocity_X = flightControllerState.getVelocityX();
    0 I, }' D' U; e; z1 F( Z$ x* j                    velocity_Y = flightControllerState.getVelocityY();1 S* V7 j- Q) X5 |3 o. Y
                        velocity_Z = flightControllerState.getVelocityZ();2 D) U3 s( ]& ~% l% A7 P; o
                        isFlying = flightControllerState.isFlying();
    8 i* [0 f2 z: F- x" v8 B                    //                    MyLog.d("经度:" + lat + ",纬度:" + lon + ",高度:" + high + ",角度:" + pitch + ",速度:" + velocity_X + "," + velocity_Y + "," + velocity_Z);& }2 v8 [9 |& M' X
                    }
      k6 x' G) {7 _/ O! M            });
    . }5 J5 t; j, _            controller.setVirtualStickAdvancedModeEnabled(true);
    & k8 e4 P$ N* @) c0 n- [/ S            controller.setRollPitchCoordinateSystem(FlightCoordinateSystem.BODY);
    2 h. _3 N5 U: W0 W0 H            controller.setVerticalControlMode(VerticalControlMode.VELOCITY);1 ]% t$ I# ?2 s2 C1 Q
                controller.setRollPitchControlMode(RollPitchControlMode.VELOCITY);
    # ^7 {) {+ M' H8 E2 z, ^5 C: A$ r8 _            controller.setYawControlMode(YawControlMode.ANGULAR_VELOCITY);
    ! m3 U: j) Y3 _//            controller.setTerrainFollowModeEnabled(false, new CommonCallbacks.CompletionCallback() {
    % B; y* ?7 D+ E. C//                @Override
    / ^: [7 ^' Q7 P( @9 \//                public void onResult(DJIError djiError) {! m# J/ m8 Z5 Q
    //                    MyLog.d(djiError.getDescription());
    $ p# w2 R7 \+ Q1 ~//                }
    # i) y7 N! t  X$ h2 _//            });
      `9 g2 h( w0 m' x2 P2 N" u5 z6 v//            controller.setTripodModeEnabled(false, new CommonCallbacks.CompletionCallback() {
    4 t  R8 c- B7 I( P" f2 \//                @Override. g; D1 `' S) w( ]5 `
    //                public void onResult(DJIError djiError) {
    7 }% Q2 H9 y; q//                    MyLog.d(djiError.getDescription());
    / u: G! [5 g5 P" R" _3 k//                }
    9 t' k+ N7 j) f: \//            });
    4 z. C- D! }1 c+ P; N//            controller.setFlightOrientationMode(FlightOrientationMode.AIRCRAFT_HEADING, new CommonCallbacks.CompletionCallback() {4 [. Z! o& W, X" a) z
    //                @Override( J: C. M5 j6 w4 J/ C, y
    //                public void onResult(DJIError djiError) {# A2 J! L7 O% R$ }  L
    //                    MyLog.d(djiError.getDescription());
    . X* K3 J- b% y4 z8 ~6 p//                    if (djiError==null){
    ' \: i2 x% V# Z: _//                        if (controller.isVirtualStickControlModeAvailable()){; E5 V" ]  {% z, I
    //
    $ C9 A% e& b- p: e2 v$ `% c//                        }else {
    # ?3 ^3 ^, r; v- ^//                            MyLog.d("虚拟摇杆模式不可用");
    ( Y( v6 m" |7 b+ J! [//                        }; M+ V' l: f# G4 }
    //                    }
    : L9 \4 f& y: S$ t  G3 {) y% d; X//                }6 Z7 I) S6 I/ P" s8 c% M
    //            });6 [. p7 S* P, z
            }$ e8 g0 |2 q/ z5 H( `$ W, }/ G' {
        }
    7 e2 M- F# J! U. d    //电池信息, o2 x; u" w% @. x% k" X8 o: Y. w
        private void batteryInformation(BaseProduct mProduct) {
    7 {3 d- p  B& H! n, `        if (null != mProduct && mProduct.isConnected()) {
      t2 T) X) l1 x" {8 B& s" }7 @            battery = ((Aircraft) mProduct).getBattery();
    4 y& w, @' S4 k5 P! G/ Y& E, z        }
    4 t1 ?9 p5 Y/ Z; y' K        if (battery != null) {
    ; Y6 W6 K# X% Q. v            battery.setStateCallback(new BatteryState.Callback() {: F' S4 c" r7 ?  _0 N. k- T" S
                    @Override
    : g3 u4 W# o! G5 v* c1 m1 Q$ p                public void onUpdate(BatteryState batteryState) {
    * z9 m! }( H1 p! B/ [1 C                    //电池电量" `$ |% R5 Q  Z: G& z
                        power = batteryState.getChargeRemainingInPercent();( ]* ?5 l$ o; u1 h( ]: {/ ~
                        //电池温度1 M& F) f: Z" Z, t7 p1 C$ M& z
                        temperature = batteryState.getTemperature();) ^* G$ L9 Z. w+ K: k1 f; L
                    }
    + d! ?$ n2 r( g- B9 F            });
    / u+ N1 J) o$ t+ r9 Z7 Y  H$ A" p        }- E+ N/ U( i2 e2 L8 Q
        }
    / ]  ^) |6 c  t4 V7 Q1 _/ _6 D    //云台信息# X6 G9 B8 m$ i
        private void cameraInformation(BaseProduct mProduct) {
    ; j& j  ^/ ^. i/ p+ m3 ]        if (null != mProduct && mProduct.isConnected()) {- ]% q7 h7 h7 A
                gimbal = ((Aircraft) mProduct).getGimbal();
    5 a! C- A4 Y, l- a, R7 t7 k        }+ v$ Y0 d4 ?5 x) @
            if (gimbal != null) {- A: d' ~7 x: ]. W1 j+ J
                gimbal.setMode(GimbalMode.YAW_FOLLOW, null);
    4 Q: G; ~* {# f& t" A6 f" h! Q            gimbal.setStateCallback(new GimbalState.Callback() {7 H' c& O/ y1 W  C0 Y
                    @Override# U% K" U  b$ i. R6 f) b% H
                    public void onUpdate(@NonNull GimbalState gimbalState) {: S$ r0 v8 |0 i. V3 L9 a
                        //俯仰角、滚转、偏航值
    % p1 A, i* @8 j! P0 V/ n# h, u- F: b                    g_attitude = gimbalState.getAttitudeInDegrees();/ c8 i* w) W  t
                        g_pitch = g_attitude.getPitch();
    6 n. A" r% U) d; S, o* k                    g_roll = g_attitude.getRoll();
    5 c2 ?  v) ~0 o& U: s! v$ T  x$ _5 L                    g_yaw = g_attitude.getYaw();
    0 \* }/ D3 t8 Y! Q. h7 Y& d; u4 g* c. E                }# z7 V5 W& v6 x% N! f3 r
                });
    ; m. q+ _# z, Y* _% e: }        }/ s3 }! C5 v3 K7 f& {4 Z) [
        }
    , }) U' Z$ x: }% a4 L    private void camera(BaseProduct mProduct) {( T' L; w, y3 D7 N! j  e+ B
            if (null != mProduct && mProduct.isConnected()) {+ C7 w  f1 Q# [) K+ w/ _2 d5 c
                camera = ((Aircraft) mProduct).getCamera();- r& d$ P& R4 T. H7 o
            }
    4 g" v1 b9 v; F4 @        if (camera != null) {9 C8 V+ a( A0 n. e* Z
                //            camera.setVideoCaptionEnabled(true, new CommonCallbacks.CompletionCallback() {3 Y  S: ]6 X+ s% b1 }2 E4 J% h& w
                //                @Override
    * S. Q* a- a- D) x; C( i            //                public void onResult(DJIError djiError) {
    1 ]( Z+ X) F: q8 d& a            //                    MyLog.d("VideoCaptionEnabled"+djiError.toString());
    0 g( n9 B( G3 h) [7 _: `            //                }  t# a+ x3 r$ g' T( B
                //            });
    $ s. `. t- o. F            //            camera.setMediaFileCustomInformation(projectId +","+trajectoryId, new CommonCallbacks.CompletionCallback() {" K* j- p' R6 l5 j
                //                @Override& j2 s& |- q1 i+ r2 n% }
                //                public void onResult(DJIError djiError) {
    9 `5 d! N% ?/ K& o' K  L; j! I8 g            //                    MyLog.d("自定义信息:"+djiError.toString());+ m- B: g! w5 o# e4 O
                //                }
    & w) y! l% y' q; b. j) x9 N' r" L            //            });
    4 {( @" Z* q4 D1 ^            camera.setSystemStateCallback(new SystemState.Callback() {
    ( B9 J/ k7 i) {8 N) J                @RequiresApi(api = Build.VERSION_CODES.O)! f0 R; A  `: n+ C7 z- z1 `4 Z
                    @Override/ I9 n& a2 J" P/ f, A5 A/ Z- I
                    public void onUpdate(@NonNull SystemState systemState) {( G# n$ o. O: C# w# @3 W0 |
                        if (systemState.getMode().equals(SettingsDefinitions.CameraMode.SHOOT_PHOTO)) {* T: B" Z8 ]' |
                            if (systemState.isStoringPhoto()) {
    4 Q, O2 v( K  a. N" @7 f9 }3 A' ?                            dateStr = Long.toString(System.currentTimeMillis());* ?& e" R0 r9 p- Y. q9 G. a
                                list.add(new DeviceInfo(dateStr, lat, lon, high, pitch, roll, yaw, velocity_X, velocity_Y, velocity_Z, g_yaw, g_roll, g_pitch));! o9 \4 V, r. ?; r& k% A0 d. @
                                CsvWriter.getInstance(",", "UTF-8").writeDataToFile(list, FileUtil.checkDirPath(FLY_FILE_PATH + "/照片数据") + "/" + DateUtils.getCurrentDates() + ".csv");
    1 V8 W! s9 t# @( _0 u                            list.clear();
    " |( m- x/ W. G- b6 E; y                            return;( x6 |9 N: z( P9 p# m% \
                            }( G; m3 q5 \# J. A
                        } else if (systemState.getMode().equals(SettingsDefinitions.CameraMode.RECORD_VIDEO)) {
    3 q' H0 N5 m1 f; }/ F' t6 O& U$ K                        if (systemState.isRecording()) {
    , q8 l: |0 Q' B6 C, B                            try {# f* Y6 ~4 ~( G" k9 |
                                    dateStr = Long.toString(System.currentTimeMillis());
      Z  v2 ?: u/ f6 u! g6 F: J- b                                list.add(new DeviceInfo(dateStr, lat, lon, high, pitch, roll, yaw, velocity_X, velocity_Y, velocity_Z, g_yaw, g_roll, g_pitch));  \& f5 G4 s& W: L4 O% C1 ^! h9 d
                                    getList.add(dateStr);
    + w  j2 r+ N  |1 M! {7 y                                Thread.sleep(100);5 v+ S  B. M% I$ d' F+ Y
                                } catch (InterruptedException e) {1 ^4 o  W: t- r5 M. d4 q
                                    e.printStackTrace();
    . @- w& ~: n) o. M                            }- B* O0 M" c/ U  M! Q, V
                            } else {
    ( }) D$ p# e& A( u  E! I                            if (list.size() > 1) {
    9 @5 @3 Z0 i/ q+ o                                posName = DateUtils.getCurrentDates() + ".csv";5 l; \' ]( Q7 F/ M8 k! b' ?
                                    CsvWriter.getInstance(",", "UTF-8").writeDataToFile(list, FileUtil.checkDirPath(FLY_FILE_PATH + "/视频数据") + "/" + posName);
    & z- U# O7 K. I% }3 A+ i                                list.clear();* h) s6 C, J# d9 ^  _3 f4 U, I8 n
                                    runOnUiThread(new Runnable() {* z  n: g  C, j3 h
                                        @Override" x; \, I4 m" _
                                        public void run() {# Q/ d; ^$ k9 q9 m. t9 p
                                            getFileList("end");
    8 |* b" I$ b8 e% r# }) a0 G                                    }+ z) W5 m# M7 b
                                    });
    * b0 C" d/ B& z                            }
    5 E5 T+ q4 ?' @7 c                        }
    ( b* ^8 ^" }5 h, ]0 D" B                    }: S" T* h( }& c4 a8 T4 o: n
                    }* E  t4 f3 m  [6 ^8 q, j1 f
                });* Y+ W$ S& r4 D; O! |
            }
    % n4 |5 I& ?  X6 _% Z    }
    ; v- T! C; `8 P5 }# t* v# ?    //遥控器信息6 N* @, m* O, k3 H/ D
        private void handheldInforamation(BaseProduct mProduct) {
    : O' e5 K& F0 t% T        if (null != mProduct && mProduct.isConnected()) {
    # y3 f2 a+ V, w" l8 @! N$ X( E- @0 t            handheldController = ((HandHeld) mProduct).getHandHeldController();
    6 o, Y3 q7 ~4 W        }1 W' a, E4 A  Y
            if (handheldController != null) {
    1 c4 v# P5 S3 Q" x            handheldController.setPowerModeCallback(new PowerMode.Callback() {/ c  d5 ~5 F8 M) R4 X
                    @Override' ~2 ?! ^1 j) G- p5 q8 J2 s
                    public void onUpdate(PowerMode powerMode) {
    2 @4 R# V- A" i$ M                    switch (powerMode) {( t8 x; L+ T) Y9 T  y3 k4 c
                            case ON:
      M; T9 g$ }6 c                            Battery battery = ((HandHeld) mProduct).getBattery();/ I+ y+ n* I6 R& H' v  A
                                battery.setStateCallback(new BatteryState.Callback() {
    . h5 n4 b& b- h" o# ]; G" O+ K" N                                @Override
    . V& e  ]& `$ G) k8 l) w% ^                                public void onUpdate(BatteryState batteryState) {4 ]3 g- c% M3 _1 D2 ~
                                        h_power = batteryState.getChargeRemainingInPercent();$ i2 _$ D, D) X
                                    }* y3 h, @# @; @, r/ ~
                                });2 m' E) ^0 R$ j6 g
                                break;
    2 Z1 C3 s* a/ V( l                    }
    9 [/ f( S7 ^2 {3 A" e                }
    9 d3 _2 |' D/ B+ D6 Y; f            });5 Q$ B) {; R0 I& |
            }4 x4 Y+ L* b6 z, ~
        }
    1 t5 _7 \8 i4 Y2 |  ~   
    ) R7 r6 v6 Y1 d+ o    @Override
    9 w7 r; l5 [6 v" |' a! ^    public boolean onKeyDown(int keyCode, KeyEvent event) {
    + p. ^0 C* q. s& p* T        if (keyCode == KeyEvent.KEYCODE_BACK
    & b/ d) h( M- J7 K* j                && event.getAction() == KeyEvent.ACTION_DOWN) {) r, f$ j1 b" J( k8 e
    //                        closeConnect();% c' T  X  u0 G# r$ V3 z0 R; z
                MainActivity.this.finish();
    $ d9 B5 `+ u% |        }+ g$ ^  C- x% Q. I
            return super.onKeyDown(keyCode, event);# g& r7 I+ Y" A9 u9 k# o
        }* p; R7 ~% U. e; N9 R% a
    }
    , x+ q# R  A! _. ]* A+ K. A: O完成后界面如下所示:
    3 V& }  r: I, _( y/ m  O; Z6 f

    sz1bbeuylep64015956024.jpg

    sz1bbeuylep64015956024.jpg

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

    splrzdloa3i64015956124.jpg

    splrzdloa3i64015956124.jpg

    # U  k4 u+ K8 v  D, U: |
    : h8 ]- j& ^/ D

    szmxbq0ilqc64015956224.png

    szmxbq0ilqc64015956224.png

    & O& t, N7 B  {% `9 x  F' c往期推荐LabVIEW OCR 实现车牌识别
    $ I) S" z6 e- S" j; o和12岁小同志搞创客开发:有意思的激光切割技术' H; C0 J7 c9 K1 J
    JavaScript+TensorFlow.js让你在视频中瞬间消失
    , U; k9 ~5 {) X# \' l使用OpenCV测量图像中物体之间的距离+ ?2 z5 b8 \+ J' R2 I
    全网仅此一篇:工业级压力传感器设计及实现  J7 Q- ]- m5 ?# p' a/ c* F7 G
    6 X- v6 l% C8 _6 N+ V$ n

    libqpzwnv4k64015956324.jpg

    libqpzwnv4k64015956324.jpg
    6 r, V$ y% k9 D2 E( Q$ {

    eaw5giox2vj64015956424.gif

    eaw5giox2vj64015956424.gif
    6 x5 D- ~8 @$ X: n0 k5 `
    点击阅读原文,更精彩~
  • 回复

    使用道具 举报

    发表回复

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

    本版积分规则


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