电子产业一站式赋能平台

PCB联盟网

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

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

[复制链接]

854

主题

854

帖子

8398

积分

高级会员

Rank: 5Rank: 5

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

3qnnlgeqxdf64015971050.gif

3qnnlgeqxdf64015971050.gif
) u8 _7 |$ D6 v4 q) `* E
点击上方蓝色字体,关注我们
. G; J: p, x. b) l9 ?( o8 Z+ j
  c5 d; r/ J/ B  ~9 g& y上一篇文章(基于Mobile SDK V4版固件开发大疆无人机手机端遥控器(1))因为时间原因介绍了一部分内容,如果已经完成上一篇内容的操作就可以进行下面功能方面的制作了。自己开发的APP功能不是很多,但是已经将大疆无人机的常用功能进行了结合,同大家一起进行学习~
$ f' f+ z. q8 l) O/ J17 X0 S2 V" [+ c0 `7 W7 X
应用程序激活与绑定
9 `, x, g, v3 D, |" o如果在中国使用DJI飞行器固件,则需要使用该用户的DJI帐户激活控制DJI飞行器的移动应用程序。这将确保大疆能根据飞行器的地理位置和用户个人资料,为飞行器配置正确的地理空间信息和飞行功能集。激活系统的主要是:) q3 u5 j/ J/ m6 e2 [. A
  • 中国用户必须在每三个月至少登录一次DJI帐户以遍激活应用程序。
  • 激活信息将存储在应用程序中,直到用户注销为止。
  • 登录DJI帐号需要连接互联网。
  • 在中国境外,SDK会自动激活应用程序,无需用户登录。
  • 另外,中国用户必须将飞机绑定到DJI官方app中的用户帐户。这仅需要一次。如果未激活应用程序,未绑定飞机(如果需要)或使用旧版SDK(
    9 B3 g+ H  {# T& b9 ?

    * {- p. n/ R2 O! z, j2
    . V% g6 x: d2 R' J, v为应用程序创建UI编写MApplication、ReceiverApplication和RegistrationActivity文件(此处粘贴部分代码)。
    6 |: a9 A/ C6 p& K1 R) Rpublic class MApplication extends MultiDexApplication {
    8 F% o: T) v4 A# H    private ReceiverApplication receiverApplication;
    ; c# U& U9 j- o    @Override
    : M6 s+ G7 C) x! u9 S4 c    protected void attachBaseContext(Context paramContext) {
    . T5 `. }6 r6 O        super.attachBaseContext(paramContext);/ E8 T0 l/ ]6 V# c% o. s5 ~3 H! N
            CrashHandler.getInstance().init(this);. E. Y* j* H1 ?# O. u$ w6 g
            Helper.install(MApplication.this);
    ) m0 L. q4 L9 `( `( Z# e        if (receiverApplication == null) {$ K9 z' [6 _! F' A7 `% [& h
                receiverApplication = new ReceiverApplication();+ u' \5 K4 g; f
                receiverApplication.setContext(this);
    ( U& i; I! o4 s$ k3 l2 M: T6 i# {        }
    2 D; f% o! ~3 x0 w/ n! j7 f  u, T    }& o& p( T1 y* f; d/ G
        @Override
    9 u. L+ @+ @& l: U, N    public void onCreate() {
    / h/ J$ J0 y0 l8 L# s; T9 \        super.onCreate();
    ! Q5 ^. w0 `6 r9 ?        receiverApplication.onCreate();: U. j6 z/ C1 b) z5 p& }
        }  w! ~, a2 S: U; \" p
    }' ^% S, Y- U) v1 z2 O
    上面的代码实现了绑定当前APP,将后续需要用到的类函数封装到ReceiverApplication 中,在ReceiverApplication 中也能够进行账户登录的操作。
    2 ~6 V0 y" q8 P0 b0 w  Z7 i/ h0 ~public class ReceiverApplication extends MultiDexApplication {
    + k/ M3 ?$ L- X1 T, e* Q. i    public static final String FLAG_CONNECTION_CHANGE = "activation_connection_change";
    % P; e/ G: n# a1 ~( h( b& j/ j    private static BaseProduct mProduct;
    3 _# ^$ ^3 S" u- w: T2 O1 i    public Handler mHandler;
    9 _" n, z* I; L    private Application instance;
    9 I& ~4 x! n( `/ D    public void setContext(Application application) {
    : F* U; S* P+ p$ N4 H  n        instance = application;
    2 m% @3 {# F" v+ ~8 j5 h    }
    - m2 F! a- z, k" S, e9 q! b    @Override
    2 x( t3 t/ j0 K3 F2 B+ ^) ]5 l    protected void attachBaseContext(Context base) {
    " j( I* D* ~# d1 `% ]; n        super.attachBaseContext(base);/ _3 N* P* U# @: [
            Helper.install(this);
    0 b. Q2 f) ^3 I: V* `! a    }
    7 }& I" O, W  L9 u/ n    @Override
    4 |  g( D) a2 S# E    public Context getApplicationContext() {: e! q8 L( Q" X; M
            return instance;
    ; _" F- y5 A* A    }7 ^. W/ P: a0 T' t
        public ReceiverApplication() {
    # n. j$ E& D9 Y" z, {2 Z    }" g9 X# W. c/ L; D& P- C( K" F
        /**2 z" L# O" f1 R. X* l
         * This function is used to get the instance of DJIBaseProduct.# ?& L2 M! {# g8 n$ C3 E
         * If no product is connected, it returns null.
      G/ O; N' |. v5 Q     */- z6 e% p: W/ }
        public static synchronized BaseProduct getProductInstance() {
    ) d- p) F1 @2 g" e2 s- d        if (null == mProduct) {$ w, O  e6 Y3 T& `8 l
                mProduct = DJISDKManager.getInstance().getProduct();" o" s. e6 z% Z
            }
    ' O+ j' {; u4 N3 M( u        return mProduct;, V, d/ i! E& m
        }
    5 G: a2 j4 I+ F) S* R    public static synchronized Aircraft getAircraftInstance() {# e3 W3 ~1 `' P* u
            if (!isAircraftConnected()) return null;
    # U: ~" f; v' y9 ?        return (Aircraft) getProductInstance();
    / W1 g4 {9 x5 {$ ^2 o9 v    }
    , F6 \3 L7 N/ M, s    public static synchronized Camera getCameraInstance() {; k' T* b% v1 O) e% j" O8 ]  A
            if (getProductInstance() == null) return null;: u, y* b  K* c$ @  E
            Camera camera = null;& E- L4 T% m- h% s
            if (getProductInstance() instanceof Aircraft){
    3 J( D1 X5 ~' y" P% U! M            camera = ((Aircraft) getProductInstance()).getCamera();! @3 G/ p- p" r( L& E
            } else if (getProductInstance() instanceof HandHeld) {
    * x! H* t9 V# i' H9 ?            camera = ((HandHeld) getProductInstance()).getCamera();. X5 F  c  J6 J# m$ M! c7 O2 q8 H
            }2 G/ l* k* |2 Z8 j( Z+ B( _
            return camera;
    ) J/ @, V& b- R    }
    ! V$ x' ]; `! j/ {  q    public static boolean isAircraftConnected() {9 p8 d( Q5 u0 w) B: J8 ]
            return getProductInstance() != null && getProductInstance() instanceof Aircraft;* y4 q( o9 G2 V% r
        }
    : [) G0 W* R0 y1 Q6 \( K    public static boolean isHandHeldConnected() {  [$ w) j; s/ I" a1 L9 a! }
            return getProductInstance() != null && getProductInstance() instanceof HandHeld;% ~) k7 ]7 Q' Y6 N
        }
    : J; U1 ~3 e7 i9 S' k0 |    public static boolean isProductModuleAvailable() {
    " n6 i1 O$ S. o- r. X8 y6 s$ k% ^        return (null != ReceiverApplication.getProductInstance());
    * G$ l7 b* r* d8 y, w# N6 a; ~    }' \& z# _3 B' `
        public static boolean isCameraModuleAvailable() {
    9 L) Z2 q2 C& U+ C/ M* E; k        return isProductModuleAvailable() &&
    $ y& F8 f  y* _                (null != ReceiverApplication.getProductInstance().getCamera());
    7 z* o. y. i2 @9 X% }1 q    }
    & J. C$ ~7 e! f; R! U    public static boolean isPlaybackAvailable() {& q+ `) n% r3 W3 `1 h$ ^9 ^. {
            return isCameraModuleAvailable() &&
    5 p. D  t* x# ^* ?                (null != ReceiverApplication.getProductInstance().getCamera().getPlaybackManager());8 ]4 E; D' c) ~& }
        }
    0 Z- m! H( o5 c  ?' J% m    @Override
    # Y  S' H# s3 K2 H- V% m9 _    public void onCreate() {; o! t) p' }( F5 D) S; O+ X* Z
            super.onCreate();
    9 G( d1 }7 s5 ]$ @: _% l; S        mHandler = new Handler(Looper.getMainLooper());
    ) F8 j3 @# h7 U        /**" G6 R) X. T  Y- _+ w9 D# R; L
             * When starting SDK services, an instance of interface DJISDKManager.DJISDKManagerCallback will be used to listen to) W0 B/ o% M$ a" A  X9 r
             * the SDK Registration result and the product changing.
    5 ?5 x% B( a0 ~+ d' o6 j         */
    ) A9 F( s0 B/ ]7 y0 M& {4 m        //Listens to the SDK registration result5 g0 {6 y/ R  A+ ^
            DJISDKManager.SDKManagerCallback mDJISDKManagerCallback = new DJISDKManager.SDKManagerCallback() {
    , |# J: n( a9 P2 C. X* [4 X( l            //Listens to the SDK registration result
    $ X) G0 ^  |2 O0 i. Z            @Override. n, h; K# i/ Q) M; r. P6 j  D
                public void onRegister(DJIError error) {
    ; }0 p% h6 c3 I4 q: d0 q                if (error == DJISDKError.REGISTRATION_SUCCESS) {9 I& l/ p* @, ^- u* i
                        Handler handler = new Handler(Looper.getMainLooper());- G/ L1 t. [. i+ b2 L& j
                        handler.post(new Runnable() {  z0 C, h8 R3 y5 y5 w$ y
                            @Override
    & }; b9 N+ K& h                        public void run() {2 z3 @0 U% W/ C4 ~/ g( ~" `
    //                            ToastUtils.showToast(getApplicationContext(), "注册成功");, o6 _; M% G9 ^! x( k. R, }/ r
    //                            Toast.makeText(getApplicationContext(), "注册成功", Toast.LENGTH_LONG).show();( p3 p2 m2 @# |: O2 m' o
    //                            loginAccount();
    & M# F0 o& @- m5 X( u0 b! U0 o                        }
    5 F1 {$ l! t4 K  ]                    });
    / e  t# ]& B7 c3 \9 M4 y                    DJISDKManager.getInstance().startConnectionToProduct();
      _8 X% K: |5 P: c0 r% d                } else {
    $ o% k  H* Q; h( ^" I4 y                    Handler handler = new Handler(Looper.getMainLooper());
    , _' {, H0 x. L* F                    handler.post(new Runnable() {
    , t- |9 U( z' \                        @Override$ B; K. ?4 ]: a; Q" C) p
                            public void run() {+ K- H* z8 r5 A) l/ D
    //                            ToastUtils.showToast(getApplicationContext(), "注册sdk失败,请检查网络是否可用");4 f! K. p" ?" H! @$ ], n
    //                            Toast.makeText(getApplicationContext(), "注册sdk失败,请检查网络是否可用", Toast.LENGTH_LONG).show();9 L- ?5 ^/ y+ ^4 A# @. n5 C
                            }. i0 s5 G% Z1 b% E
                        });
    # S9 L) s; V: {, q9 M                }
    . I5 o/ o6 N; G6 f7 y6 P                Log.e("TAG", error.toString());; b4 p0 ]3 d8 d- ?. d
                }& J9 ?9 o/ m  X0 u0 \) D
                @Override/ f2 A. A- d3 g$ i! U
                public void onProductDisconnect() {) K/ h5 @  l( d4 M1 j) l( P
                    Log.d("TAG", "设备连接");3 K& f+ M5 F5 C/ q
                    notifyStatusChange();' s2 R( e. ?* y# _% r2 |: _8 e' C
                }5 \6 y( N$ J$ k4 k" c2 z  [7 _& \' `9 |
                @Override9 A) m7 \8 ]1 I) X+ E. c. j
                public void onProductConnect(BaseProduct baseProduct) {
    " A: R- t) p2 v% m9 Y' C# K                Log.d("TAG", String.format("新设备连接:%s", baseProduct));
    ' `2 l: p* R# R                notifyStatusChange();( K1 Q0 T3 h% M1 l
                }6 f5 n$ U: d7 [
                @Override
    ; y( P# m1 M- ]/ z0 E            public void onProductChanged(BaseProduct baseProduct) {
    * k% E9 M$ Y) K0 q- `            }
    6 t  I9 u' d) x. u# @, [" S            @Override
    ( n* C! \& t4 |6 E9 W. S            public void onComponentChange(BaseProduct.ComponentKey componentKey, BaseComponent oldComponent,
    / Q' ~0 D2 i4 R                                          BaseComponent newComponent) {2 f( o2 A( v8 V0 |8 D9 i& O& G
                    if (newComponent != null) {* U; ~% k  z' d/ U6 t" y
                        newComponent.setComponentListener(new BaseComponent.ComponentListener() {
    . F+ a) D; G4 ]                        @Override2 `# L5 R' ^/ r( L8 J
                            public void onConnectivityChange(boolean isConnected) {
    # R' Q9 X: V7 H9 p                            Log.d("TAG", "设备连接已更改: " + isConnected);
    ' o1 m" X! X9 K, F! c                            notifyStatusChange();) D' V# b$ @3 v( K6 e% t* U6 ^
                            }5 U  j& s# m3 x
                        });
      V/ {( X& y+ y0 h! `/ l                }' e0 _% d1 T% N& F1 C" W' I. U/ z
                    Log.d("TAG",
    8 @) f4 l# Z' i! S* e1 {                        String.format("设备改变 key:%s, 旧设备:%s, 新设备:%s",, j: ]% I8 D: F" B. n- S0 O0 b' o. y
                                    componentKey,2 o7 t+ m0 k. v- T6 a
                                    oldComponent,
    & ^+ ^: G2 e2 b, z3 r8 Q& p                                newComponent));( \( P& u1 d8 M5 j, H2 S$ I
                }# D# j4 U# _! q; ?9 x) g! c
                @Override0 Q3 T& v% z4 j4 u
                public void onInitProcess(DJISDKInitEvent djisdkInitEvent, int i) {
    7 \4 k( q' W0 t3 w            }$ p  u: @& Q% A3 C
                @Override' a+ G4 @, l4 }" I- ]6 B
                public void onDatabaseDownloadProgress(long l, long l1) {/ X) H3 b  Q1 Q' n, d
                }
    " i1 G- D3 Q& c. {  p8 @* q9 m        };0 m5 v1 W: O  i( s7 y+ C2 G+ m
            //Check the permissions before registering the application for android system 6.0 above.
    9 z) ^4 `0 s! D& U9 Q, h        int permissionCheck = ContextCompat.checkSelfPermission(getApplicationContext(), android.Manifest.permission.WRITE_EXTERNAL_STORAGE);
    # e8 V% [* t- ^6 x* O        int permissionCheck2 = ContextCompat.checkSelfPermission(getApplicationContext(), android.Manifest.permission.READ_PHONE_STATE);+ E8 A; ~* r' M! K) r5 ~8 H: C
            if (Build.VERSION.SDK_INT 0 && permissionCheck2 == 0)) {
    2 L& o4 G9 k  D% O7 j            //This is used to start SDK services and initiate SDK.4 u5 B, u" q8 n1 b: h$ L
                DJISDKManager.getInstance().registerApp(getApplicationContext(), mDJISDKManagerCallback);$ w# ]: [. q- h& w
    //            ToastUtils.showToast(getApplicationContext(), "正在注册,请等待...");! G2 w$ T0 f7 C2 Y9 g- _
    //            Toast.makeText(getApplicationContext(), "正在注册,请等待...", Toast.LENGTH_LONG).show();
    1 I# [6 Z4 \; ^9 v/ v8 G        } else {1 p# \, t, @* ]; \* l
    //            ToastUtils.showToast(getApplicationContext(), "请检查是否授予了权限");
    % W5 G% `& a3 [( c7 E  L- j) ?//            Toast.makeText(getApplicationContext(), "请检查是否授予了权限。", Toast.LENGTH_LONG).show();2 _) ]/ ^4 b5 s4 M, A! p
            }5 u, \& k# q+ i+ O
        }
    * W4 }% U% W2 X    private void notifyStatusChange() {
      e, \- j* ^( h0 K* u  N        mHandler.removeCallbacks(updateRunnable);& I& s  l0 ?0 _, z6 R8 G6 L
            mHandler.postDelayed(updateRunnable, 500);5 L" H: ?7 t& Q' o2 |
        }
    $ h- m% t& ^7 D7 R$ y    private Runnable updateRunnable = new Runnable() {
    - z7 N" F$ J  @: D        @Override( C9 J3 q" D) Q) B
            public void run() {
    . m+ g5 Y* C) x: \: r; i8 ?2 ~4 m            Intent intent = new Intent(FLAG_CONNECTION_CHANGE);
    3 Q! t- k1 v) ~) D* G$ W+ g            getApplicationContext().sendBroadcast(intent);
    7 ]9 f$ s( E" P        }
    . z/ T5 q* q% W, u    };: c9 o, T$ |. U% P6 _
    }9 _% L2 z" Q* S2 m% o+ b' w
    上面的代码是对BaseProduct、Aircraft和Camera类进行实例化,在后续使用中不用再去进行重复的实例化工作,减少内存的消耗。: Q, h1 _& q  M: b, c! Z( l+ O1 \3 _+ s
    @layout(R.layout.activity_registration)
    , d6 f2 v8 O- o+ k$ l4 Cpublic class RegistrationActivity extends BaseActivity implements View.OnClickListener{
    & X4 r" F* P  m+ s1 f    private static final String TAG = RegistrationActivity.class.getName();5 j2 }2 B+ r9 {: _/ F
        private AtomicBoolean isRegistrationInProgress = new AtomicBoolean(false);
    : s: B2 f5 W, X, L    private static final String[] permissions = new String[]{
    * P1 B: F7 n4 u            Manifest.permission.BLUETOOTH,( ^( [! K6 j/ t& F. i3 {3 r7 @
                Manifest.permission.BLUETOOTH_ADMIN,- {2 |. J8 Q# n5 R/ r  @
                Manifest.permission.VIBRATE,
    - P( S  j( y' P6 V3 Y* t( |            Manifest.permission.INTERNET,
    ! F* w9 s9 Z* }/ ~# l            Manifest.permission.ACCESS_WIFI_STATE,: }: ]0 ^( ]4 m+ a2 T
                Manifest.permission.ACCESS_COARSE_LOCATION,1 }* `1 D$ i" ?. X
                Manifest.permission.ACCESS_NETWORK_STATE,
    6 s0 L0 E0 I6 ]+ H            Manifest.permission.ACCESS_FINE_LOCATION,: l* S7 q5 V1 b- o4 y; N; }6 }
                Manifest.permission.CHANGE_WIFI_STATE,: Y- ?  P& @& H
                Manifest.permission.RECORD_AUDIO,
    / I/ M1 `7 B4 }6 j+ a# |* G            Manifest.permission.WRITE_EXTERNAL_STORAGE,0 }: a9 x3 Y( `
                Manifest.permission.READ_EXTERNAL_STORAGE,
    . S( L! _& R4 f" P0 O7 w7 t            Manifest.permission.READ_PHONE_STATE,6 ]' T$ e( \/ h' O* r
        };
    ! |- I$ S/ R* e
    9 L) e$ ^! e% s( K+ u- @$ q3 o/ D    @Override
    9 l; E" j/ A+ ~2 H/ F  A  j    public void initViews() {/ k" y: ]. x2 T7 V: C
            isPermission();
    " Y/ k% R; T9 [: X; O        IntentFilter filter = new IntentFilter();
    - T, P* Z+ ]; F7 L' q        filter.addAction(ReceiverApplication.FLAG_CONNECTION_CHANGE);
    - r0 S, s& z; f# p- ~& H2 C  ?        registerReceiver(mReceiver, filter);0 Y3 V( M" u: P$ c# N
        }
    $ Q% _) n& v0 [( q& S    @Override
    ! D- t  @8 w8 ]# v' D    public void initDatas() {
    + x* ~4 E4 j3 s, X0 n! q$ d* E3 O% M* t        startSDKRegistration();% L0 w8 b3 V5 O# G2 L' |( k
        }
    * r+ N4 v( c3 z# {/ j' w9 R    @Override3 G3 W+ U& O2 Y) n# J
        protected void requestData() {5 k% L  Y& C( Q" \  m$ R, T
            + Z5 l, I; A) G! [
        }
    # P( }8 n, ~! ~
    9 u, g2 Z" F" \. q2 Y  e9 Y    @Override& E( u" z2 S2 x( c
        protected void onResume() {, g7 U2 a- B" |. V
            super.onResume();
    7 E5 \! q9 u" G3 H    }" H. ~& C2 g- t; \* E
    9 K6 \& J5 X$ A' e# k2 W& u2 `
        private void isPermission() {( @8 p+ U% N7 E& O; t, I
            requestRunTimePermission(permissions, new IPermission() {0 F9 o7 r+ v. B8 h2 S) |
                @Override' n( E9 a$ Z2 w, u  R9 z2 G9 Q1 \% W
                public void onGranted() {, l- X$ Q- S9 o3 K
                }( H0 P1 U2 I! T+ Z1 @3 J
                @Override
    # [4 |( l) E. C( e# x- |6 y            public void onDenied(List deniedPermissions) {! L' i# y/ c1 @$ f
                }
    5 v& E" w* W( Y. \5 s0 |+ y6 m" p* h        });) J( u" l. l- `9 R; C! d4 @
        }5 G/ }" O; E! O* |- F" O" l$ X
        ^: ]! {: p' L
        //无人机首次注册4 [/ T$ C; ^0 e5 A; w
            private void startSDKRegistration() {
    7 q0 X2 @/ d, a+ e, y  p& j            if (isRegistrationInProgress.compareAndSet(false, true)) {
    * Q5 `3 m. Y2 M/ g4 h6 W                AsyncTask.execute(new Runnable() {
    + l; J" N+ [5 t6 H2 Q& V7 S0 l                    @Override
    ; \2 G0 M+ m) U1 }) n( `% j                    public void run() {# k3 f6 q7 e" B
    //                      showToasts("注册中,请等待...");
    & k6 A. N! s7 c+ J6 p" Z/ e( f' \                        DJISDKManager.getInstance().registerApp(getApplicationContext(), new DJISDKManager.SDKManagerCallback() {
    " z, _6 c  E5 N% y1 K6 ]                            @Override
    $ f( `. V& c% w$ j7 y, }# V                            public void onRegister(DJIError djiError) {
    $ x7 X2 D  |# T$ }1 V, \                                if (djiError == DJISDKError.REGISTRATION_SUCCESS) {
    5 X) E5 S) @  p; X                                    DJILog.e("App 注册", DJISDKError.REGISTRATION_SUCCESS.getDescription());- H0 V$ u! k! V* ?. O' X. }9 |( P1 o
                                        DJISDKManager.getInstance().startConnectionToProduct();# A5 e/ q* H7 J* V8 k( `  @
        //                                showToasts("注册成功");
    , Y% s  k1 i3 S                                    loginAccount();* E2 L0 x+ v9 b
                                    } else {/ e- [  a6 [2 R* c$ u
                                        showToasts("注册sdk失败,请检查网络是否可用");
    ; y0 ^' B% z* p6 m  M                                }
    ) {/ t% u, V& U+ j# ^                                Log.v(TAG, djiError.getDescription());
    ! b0 o6 U: f; ~4 F: _                            }4 o1 B& t  X3 i* M/ Y  h  J3 _
                                @Override% l* a5 b6 [$ W
                                public void onProductDisconnect() {
    * o1 t; [5 h5 v) t* L/ \) j                                Log.d(TAG, "产品断开连接");5 j4 a' h) Q; ^
        //                            showToasts("产品断开连接");
    4 {& F" Q/ t! v                            }
    - |; ^# n, X0 P5 F' y                            @Override
    & O: I5 C  ]. L                            public void onProductConnect(BaseProduct baseProduct) {
    8 U  `1 U% G! y3 B- a5 u- S& k                                Log.d(TAG, String.format("新产品连接:%s", baseProduct));- J' Q9 r: s0 l+ ?8 D+ S9 ^$ B
        //                            showToasts("产品连接");) _) ~% s4 l3 N
                                }; [+ ]2 J/ N4 d% Z1 d3 D
                                @Override
    ; u' w. w' k' E, ]; i                            public void onProductChanged(BaseProduct baseProduct) {
    , L) l6 Z! c2 ^& Z                            }
    ! g, d( R' T" e8 k' P( t                            @Override" \5 Y: J) {0 c( S' j2 \
                                public void onComponentChange(BaseProduct.ComponentKey componentKey, BaseComponent oldComponent,
    # `7 u* P2 V. v2 j                                                          BaseComponent newComponent) {
    ' t2 o+ v' h( M  t+ E                                if (newComponent != null) {
    # ~' b. x8 ]8 G, K% `                                    newComponent.setComponentListener(new BaseComponent.ComponentListener() {  e1 }. p$ F; B" B/ r
                                            @Override
      d+ g. N; f6 b. K! x, d; p% @2 c                                        public void onConnectivityChange(boolean isConnected) {9 S# h+ x) |( v3 I" y. U- K
                                                Log.d(TAG, "组件连接已更改: " + isConnected);
    + K2 H" h* k& g2 ~. g9 i! s                                        }
    5 ?) J: v, `9 a- p; y" O                                    });! j5 w5 P% M$ {8 Q) w. P
                                    }
    * l. `7 F2 R8 A: s( _1 s* q                                Log.d(TAG, String.format("改变设备Key:%s, " + "旧设备:%s, " + "新设备:%s",# a; A6 o* N4 Q0 Q! B) w( r
                                            componentKey, oldComponent, newComponent));$ ^# D8 S4 y! Y: d; A- M
                                }
    0 |# M  B2 `- i5 k# R/ }7 e3 X                            @Override- o; ]; D. U9 I3 E
                                public void onInitProcess(DJISDKInitEvent djisdkInitEvent, int i) {
    $ y6 k& m9 n5 v4 d6 ~                            }. ~- G3 s: v: }
                                @Override
    2 \7 k) T  H7 n/ t; L0 u                            public void onDatabaseDownloadProgress(long l, long l1) {- r8 y' \9 m8 ?4 O2 P- b
                                }
    5 k& j5 p" Z* k/ P- G                        });, q- R0 J6 n6 X0 U
                        }% A8 E) S/ b  v, }3 n# a  X  l
                    });" d5 J0 N, Q; v; H
                }; R0 m2 d7 T/ @  q3 Q
            }
    6 K" ]1 Z- [) H/ Q: o! p    protected BroadcastReceiver mReceiver = new BroadcastReceiver() {/ p1 c) N  z0 o/ _( Q( W8 R
            @Override% h  E0 z$ v/ Q' x6 }( |( B& F
            public void onReceive(Context context, Intent intent) {
    3 C( y( {2 I' b1 H) m- V! m% H            refreshSDKRelativeUI();" P" O9 b+ b# I# }- \& A2 J
            }1 O' q3 U/ }. u" K
        };
    . H& u2 }. U3 h% Z/ g; x) y    private void refreshSDKRelativeUI() {% l$ ?* x4 k2 t2 L  o  C; G
            BaseProduct mProduct = ReceiverApplication.getProductInstance();
    $ J3 j" z! k, }/ {        if (null != mProduct && mProduct.isConnected()) {# T- {  `: j$ z: y$ q; X" P, k4 f
                Log.v(TAG, "刷新SDK: True");  [! t- s( h0 T
                mButtonFlightTask.setEnabled(true);
    6 U) `1 \. e8 N) [! ^            mButtonSettingRoute.setEnabled(true);9 i& {/ W0 i5 q  D# Y/ U' h
                mButtonFileManagement.setEnabled(true);
    5 v0 [: ?# q$ z2 X        } else {1 R' u# R2 l! N, {* \! m
                Log.v(TAG, "刷新SDK: False");
    2 Z  G- R4 Q+ V( T" ~# D1 t3 m//            mButtonOpen.setEnabled(false);  ^9 ?0 U4 }. Y9 I6 j* o
    //            mButtonSettingRoute.setEnabled(false);
      d$ j! b$ M* j7 P5 J( t/ N. f//            mButtonFileManagement.setEnabled(false);
    ( d+ R/ h# `) m$ g//            startSDKRegistration();4 s% c- O/ M; b# X3 ]. G
            }* D* \. K7 s4 e( f1 }$ Z6 a7 X
        }- E5 f  |7 D$ Q/ B3 Q8 d! L
        protected long exitTime;   //记录第一次点击时的时间6 @5 J8 I( o6 z) q
        @Override
    9 [* s0 b" U% I- Z& [: w: ?; w    public boolean onKeyDown(int keyCode, KeyEvent event) {( A$ T: e) e* p- t6 P+ W  @
            if (keyCode == KeyEvent.KEYCODE_BACK
    0 A2 A8 U5 z( a. _                && event.getAction() == KeyEvent.ACTION_DOWN) {
    ; q& t3 o+ I* ^            if ((System.currentTimeMillis() - exitTime) > 2000) {0 F: @# G' Q: J/ R$ \" \! w5 j4 J
                    showToast("再按一次退出程序");- D! c/ O& K% P6 c, ~, @0 y
                    exitTime = System.currentTimeMillis();! a/ t2 {  M8 u! o! k
                } else {
    6 a2 s  t7 `- s9 @5 x$ H                RegistrationActivity.this.finish();1 g9 J9 A! g' Q: S1 P. S5 _  V! R' f
                    System.exit(0);& ~' `: b  S2 r% s& M
                }
    8 t" _. S0 r& c$ Y, p            return true;* c. \0 d2 M! ~5 J9 s
            }3 w6 f+ n9 f' s6 b: K
            return super.onKeyDown(keyCode, event);
    4 Y; l; B  G# @) ]- J" u3 n    }2 P) i. [8 t. @' v- W6 V, H  r

    % P# P+ v% l8 y2 B& y        private void loginAccount() {
    * \8 n: ~3 |" z: I8 f            UserAccountManager.getInstance().logIntoDJIUserAccount(this, new CommonCallbacks.CompletionCallbackWith[U]() {
    1 w4 O& V9 q5 d3 B1 R1 _                @Override
    - H1 t7 c$ g( `3 g! n  Q                public void onSuccess(UserAccountState userAccountState) {$ S2 o2 o% [3 B2 w! x( m2 q
                        runOnUiThread(new Runnable() {$ B, o+ t6 J8 \& x
                            @Override0 u. a$ u* e  j6 s
                            public void run() {
    9 N. M; K% s1 K) f1 [                            mButtonFlightTask.setEnabled(true);
    " }8 o' R6 E% T/ V                            mButtonSettingRoute.setEnabled(true);
    . K  ?* i8 t* w2 {8 @                            mButtonFileManagement.setEnabled(true);$ q+ V* |! G. d2 L+ |4 `
                            }' u6 H( E7 G5 x2 i- A3 k+ e
                        });: B: \1 P) o1 G& M% A0 B
                    }. X) }6 A! Y9 Q8 E
                    @Override9 T( }) I& L. p1 E" W
                    public void onFailure(DJIError djiError) {$ y) `8 r. X, c( x$ C
                    }) b& `7 c. j* @, ]1 ^
                });" Y. j# S% D1 `- w7 V9 t' a4 c
            }
    + e! i# k2 e2 {2 B0 Y7 ~7 Q% ?}9 Z2 A$ I7 k5 Z+ s/ s% p, w9 T
    上面的代码就要进行第一次注册登录了,当然你不需要自己去设计登录注册页面,大疆会调取自己的登录注册页面供你使用。
    9 f: o+ \7 @! X% T. a  ]

    hq4gpuho40364015971150.png

    hq4gpuho40364015971150.png

    7 ~: b) i6 u8 n5 r5 l安装提示注册登录即可。
    1 v/ J1 b# o  c( X上面的这些做完后,恭喜你!现在,您的移动应用程序和飞机可以在中国使用而没有任何问题。换句话说,您的应用程序现在可以看到飞机的视频流,并且飞行将不仅限于直径为100m和高度为30m的圆柱体区域。
    + o4 z2 A, e4 f1 t5 _+ r" z+ q3) ^! q# {8 Q9 v$ k
    飞行界面使用# |( `% p. s3 V  P- N  z5 A, i
    虽然说可以正常飞行了,但是飞行需要设计飞行界面。那么创建一下飞行界面的UI及逻辑处理文件。逻辑处理文件中包含了获取飞机的实时姿态信息,代码中有注释内容,描述的内容就不多说了。+ z0 V1 O) a2 L0 Q8 I- P

      @) Q" e2 `1 T# Y; y" u; w# U导入UX SDK依赖' e  q; l* D2 T, ^
    上一节有说过集成部分,其中内容有导入UxSDk 的操作,这里再顺便提一下。再build.gradle文件中加入implementation "com.dji:dji-uxsdk:4.16"依赖,等待安装即可。( E  j! b% a# [  G

    ( k2 C+ g. [4 \& D# {设计界面UI
    0 a% Q! o3 g! K. V创建MainActivity文件及activity_main.xml。
    & U& O' {( R% cRelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"& Y5 D/ O4 W7 G4 z  ^" k- G
        xmlns:tools="http://schemas.android.com/tools"
    ! I  n$ A) O# N' z% I- b    xmlns:custom="http://schemas.android.com/apk/res-auto"- t0 {4 [! q; h7 B  c) h
        android:layout_width="match_parent"" s1 W! d# ~0 I! z" @% ^8 w3 G+ Y
        android:layout_height="match_parent"
    % y) }6 H( U2 O. M* o+ i    android:background="@color/background_blue"* s" ^0 t; p  i1 q* O- h" `
        android:id="@+id/root_view"
    # x$ w! I  r. @4 Q    tools:context=".ui.MainActivity">1 k# d4 R# R, H7 R
        " h  P+ p2 _. q0 d0 L5 P0 v
        RelativeLayout
    # U1 H+ i# g2 p; W1 \6 Z4 q3 ?; r        android:id="@+id/fpv_container"
    7 m. S( T9 Z2 l2 b9 u  p        android:layout_width="match_parent") P% \! O+ N2 p: n$ J* |& P
            android:layout_height="match_parent">8 B* y1 K& t; P! j# ~
            dji.ux.widget.FPVWidget1 Y' Y5 [4 a8 L; `
                android:id="@+id/fpv_widget": Q/ }- E$ P9 d7 s1 [% G+ t) T
                android:layout_width="match_parent"
    $ I9 B2 H1 T; s% D            android:layout_height="match_parent"
    5 u  l: Q( {/ X* j0 g/ \            android:layout_centerInParent="true"
    ( q! O( w" j" v' E7 T            custom:sourceCameraNameVisibility="false" />/ r9 w+ Y$ w: A* a
        RelativeLayout>* s& f- l4 ?8 ?2 K/ x7 W
        dji.ux.widget.FPVOverlayWidget" i, v" G) g: X, z6 C
            android:id="@+id/fpv_overlay_widget"
    8 u: n, \6 F$ Q/ V0 D" |        android:layout_width="match_parent"% t' r! G2 L( r, d6 V. S3 ^8 m" y
            android:layout_height="match_parent"/>' Z4 B5 S9 I% [1 a
        RelativeLayout$ Y1 I+ j. i7 C$ M
            android:layout_width="match_parent"/ |  S+ _; G5 T' y! C
            android:layout_height="match_parent"
    $ Y6 r4 P* [- m3 A* I; I        android:layout_marginBottom="40dp"
    ! e5 Q+ F! e# _4 N        android:layout_toRightOf="@+id/TakeOffReturnPanel"+ M* x# n$ N- B$ K6 d
            android:layout_toLeftOf="@+id/CameraCapturePanel"  K6 V: L! u  A, Z
            android:layout_below="@+id/camera"$ Z9 H3 k; v* ]8 A4 i9 I7 {" \
            tools:ignore="RtlHardcoded">
    . H  q1 B! H! a. f% E        dji.ux.widget.RadarWidget
    0 D0 s8 ~7 T5 W4 T; m8 s            android:layout_width="wrap_content"+ X) u; h8 f% h1 g8 W6 q5 V
                android:layout_height="wrap_content"( |/ ~8 u  {& ~* }! Z. j7 H" _
                android:layout_centerInParent="true"/>- E+ Y6 n; ~( F+ l7 ^
        RelativeLayout>
    7 C" Q- [* i9 Q. _   
    $ W& T2 f& |# r    LinearLayout! j* }6 z. A) Q. K- b' o) h
            android:id="@+id/TakeOffReturnPanel"" V4 a! g2 Z6 Y
            android:layout_width="40dp"
    / _" h2 X+ b! n' X        android:layout_height="wrap_content"/ m' q9 a: p+ z1 l  G4 l) R' O: W! q/ i
            android:layout_marginLeft="12dp"5 ^9 v7 [0 C, T8 H4 x9 s
            android:layout_marginBottom="4dp"( {2 V% |: W. [% \- U8 ~" q; }% W
            android:layout_marginTop="50dp": `. `1 h- b5 j! J9 B( I
            android:orientation="vertical". \: ]% q8 _9 E( u# h( i' [  M
            android:gravity="center">: s- I! f0 b$ A
            ImageView
    ! P. A$ Q" u( {- {            android:id="@+id/img_show_back"
    ( @( X" K- M# b0 `! ~            android:layout_width="match_parent": D- h/ d- ?1 y+ M+ i3 J/ b
                android:layout_height="38dp"8 N0 Q. w) b8 E; m% ~1 r0 N2 S5 ~1 ~
                android:src="@mipmap/ic_back_36dp"
    * U% ^3 x. I0 w- A  ~            android:layout_marginBottom="10dp">ImageView>
    ) B+ ^. Z% u/ q        dji.ux.widget.TakeOffWidget
    , E  R# _- C# X* ^( y3 c6 Z# X+ H( a            android:layout_width="40dp"
    ; [8 d5 x) H* \& Y2 U/ o8 |0 a$ }" A            android:layout_height="40dp"0 `& A2 a! c3 M9 ]4 T/ f
                android:layout_marginBottom="5dp" />
    5 _& N! k+ v' j: M" `6 A' f5 w4 o        dji.ux.widget.ReturnHomeWidget
    # [) q' u6 X& }1 i$ T% B: y            android:layout_width="40dp") J$ f$ ~" U: b% w7 P
                android:layout_height="40dp"
    - d$ A: O: N4 M; K+ C3 }            android:layout_marginTop="5dp": |1 v- V0 q0 g) i' W
                android:layout_marginBottom="5dp"/>
    7 C& N3 @$ X1 j; a: |- {        ImageView' G7 Q& A, q& \& S( q! e; F
                android:id="@+id/img_live"
    ' _+ |- u% a# D8 K            android:layout_width="35dp"
    / R- M2 e# v5 ]0 W" R' \# d0 C3 ^            android:layout_height="35dp"% A9 S! x) [# d) P
                android:layout_marginTop="5dp"! r: @3 h" {) c! |
                android:layout_marginBottom="5dp"
    8 \! i9 e$ w' \- |            android:src="@mipmap/ic_live_write_36dp">ImageView>
    ( m1 {# p% V9 K% s    LinearLayout>
      g& |, O9 o' U2 D& ]. P& O8 V    FrameLayout% b) \' {: D2 T$ u
            android:layout_width="150dp"
    3 u! O5 {+ w" G+ y        android:layout_height="100dp"
    3 s0 H- B' H7 [$ j# A7 P5 u$ o        android:id="@+id/secondary_video_view"
    7 d; W9 b1 U$ P3 S/ \# c. `        android:layout_marginLeft="12dp"
    7 W, [6 v! P- {7 v' |) g        android:layout_marginBottom="7dp"
    8 b" h  Q! W4 a/ j* e% `        android:layout_marginTop="50dp"
    ' z4 N' {  L4 f5 H3 a        android:layout_alignParentLeft="true"8 f! E" L& k- I5 R7 g
            android:layout_below="@+id/TakeOffReturnPanel"# Y" \( a1 Z7 i3 x8 k
            android:background="@color/black">0 }- i$ u+ Q1 Y3 M
            dji.ux.widget.FPVWidget
    / c7 [) S  [- w* i            android:id="@+id/secondary_fpv_widget"& c- A1 H8 \+ x8 f' z
                android:layout_width="match_parent"+ b8 d& m- ?0 y' A
                android:layout_height="match_parent"
    - I6 K1 d0 |9 B: H            custom:sourceCameraNameVisibility="false"$ V1 E" O# J) b" m/ w9 p
                custom:videoSource="secondary"/>
    . T- R9 {' s' G; I+ a1 v; i- D5 @    FrameLayout>
    & L9 i' z, E; b    dji.ux.workflow.CompassCalibratingWorkFlow8 s( w0 k: x+ r( q" U
            android:layout_width="match_parent"& e3 t! c' _2 _/ _
            android:layout_height="match_parent"/>/ `% O% h  Z- a( m/ P& g8 x
        dji.ux.workflow.CameraSensorCleaningWorkFlow
    - S2 k! l4 \3 g0 S1 \% t        android:layout_width="match_parent"
    ( @+ d7 r4 n8 J0 v        android:layout_height="match_parent"/>
    " b4 A% x! ^* V& L    dji.ux.widget.RemainingFlightTimeWidget/ p2 ]: C5 G, M. @' \% G; [* v
            android:layout_alignParentTop="true"* C% c0 S, A& Z! Z
            android:layout_marginTop="18dp"
    ; G& J# I+ ^5 g7 Q        android:layout_width="match_parent"
    % [& t* F1 V- V& u        android:id="@+id/remaining_flight_time"
    0 O/ g  x% c: ]  O4 ~3 @2 v        android:background="@color/transparent"3 m3 s- j" E; Z+ ?7 a  A! M) @$ i
            android:layout_height="20dp"/>; p$ }( w) `0 _+ z
        LinearLayout
    4 i7 c. b) ~, S        android:id="@+id/camera"
    ( c  [8 T) H  e/ M3 `" }2 e) w5 A5 O        android:layout_alignParentRight="true"
    3 L3 n8 Y5 O8 h# h/ R        android:layout_width="wrap_content"
    " ^6 B1 [4 ~1 d- X3 U        android:layout_height="wrap_content"* ]0 u) }1 l( i. S+ k
            android:layout_below="@+id/signal"0 e; A& h# O0 }$ u# L7 r7 b
            android:layout_marginTop="15dp"$ }6 P' {+ R2 j6 y) D2 [* ?8 D
            android:background="@color/dark_gray"8 g3 z# l8 D: Y; A
            android:orientation="horizontal">" J4 \5 S, ^9 G$ O
            dji.ux.widget.config.CameraConfigISOAndEIWidget5 F; l2 C) @. I' b
                android:layout_width="50dp"# I- H7 e! l+ p- G& ]( }
                android:layout_height="25dp"/>
    & B. S7 E6 f* k3 i# c' P        dji.ux.widget.config.CameraConfigShutterWidget8 q3 B# |( n+ I1 V7 ]& b
                android:layout_width="50dp"& ]/ z+ p6 ~: B9 D( n5 E6 A7 {
                android:layout_height="25dp"/>) ~# d3 y5 c) Z/ n
            dji.ux.widget.config.CameraConfigApertureWidget) T! P8 V& `( ^3 ~
                android:layout_width="50dp"
    5 a* L, R* m2 F# ~8 j* w            android:layout_height="25dp"/>8 i% o( v; d6 t) [
            dji.ux.widget.config.CameraConfigEVWidget% K9 J; L( o# z" K( ^1 p
                android:layout_width="50dp"
    8 w6 d) y: m. H( W' C4 S# U            android:layout_height="25dp"/>
    9 c) A& F: j* T; E" Y- m. m3 }4 T        dji.ux.widget.config.CameraConfigWBWidget: O, ?# \- {: _& Z8 v
                android:layout_width="60dp"
    ( o% t$ T8 I* G3 J1 e* l            android:layout_height="25dp"/>
    & A5 ^" T' ~) [9 g. H: K        dji.ux.widget.config.CameraConfigStorageWidget* {6 k0 j0 J" M1 w+ C- H
                android:layout_width="108dp"2 q' {. w$ u; V; j. G
                android:layout_height="25dp"/>! h  ?* _1 N8 k! ?
            dji.ux.widget.config.CameraConfigSSDWidget0 l& `' {0 C* Q7 B
                android:layout_width="125dp"
    : E- c- }" @1 k8 v5 w9 u$ ]8 L! ]            android:layout_height="25dp"/>0 [( ~. A4 e3 G. f
        LinearLayout>- ^  ^3 a% L2 n' v: `. R
        LinearLayout; M* ]! ^6 H$ ]! T; q5 t. [
            android:id="@+id/camera2"6 A% V* d" ?# @* S; e- A
            android:layout_width="wrap_content"9 t8 p: S& D, D$ w4 o1 U4 f
            android:layout_height="wrap_content"
    ; x9 ~3 Z; S- i$ F. }  `& O$ P        android:layout_marginTop="5dp"! m. k4 A1 |; \5 s+ N
            android:layout_below="@id/camera"
    . N8 q/ v/ Z2 H9 Q' w# b' G        android:layout_toLeftOf="@+id/CameraCapturePanel"
    # b! R. C/ \6 N, t1 h% N' q        android:background="@color/dark_gray"
    ) w; i; n3 ^& J1 C$ ]; n/ w        android:orientation="horizontal">" m8 Z) w4 {2 z$ q
            dji.ux.widget.SpeakerWidget
    , u: R/ D, k6 Y- N0 |' C0 g            android:layout_width="35dp"( X1 k- c- g) `: p6 q6 A; s  {
                android:layout_height="35dp"/>7 t2 d) [) i% k  n* X# q
            dji.ux.widget.AutoExposureLockWidget4 H+ Y% S5 }0 n! o1 b
                android:layout_width="35dp"* Y1 @% F. e! k: O" v
                android:layout_height="35dp"/>
    : j0 p; ^! Y1 C% K1 y  {! _        dji.ux.widget.FocusModeWidget& C" f$ }6 j: \- O2 f% X
                android:layout_width="35dp"9 n* [. l" r. O' `: S  c
                android:layout_height="35dp"/>
    , u$ P  M, U  {/ j2 T5 P' }        dji.ux.widget.FocusExposureSwitchWidget& g1 y: W" Z  [+ k0 b
                android:layout_width="35dp"3 J0 `. Q: s1 m
                android:layout_height="35dp"/>' z, e$ u" `* e' m- c
            dji.ux.widget.BeaconWidget
    , P0 }+ p8 r' A            android:layout_width="35dp"
    : i7 l5 _/ a. O3 X4 t            android:layout_height="35dp"/>8 c( X, e! [4 |4 @1 e) ~* r  M
            dji.ux.widget.SpotlightWidget
    4 r% P% s8 Z' U1 O+ N+ g            android:layout_width="35dp"
    7 p1 L. c6 ^: i5 l            android:layout_height="35dp"/># P5 B2 l2 P  N2 J# z
            dji.ux.widget.AccessLockerWidget
    2 I! q2 H' r8 ]% q/ M( P            android:layout_width="35dp"
    / C/ s' C4 U: M& l) q) A; y            android:layout_height="35dp"/>
    7 ^! e! X8 W6 b% Y4 E    LinearLayout>8 z) S1 o: z; y) X
        dji.ux.widget.ManualFocusWidget
    ) X7 S7 A: h' L5 b! M+ l        android:layout_alignTop="@+id/camera2", i) l' E0 a& b! y/ s) Z' z
            android:layout_toLeftOf="@+id/camera2"
    & P- b6 u( s9 }7 E8 {- b% Z        android:layout_width="50dp"8 s7 M8 p  j' P+ O7 U
            android:layout_height="210dp"( k, F1 D5 z% S! r, \1 {$ b# |
            tools:ignore="RtlHardcoded"/>- K2 }8 x$ U# f+ I$ |9 {- \
        dji.ux.widget.MapWidget0 E/ s4 k0 j" v* C) ~: s  y
            android:id="@+id/map_widget"& G4 ~; _4 {5 \6 i
            android:layout_width="150dp"
    $ ?% H( B+ P0 t8 |1 H" k' h        android:layout_height="100dp"
    ) m4 a  w" X3 @  f. v& f' R        android:layout_marginRight="12dp"
    1 H- @$ p" ?3 k. ~        android:layout_marginBottom="12dp"
      P& U" B% J5 l  D        android:layout_alignParentRight="true"! x' D, _* }4 u2 n
            android:layout_alignParentBottom="true"/>" S$ ?" B% ^" q! ~$ q/ X8 k
       
    8 ?1 F! d" P: L    dji.ux.widget.controls.CameraControlsWidget5 p$ S6 K/ {7 B: K8 T9 |3 l. {
            android:id="@+id/CameraCapturePanel"; d% h' \( \7 F- d, B/ |8 y% m
            android:layout_alignParentRight="true"- _; h6 P  V! y; p
            android:layout_below="@id/camera"
    1 J" H4 {/ u, k5 W! ^4 }. s        android:layout_width="50dp"
    9 s  l$ Q3 n4 Y7 ?) f* K+ O8 m        android:layout_height="213dp"! ?( M4 Q8 l! u' S: G
            android:layout_marginTop="5dp"' ]: @8 d+ d9 {6 U9 L
            tools:ignore="RtlHardcoded"/>
    + P2 s4 Y& q( f+ i8 C; Y( r    3 x% V, a, `8 S
        LinearLayout
    $ S* ?7 Z4 ?& U9 P1 s        android:id="@+id/signal"
    ) y+ X- \! j9 B  I2 M        android:layout_width="match_parent"
    2 x! v3 |4 h1 N* [1 I: i+ v        android:layout_height="25dp"
    / z' u$ Q9 K$ e7 s: v        android:background="@color/dark_gray"
    ) I" @) S' j7 u0 V/ w        android:orientation="horizontal">
    5 r5 `' U6 n( E% Q/ F9 @/ ]- a# Q' M4 |        dji.ux.widget.PreFlightStatusWidget, S7 J+ `- i( T* @! K( @& k
                android:layout_width="180dp"1 P0 m3 ^1 Z" X$ N+ U, A
                android:layout_height="25dp"/>
    2 r' X' K+ Y/ H4 K4 v# @        dji.ux.widget.FlightModeWidget
    6 U0 n" Q/ R6 E9 h            android:layout_width="103dp"9 H4 ?! w: \. H6 ~* y3 W
                android:layout_height="22dp"/>
    " S% u' L. I6 T2 \( _        dji.ux.widget.GPSSignalWidget, k$ O+ D, T5 @& q- M+ C+ X
                android:layout_width="44dp"
    - a9 c, \% K0 n' `3 P/ h            android:layout_height="22dp"/>* ?  Z3 T9 l. }4 H% M
            dji.ux.widget.VisionWidget+ x& M- `5 V  V; D
                android:layout_width="22dp"; R' v7 R: r+ J- Z
                android:layout_height="22dp"/>+ f& m! l" Z. }! U2 K) q$ [7 z
            dji.ux.widget.RemoteControlSignalWidget$ _5 Q# F& o1 h1 k# J
                android:layout_width="38dp"  T3 a. q% z9 A
                android:layout_height="22dp"/>
    ! k9 _( J. I3 J        dji.ux.widget.VideoSignalWidget
    0 k4 c9 }. ~/ N( E3 P! R            android:layout_width="38dp"
    6 p) P, [, y) J5 J! p            android:layout_height="22dp"/>
    2 s( G3 f' g+ q: |' k8 F) V* |        dji.ux.widget.WiFiSignalWidget7 w2 Z" L/ D" ~: w* N# E
                android:layout_width="32dp"
    . ?# i# S5 K+ e/ A, o; B3 ?            android:layout_height="25dp"/>) X! t+ A0 M; J" r7 a* A
            dji.ux.widget.BatteryWidget
    + d$ s' @  T8 B! i( B+ M( G2 w            android:layout_width="96dp"/ G8 o  r. m6 e( t6 y
                android:layout_height="22dp"
    / Q# q) O# f+ A/ ~7 Y% ?9 P) `            custom:excludeView="singleVoltage"/>/ e( D0 Z; x' L
            dji.ux.widget.ConnectionWidget
    0 L6 f5 K9 |# `# y0 u: i- ^# C            android:layout_marginTop="3dp", c5 L3 A2 c' r" s: @
                android:layout_width="18dp"
    - f1 |+ S4 j8 s/ g& ^- V4 {# Z            android:layout_height="18dp"/>( \' ?7 u! I$ w) r4 y' U4 l8 c
        LinearLayout># z4 L( B# I; T% Y) p6 o3 {3 n
        LinearLayout
      `9 u. @, q' j7 |- Q        android:id="@+id/dashboard_widget"7 W1 Q8 F, n6 q: f( l
            android:layout_width="match_parent"0 ~! Z' ?- ?8 @, x2 A5 p* W
            android:layout_height="wrap_content"
    ) i& v5 P- Z) ^# T+ `. e# U) h        android:layout_alignParentBottom="true"
    % u: n7 J0 H& w0 S7 G/ i; o" _        android:orientation="horizontal"2 e3 ^; {" [2 i5 f
            android:padding="12dp">  V# D4 h8 O+ g. j
            dji.ux.widget.dashboard.DashboardWidget
    8 P$ h) A: W' [# ~            android:id="@+id/Compass"% m+ ^" O0 Q% b3 U
                android:layout_width="405dp"
      [( I; L7 n. U            android:layout_height="91dp"5 f7 E( A) h$ `+ T
                android:layout_marginRight="12dp"
    ) t) e) a0 B; w4 R* J            tools:ignore="RtlHardcoded" />
    . H: {2 l/ R8 I. j1 @. d8 |6 \- g    LinearLayout>) @: d2 I5 b7 W" p  P

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

    noljwkfd5j364015971250.jpg

    noljwkfd5j364015971250.jpg
    ; I' x) e3 @% D- t- y' Y
    上面的工作完成后就可以在无人且宽阔的地方进行无人机飞行了。) Y3 e3 g2 ~! r  t. ~
    4
    7 @, y7 l; K6 d多媒体资源的操作$ \6 H& @) p6 Q( r4 a( Q
    多媒体文件操作,主要为多媒体文件的获取、查看、删除、下载的操作- f; {+ s6 A+ l: U( c# L# c
    同样创建多媒体功能文件FileManagementActivity及activity_file_management.xml' I# g; _9 Y/ S1 }; L: U
    activity_file_management.xml
    ( H/ k4 R, k( [( H4 DLinearLayout xmlns:android="http://schemas.android.com/apk/res/android"/ [; w# U8 ]# ^
        xmlns:tools="http://schemas.android.com/tools"( V6 R3 j( u- z  g3 P8 x% |
        android:layout_width="match_parent"
    : w' |! s* |8 s# e1 Y1 D' c3 w    android:layout_height="match_parent"" P/ _$ n" \2 C: F7 P. a
        xmlns:custom="http://schemas.android.com/apk/res-auto"- z% g  p$ m$ P  B5 R
        tools:context=".ui.FileManagementActivity"- z" O7 q$ d2 u9 E' d$ ?, B- C% q0 k% }
        android:orientation="vertical"
    . l6 w2 z+ r& C' M. r+ g. |1 {    android:background="@drawable/shape_corner_eight">9 V- g% q2 G! t! d; H. N: b; N. A
        include layout="@layout/activity_toolbar": A" a0 s5 S$ M% N& g- ]$ y, |1 s( {
            android:id="@+id/layout_file">include>% ]7 ~- `3 o8 e2 r& P! X7 T
        LinearLayout
    , d4 S+ r' q+ i! S        android:layout_width="match_parent"
    1 V( u+ q8 i* A        android:layout_height="match_parent"$ t/ M0 ]0 ^4 S% P
            android:orientation="horizontal">6 y" X0 x' g  _9 T
            LinearLayout9 S8 O' O3 w$ T# j
                android:layout_width="250dp"
    . J( ^' H% g1 b4 P; h/ H            android:layout_height="match_parent"8 w- Y4 k# c* h6 W6 r
                android:orientation="vertical"& l& w* x& }% Z# T  C- d
                android:layout_marginLeft="15dp"0 X: F! c/ [! E# L# I
                android:layout_marginRight="15dp">
    2 p: Q8 l) z% c            RadioGroup5 @2 u  b# ~0 I% T7 F
                    android:id="@+id/rg_file_management"
    0 d, e) D6 z: `                android:layout_width="match_parent"
    1 a, s: V$ O) R; r  L                android:layout_height="40dp"4 B9 z( m, W. ^
                    android:orientation="horizontal"
    3 i+ L3 z3 Z2 }& o" P0 O( X7 F! T                android:background="#2B3141"" {! d5 ?. [" [  y& J$ j3 l2 X
                    android:gravity="center">. m# T6 z+ A; n+ F6 i! h: s
                    RadioButton
    ) e; T% A  X/ e0 ?                    android:id="@+id/rb_file_all"
    5 ^2 c2 j# L) |8 r2 q                    android:layout_width="0dp"  ~0 L. B; o0 m6 P1 P
                        android:layout_height="match_parent"8 k: V7 o8 p! F
                        android:layout_weight="1"9 O9 q% X) n2 c" O6 I- X7 ~
                        android:button="@null"
    ' f6 c. z+ x) t/ L- Q                    android:checked="true"
    2 o: Q: i; W, ^. X! Q9 E                    android:gravity="center"
    2 V7 K- b# o* E                    android:text="全部"
    ) D# B  z' J- ]; V: I7 h. C  U( D                    android:textColor="@drawable/nav_item_color_selector"
    : Y. \) D2 n# g: s                    android:textSize="18sp"9 K7 m3 I' D' \$ N1 ], h# g
                        tools:ignore="TouchTargetSizeCheck">RadioButton>+ Z' W4 ^: B- g% A1 ?) T* |. C  ?& Q
                    RadioButton
    9 A& x! o5 m+ w3 @9 P                    android:id="@+id/rb_file_photo"0 [5 z7 `! |  B" m" U1 G
                        android:layout_width="0dp"
    6 Y2 A! b- F0 j% B- m5 J+ M                    android:layout_height="match_parent"
    4 W- i( n+ `6 P6 J8 ]3 E                    android:layout_weight="1"' f) B7 }; z7 W5 ]
                        android:button="@null"
    + Y) j& l! S$ V6 y5 Y+ l$ C; J                    android:gravity="center"
    , {" o4 z6 z0 r8 O. @                    android:text="照片"
    & b# O2 ^6 u- ~  g/ U& b* c                    android:textColor="@drawable/nav_item_color_selector"
    . t3 Q% N, H" \. E+ I% w9 K                    android:textSize="18sp"- L0 A8 n2 Z5 r( T) {0 g
                        tools:ignore="TouchTargetSizeCheck">RadioButton>
    / l- k/ z2 a3 w6 c                RadioButton7 o% c2 r; \1 K1 j% I2 k5 L+ i, i6 p
                        android:id="@+id/rb_file_video"
    3 L5 K! w, J( v+ _( d. B& X                    android:layout_width="0dp"# A- ^# l- l" k3 L
                        android:layout_height="match_parent"
    , k, G! N6 n; P. {) e                    android:layout_weight="1"5 O% O  e% Z( N9 s" D1 j: z# |
                        android:button="@null"; m; N( F* t* [+ V/ Z! T/ T
                        android:gravity="center", |! b0 O8 Z- t' Z
                        android:text="视频"8 p" T+ {0 k* d. J% a
                        android:textColor="@drawable/nav_item_color_selector"6 a% r' D; l, w0 H4 J: c  @
                        android:textSize="18sp". H+ b& [$ o  J6 k* @, \7 p
                        tools:ignore="TouchTargetSizeCheck">RadioButton>, s2 U  H) T6 c% B; p. f
                RadioGroup>4 Y+ V( ]1 _$ ^4 I) h
                androidx.recyclerview.widget.RecyclerView1 {- T1 [9 Y  z2 G/ A: }+ e
                    android:id="@+id/rv_file_management"
    : a( U9 w5 T4 q. _                android:layout_width="match_parent"
    : `7 [4 l/ M0 M" y) [! @                android:layout_height="0dp"
    / O' C- p- ]2 x: e8 E8 X                android:layout_weight="1"- |9 ]" }( z# ?' S3 M5 i. G  D: ^
                    android:layout_marginTop="10dp">androidx.recyclerview.widget.RecyclerView>
    ' ^; n* Q! `; S! n3 m' w3 E- [        LinearLayout>! T3 p9 z: l7 l7 w
            RelativeLayout# Y# y7 W3 z- F9 T& {+ O$ r
                android:layout_width="0dp"6 E1 p! Z( {, n% x, p2 e
                android:layout_weight="2"- Q5 @; ^/ o, G2 s  z4 M0 {
                android:layout_height="match_parent">
    - U$ k% |) \+ L5 I4 `* Z            RelativeLayout
    1 m7 l1 z( v: @5 T7 a9 E                android:layout_width="match_parent"0 X4 x0 W" u( L. J
                    android:layout_height="match_parent">5 p& W5 b0 ?, C' k- m- u; z- `& |
                    dji.ux.widget.FPVWidget
    3 q6 X$ t1 B6 _9 T                    android:id="@+id/FPVWidget"
    1 g* r" x6 ?: _3 e' y1 w; o                    android:layout_width="match_parent"
      d: Z1 {# [4 \; ?! u                    android:layout_height="match_parent"
    * y7 A( j# x" v2 [' f1 D5 g                    android:layout_centerInParent="true"
    ) u2 A# W1 N) q0 M& C                    custom:sourceCameraNameVisibility="false" />
    & X" `( z: i) @5 c7 V( W            RelativeLayout>
    * @$ D; [4 N$ o" x* k* W" M- c            ImageView
    2 Z: U+ o, F6 Y+ W                android:id="@+id/img_show". U* |4 m1 |# W  s
                    android:layout_width="match_parent", D3 B7 j+ E( A3 A
                    android:layout_height="match_parent"
    & K) o* z( `! w1 V* S2 A- z4 I                android:scaleType="fitXY"
    - K  w5 W) v/ [/ [( L4 m$ ?0 A                android:visibility="invisible">ImageView>
    2 o  r+ c7 H* S  U& j6 c            LinearLayout
    4 @$ W" [. e" ~+ D                android:id="@+id/ll_video_btn"
    , z& w6 S  r$ i                android:layout_width="match_parent"
    , A& ~+ ~* j  C6 P' |                android:layout_height="50dp"
    4 l! n% W! Q8 J& @+ @! J                android:orientation="horizontal"
    # A- o6 Z' A1 A                android:gravity="center"
    * n1 _0 W7 \/ B1 u+ V3 B# j. @                android:layout_marginBottom="15dp"
    " W- u; L6 A4 @( ^7 a' G1 _                android:layout_alignParentBottom="true"
    ' y" X7 B+ ]% G1 J                android:visibility="gone">
    9 j/ W9 D& n8 E+ }/ O$ X2 [: n                ImageView
    % {6 O2 o7 |2 U8 V% }+ B5 B                    android:id="@+id/img_video_pause"
    1 `& K8 U+ U, ~5 K                    android:layout_width="35dp"
    ( C* j% f1 J& M1 Q                    android:layout_height="35dp"
    $ C& Z5 @$ N) j                    android:src="@drawable/background_stop_selector">ImageView>
      m0 M7 ^: j2 g4 K                ImageView
    & |! {! a* @+ \; E6 [+ n5 O                    android:id="@+id/img_video_play"
    + c. e# W8 T* K; i5 [& r! v                    android:layout_width="45dp"6 V+ t$ I0 r4 t5 n- z  F, ^9 u
                        android:layout_height="45dp"
      P+ `8 ~! Q' t" w. q) A% Z                    android:layout_marginLeft="20dp"& F6 z7 Y" Z$ N7 y2 r8 y0 E3 k
                        android:src="@drawable/background_palyer_selector">ImageView>( ?* l! D9 {, `# b
                    ImageView
    + p6 m8 Z) |  Z$ K+ U) S' R; E                    android:id="@+id/img_video_stop"' D, R7 b  K, t+ n7 P
                        android:layout_width="35dp"
    9 e# }4 y- f& i3 }                    android:layout_height="35dp"
    + U- J  C6 A/ ]9 X7 \                    android:layout_marginLeft="20dp") t' {7 i+ E- ^
                        android:src="@mipmap/ic_reset_36dp">ImageView>; i% K/ [; H4 ~' v4 U9 h2 K
                LinearLayout>
    * W/ @1 L" u' \0 R. |        RelativeLayout>
    2 z2 x4 ^$ j" h    LinearLayout>
    9 @6 N. R) p& n, z! D0 RLinearLayout>
    4 o4 W( C# L6 cFileManagementActivity
    & Z% M+ {! z. w4 n7 a# k@Layout(R.layout.activity_file_management)
    / ]$ G- O0 g  X0 u: d, spublic class FileManagementActivity extends BaseActivity implements View.OnClickListener {
      m9 J8 G' m* K+ f1 C& u/ x- Y    private static final String TAG = FileManagementActivity.class.getName();% |( e& J) I( d+ M" O+ z9 M
        @BindView(R.id.layout_file)+ F2 ?) h5 |6 R! z& S" \1 u
        View mViewLayoutToolbar;
    " [% G  q9 V( A! |4 Y% Y+ z    @BindView(R.id.tv_toolbar_title)* z6 k# Z$ e9 x8 m6 y, o
        TextView mTextViewToolbarTitle;5 `& }! ]( R4 e) a! p
        @BindView(R.id.ll_file)
    2 U7 b% s8 o- e6 M$ G3 P! P    LinearLayout mLinearLayout;
    . S* v: y: [4 [, e* X! O7 n8 {    @BindView(R.id.rg_file_management)( r; @) S, m/ K/ _
        RadioGroup mRadioGroup;% m0 z) K; o( E1 W1 f1 M0 D" [! S
        @BindView(R.id.rv_file_management)) w) \( L6 \, N0 s& M1 L
        RecyclerView mRecyclerView;
    , A, P  V* j9 v9 F$ Y* D9 K    @BindView(R.id.img_show)
    0 i0 x2 J- N2 r0 x; X/ W) Y( ]8 F    ImageView mImageView;
    * ]: P5 [6 i+ t5 i0 F! ?    @BindView(R.id.ll_video_btn)
    * W- [$ M6 c8 ]$ V6 H    LinearLayout mLinearLayoutVideo;( c) f3 a0 I. n1 v7 }
        @BindView(R.id.img_video_play)
      Y0 U5 W& _# R8 p    ImageView mImageViewVideoPlay;9 G  O6 B' ~* p; U& ~
        @BindView(R.id.img_video_pause)
    5 h& X" @* ]) @! o! W7 h* e    ImageView mImageViewVideoPause;
    - K4 j* p% w' m    private FileListAdapter mListAdapter;
    ( a6 G7 ~+ Y! C% h4 Z    private List List = new ArrayList();! J' i/ x$ v7 J7 i; d; |
        private List mediaFileList = new ArrayList();7 w& [( U  Z! o& r, H7 b3 U
        private MediaManager mMediaManager;1 @8 U' H' z8 S
        private MediaManager.FileListState currentFileListState = MediaManager.FileListState.UNKNOWN;7 Y3 z" K6 n  b. X
        private MediaManager.VideoPlaybackState state;
    - ~: p9 f6 q  A5 O    private ProgressDialog mLoadingDialog;
    , X; G2 B: L' b6 b    private ProgressDialog mDownloadDialog;4 @; B. E* y: y
        private FetchMediaTaskScheduler scheduler;
    5 r4 W: t2 k' r5 l+ T; V    private int lastClickViewIndex = -1;
    + Y: @0 A( ~* A" s! ~6 M    private int currentProgress = -1;% \) G% m: B4 y( r
        private String SavePath = "";% e+ O' I* B2 @, g) d
        private View lastClickView;
    3 o# m; Q5 x" W% C. R2 R1 W    private boolean isResume = false;
    0 x4 i( l( g" M$ m+ _    private SFTPUtils sftp;
    ; }/ ?6 G  F( [/ W( N, L3 `    private SettingsDefinitions.StorageLocation storageLocation;
    ) ^) t9 M" `# S' Y2 w6 c% m7 \    @Override# b8 c. _3 `6 b$ L/ J' d
        public void initViews() {
    , ]! D( n+ K" {, P        mLinearLayout.setVisibility(View.VISIBLE);
    ' Y' c* j* Q# r4 c* [% n        mTextViewToolbarTitle.setText("文件管理");
    8 ]6 }! z) z. p, f5 `        mImageViewVideoPlay.setEnabled(true);, D  B: `7 e$ \) G1 e
            mImageViewVideoPause.setEnabled(false);
    # X9 R- o, L, m7 I* @* r        mRadioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {8 D: X2 ^) T  b: t
                @Override- C5 Z: M  s8 P9 m
                public void onCheckedChanged(RadioGroup group, int checkedId) {& ~! ^! P2 x/ ]$ ^9 D
                    List.clear();
    7 ^$ ]) g* q4 J; z# g+ Q- B                mediaFileList.clear();
    ! g4 B- R# [/ j+ H, b& e                switch (checkedId) {) D, D/ _- O+ F- i3 ?
                        case R.id.rb_file_all:
    7 |, X: |6 y' L4 q# ]7 n                        getFileList(0);
    & Q& i; z! L; Y2 }; q                        mListAdapter.notifyDataSetChanged();
    8 m. c) k' e, P* \                        break;
    2 _% ~3 k. P) ^# F1 S* }  Q0 N                    case R.id.rb_file_photo:$ A5 S4 f% t( s, u6 W1 p& H, `: H# ]3 l
                            getFileList(1);# S1 z( ?$ u0 T1 d! {9 ^* R
                            mListAdapter.notifyDataSetChanged();
    / o& X$ K& Y% z+ m                        break;
    % |+ a% O9 D# o' D. e                    case R.id.rb_file_video:
    7 U/ V- m1 A, `% W* T                        getFileList(2);+ @4 m: s2 N' x: N$ T
                            mListAdapter.notifyDataSetChanged();
    , z" T: \& B7 J# ?' F/ B$ J9 i                        break;' U( i3 ^& a0 T9 z# N
                    }
    ' |+ [$ S9 s- B' E            }
    8 R& ?) r# ]; m: k; F        });1 w- v2 X6 w! a+ P
            LinearLayoutManager layoutManager = new LinearLayoutManager(FileManagementActivity.this, RecyclerView.VERTICAL, false);
    7 s6 B" T( C2 @        mRecyclerView.setLayoutManager(layoutManager);
    % T! Q& K. a2 a        //Init FileListAdapter
    # e- S1 y4 ?0 I- r2 ^+ w        mListAdapter = new FileListAdapter();# Y( X" q# g" k, V
            mRecyclerView.setAdapter(mListAdapter);1 u6 Y' W5 ~% h* z# ]
            //Init Loading Dialog  B0 {9 m" W; ~, p
            mLoadingDialog = new ProgressDialog(FileManagementActivity.this);& h. A$ p/ M, v# L! X
            mLoadingDialog.setMessage("请等待...");0 `& g/ o# y9 x
            mLoadingDialog.setCanceledOnTouchOutside(false);" X9 Y) m- o8 D2 e
            mLoadingDialog.setCancelable(false);' s# G4 J5 t( b% t) |
            //Init Download Dialog: X, g' H! I4 H2 K* \4 s
            mDownloadDialog = new ProgressDialog(FileManagementActivity.this);% O3 R( L' D! u; T1 x) w3 h
            mDownloadDialog.setTitle("下载中...");
    6 |6 g/ ^7 `" n: i8 l        mDownloadDialog.setIcon(android.R.drawable.ic_dialog_info);
      [/ E, u- D3 l6 F6 _/ H        mDownloadDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
    9 `! u" w/ D4 t  @" I7 A        mDownloadDialog.setCanceledOnTouchOutside(false);3 o5 v7 [$ }, E* b3 n. }
            mDownloadDialog.setCancelable(true);: q+ [- X7 X+ t5 i( B+ [
            mDownloadDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
    % Y+ _& L9 C9 T+ n; c            @Override' ]5 O/ [, D; y( G/ @1 ~' f
                public void onCancel(DialogInterface dialog) {
    5 N- |$ @1 w- n# {+ Y                if (mMediaManager != null) {/ B) E, T7 J+ s
                        mMediaManager.exitMediaDownloading();- ]9 Z$ v5 O0 e9 F& U
                    }5 R, s8 [" X3 w$ Y9 |) X
                }* i) P5 A1 D- A3 A
            });
    0 e" {. f$ R" \% F& Y        sftp = new SFTPUtils("49.4.79.249","uav","uavHHch@YREC.cn");; G* Z- i9 h- u& h
            ReceiverApplication.getAircraftInstance().getCamera().setStorageStateCallBack(new StorageState.Callback() {
    " A# z" J# ^8 v5 z. E7 a/ q            @Override
    9 _: W7 \; i$ q& X9 y4 r            public void onUpdate(@NonNull @NotNull StorageState storageState) {
    3 n7 Z, _, f4 n/ P* P+ j                if(storageState.isInserted()) {1 O% E! l$ e! u" C% ]1 x
                        storageLocation = SettingsDefinitions.StorageLocation.SDCARD;3 L4 O7 l* U: f' g1 j: U
                        ReceiverApplication.getAircraftInstance().getCamera().setStorageLocation(SettingsDefinitions.StorageLocation.SDCARD, new CommonCallbacks.CompletionCallback() {
    : F& F' s- A) X9 t! V* u! {- Q; E: i                        @Override
    + G. y  u6 D' X                        public void onResult(DJIError djiError) {6 f1 f- |6 c0 ]7 T% U$ ~$ u
                            }9 d  f) z; D  j' B6 Z% v
                        });" T) Z, c1 v" V: {2 p2 H
                    } else {  `1 c; E' `! R5 G, `- T8 k
                        storageLocation = SettingsDefinitions.StorageLocation.INTERNAL_STORAGE;* P" a9 ]; z! `3 F, H
                        ReceiverApplication.getAircraftInstance().getCamera().setStorageLocation(SettingsDefinitions.StorageLocation.INTERNAL_STORAGE, new CommonCallbacks.CompletionCallback() {
    2 B6 E% [/ l5 `                        @Override
    & ^, R% u5 I+ f. V2 _1 N                        public void onResult(DJIError djiError) {: z- {# B- {5 ^  k# w7 S
                            }4 q9 ^" }2 [+ v4 J. z, K$ @3 k
                        });! ], z) V+ S* r
                    }
    , _- T& f3 H1 F; [, f            }" `6 M. Z- o5 _. G) q% S
            });( W6 m2 V- G9 K7 m6 R3 `7 X8 ^+ L, |
        }( x  a6 w2 t- b# L. k
        @Override! O9 D4 J: |9 d9 N# K) F
        public void initDatas() {
    ( e& F! Q. a1 c7 U; W' R- j    }
    4 v. y+ N* ~, B0 g& T( D6 h4 M/ ~    @Override/ _8 ^6 J: i7 O
        protected void requestData() {# O  N( V  s; [' D
        }4 i9 w* s9 j  m+ ?- y
        @Override
    - m' S+ L9 c5 ~* O# i$ a9 j9 V2 v    public void onComplete(String url, String jsonStr) {
    2 E% x7 s7 T, Q0 F4 D# A        super.onComplete(url, jsonStr);
    2 N9 n$ L& h4 O: v        switch (url){3 M. g, J& ~0 J( r. @! O6 x6 Z
                case POST_VIDEO_INFO:
    ! l: w. k: r# |1 ]                break;. s  W/ O( G+ j( k4 c3 O
                default:+ M( p1 l! e- ^% o
                    getVideoJson(jsonStr);* E  l9 D0 Z+ s
                    break;
    0 ]% j$ b" R) H& ~4 c+ V        }* \4 d7 I  g/ ], C
        }$ s/ x! _1 _' J! I
        private void getVideoJson(String jsonStr) {
    ; N; s# Y" D. ^- N9 L        VideoModule module = GsonUtil.GsonToBean(jsonStr,VideoModule.class);1 k0 E$ I8 B' Z- r( }
            if (module.getCode() == 200 && module.getRows().size() == 1){
    2 [9 R- p4 F( r5 n. S( Z2 G            runOnUiThread(new Runnable() {
    9 ^9 C; w0 N/ V                @Override; ?2 r2 k8 I# j9 o/ W# _
                    public void run() {( T% s2 h: n3 w( {- f: O& B
                        UpdateFileModule fileModule = new UpdateFileModule(module.getRows().get(0).getId(),"/mnt/uavFtpFolder/"+module.getRows().get(0).getFileName());
    + n  }- ^4 w! M) N+ b- v  t                    http.getHttp(POST_VIDEO_INFO,"PUT",GsonUtil.GsonString(fileModule));
    : I! G8 a7 J( j) ]. ]# y                }- {9 r, @2 `! d4 }$ F
                });7 ~; A. w' G0 J) y
            }
    ; n& C5 @/ f- s, G9 ~    }
    . E3 ~/ h: A2 K    @Override1 ~$ u+ I& G5 X
        protected void onResume() {% v  c6 B9 U  o" Y: `$ C2 q& ~6 V
            super.onResume();
    & x+ g( \' g/ {' b        initMediaManager();* X; t9 Q+ v' U4 G, g8 M
        }6 [) e4 q/ [  d& a2 R
        @Override  \/ f% S- m5 O: l
        protected void onPause() {' A! ~0 q2 V( L  u2 v+ h
            super.onPause();
    ! z6 N. g  [" T6 a9 J7 T    }
    2 b2 a' {# @' i9 H9 ?  J6 v    @Override" H9 }' P/ S$ s6 y, c$ H$ h$ t
        protected void onStop() {- O. |' Z; e8 a/ n
            super.onStop();3 A3 f0 S* j" e- L3 d; x2 m* b
        }+ u, V6 R$ n1 C: W1 G) C

    ! ]. Z& Q& h4 W) v; F    @Override
    ( f/ |7 a& z" H. H4 ?    protected void onDestroy() {/ _/ u& @% t( l
            lastClickView = null;) |/ C( K, Y- ?. u: f
            if (mMediaManager != null) {1 {7 _9 |( _+ P8 A1 t
                mMediaManager.stop(null);
    1 K6 N( Q! E3 }6 @2 ~            mMediaManager.removeFileListStateCallback(this.updateFileListStateListener);
    7 p0 G' i2 S; I9 [9 J% l            mMediaManager.exitMediaDownloading();
    . S- b$ W+ V* ^# C8 g! N: q8 P4 ]            if (scheduler != null) {0 y% y1 u- c8 N
                    scheduler.removeAllTasks();9 w/ x# t# r$ S2 P7 v
                }
    ' f7 C1 T3 k2 C; ]2 L        }$ s% B; k, X; U' m. Y; d
            if (isMavicAir2() || isM300()) {
    " i- h5 n% a& a2 P& M3 Z            if (ReceiverApplication.getCameraInstance() != null) {
    ' W0 ^, J& w4 r                ReceiverApplication.getCameraInstance().exitPlayback(djiError -> {" S0 c  a; }- |. l# Y
                        if (djiError != null) {
    : {% k4 r# ?' e) x0 q                        ReceiverApplication.getCameraInstance().setFlatMode(SettingsDefinitions.FlatCameraMode.PHOTO_SINGLE, djiError1 -> {
    # q: J" b/ Q) d  s+ {- T                            if (djiError1 != null) {
    : P+ Z4 Y, f/ O+ x$ u% ]; T7 [2 @                                showToasts("设置单张拍照模式失败. " + djiError1.getDescription());6 t" F1 H/ z+ G: ?
                                }. H' |7 E% v; m8 d" ?) Z: K
                            });
    ) x8 O( s3 R) N/ k                    }; A5 ^- E/ O) y. |3 C
                    });
    : A6 H' r) f9 T3 I8 C9 C            } else {7 o. x' _' H& W) q' P' a
                    ReceiverApplication.getCameraInstance().setMode(SettingsDefinitions.CameraMode.SHOOT_PHOTO, djiError -> {4 P( @: x: F) I. P! ^
                        if (djiError != null) {
    1 N, m5 }9 X6 s* L1 `7 l                        showToasts("设置拍照模式失败. " + djiError.getDescription());
    $ f& x( @+ U/ E6 \# i* ?6 X6 I                    }" E9 M) B; Q/ s$ F
                    });2 c7 A! h7 K6 {; N& Q
                }7 u6 J8 g+ F# ?& K* _- e
            }
      Q4 J. l+ c0 h  F* n        if (mediaFileList != null) {! V6 ]9 G5 y/ D+ G
                //            List.clear();7 O# z& q* T0 ]$ ?. z8 ~  v
                mediaFileList.clear();
    , ~5 ~( h0 q+ m% {. J* X7 ?        }
    9 N9 P8 ], N# \: R; {8 W3 p! a- t* w        super.onDestroy();: t8 g% Q$ w- M7 Q/ E
        }
    & G/ l& Q3 H- S6 ^- b2 W    private void showProgressDialogs() {% V( j' A* E$ j! e( U% B0 l
            runOnUiThread(new Runnable() {
    ! t- ?4 K, A( f8 J/ d' B            public void run() {) Q: b' C2 _( V" q: O6 g) Q7 K: Y* ^
                    if (mLoadingDialog != null) {5 Y7 I" w6 g9 j0 T0 M6 e
                        mLoadingDialog.show();
    # Q2 u, V) b0 T5 M4 Y4 m                }
      P6 m( z6 a1 U            }
    " x" B& H! k: O) {% a        });; ~' P; m5 P( O8 F6 l" o9 ~
        }  _6 I- W9 V/ u. W& Z
        private void hideProgressDialog() {
    " G3 f) n# z6 w        runOnUiThread(new Runnable() {, [# e, k, |6 q$ [
                public void run() {
    6 \, a0 I5 u1 m2 ~                if (null != mLoadingDialog && mLoadingDialog.isShowing()) {) m, {& P6 m" S+ |
                        mLoadingDialog.dismiss();
    ' \, q  r: N/ D- F1 L                }' [4 j  L1 v4 t( P# W, c
                }2 a& Q! q( j8 z9 ~* ~) X6 L- U
            });
    # ]8 P3 K, _( t* O4 y3 K' w8 y    }
    # s$ g7 W; u1 r8 ~" t/ u  Q    private void ShowDownloadProgressDialog() {
    ' y: \- _* t6 a        if (mDownloadDialog != null) {/ I% x2 j& b) s8 K  C9 S2 w
                runOnUiThread(new Runnable() {" [9 l* V8 l+ ~0 ?4 |3 {+ r
                    public void run() {
      j( |0 G# ^+ X                    mDownloadDialog.incrementProgressBy(-mDownloadDialog.getProgress());
    / t" `7 z" R* x; C$ S0 |                    mDownloadDialog.show();
    3 K" V, K8 S" d! Q7 f4 Y, H& b- O                }3 H- F* R6 k4 E9 U9 Z: j
                });, k6 B6 g# `& o: z- G7 X2 B, o
            }& q6 k' @0 i; H* D5 G" ^' _
        }( D" K# h' g4 z2 ?( v9 @  d3 H! o
        private void HideDownloadProgressDialog() {
    & `3 w" J9 y. w* R3 s        if (null != mDownloadDialog && mDownloadDialog.isShowing()) {
    8 c: r  S9 n8 Q5 o# g, H            runOnUiThread(new Runnable() {
    3 O) M( ~( }* l7 R& q# L# g                public void run() {" \6 X' W+ k* \8 ]* M
                        mDownloadDialog.dismiss();
    $ X; H* @: l4 e# l. ?, t                }/ {+ K0 U" x5 [7 U. t4 E, l; [3 I
                });
    ( E9 o+ u4 F. q& `        }- N1 y7 h$ c7 p+ d! b) `2 g
        }
    3 S& i& c' E* L  }& E3 a    private void initMediaManager() {
    + Q* z% ^. ?: d$ Y( S" p8 a, u        if (ReceiverApplication.getProductInstance() == null) {
    $ c; j$ a) X/ j0 W            mediaFileList.clear();' F+ W$ M2 F, V
                mListAdapter.notifyDataSetChanged();
      E3 I. Q7 W% {+ e1 @2 r            DJILog.e(TAG, "设备已断开");
    ' s/ @- R5 Z1 n) h& _8 E1 z            return;1 V. V& ?' T5 k8 @- k
            } else {
    + [3 a6 B, m5 D/ S            if (null != ReceiverApplication.getCameraInstance() && ReceiverApplication.getCameraInstance().isMediaDownloadModeSupported()) {  M% [' q* q$ O
                    mMediaManager = ReceiverApplication.getCameraInstance().getMediaManager();7 U% A+ n/ Y- w0 ^! K
                    if (null != mMediaManager) {
    6 f$ L3 V3 r+ {* U+ X3 A                    mMediaManager.addUpdateFileListStateListener(this.updateFileListStateListener);9 s2 O6 Y: j5 x. N9 C+ @
                        mMediaManager.addMediaUpdatedVideoPlaybackStateListener(new MediaManager.VideoPlaybackStateListener() {, e. s9 M" M# Z3 ]/ I6 x& Q8 W
                            @Override
    ! @$ z$ J+ P  F! U5 I2 _: I# C                        public void onUpdate(MediaManager.VideoPlaybackState videoPlaybackState) {
    / j* v: m1 U3 p! S2 y! j                            state = videoPlaybackState;- E3 C8 ?4 I* ?& O: M+ K8 i
                                if (videoPlaybackState.getPlaybackStatus() == MediaFile.VideoPlaybackStatus.STOPPED){" s9 \4 N9 t1 q
                                    runOnUiThread(new Runnable() {
    & f: r# r. H) D& H                                    @Override
    % j6 w! @! K0 r. j, M: s9 c                                    public void run() {7 G& ?7 W5 E/ H4 Z" H# ~
    //                                        mImageViewVideoPlay.setEnabled(true);
    $ [" X! I1 f: Y8 q* g5 H0 @//                                        mImageViewVideoPause.setEnabled(false);
    8 n5 X3 S1 E! M, l  v% _: k                                    }  R% m6 k3 ]4 z: T! {9 ?% i
                                    });
    0 \2 U; _* T! s9 f4 R* Y                            }, I# T4 J& U$ n( v+ K( u
                            }5 |5 u7 l) H1 i/ s
                        });9 D+ B, H, A4 Z' l3 l
                        if (isMavicAir2() || isM300()) {
    9 q9 S$ v4 [( W2 S  f                        ReceiverApplication.getCameraInstance().enterPlayback(djiError -> {; q% y- T$ m4 U  y0 ?3 s- {5 w& o
                                if (djiError == null) {+ T$ e; e6 b) x5 w% I& b$ U0 m! H
                                    DJILog.e(TAG, "设置cameraMode成功");/ l: R+ k/ n1 W7 E
                                    showProgressDialogs();
    6 U. D( J/ e! f- D5 F9 ?; g                                getFileList(0);
    ! r9 }, ^  K2 ]- [: H8 z                            } else {3 S8 X( r5 j% Y" j
                                    showToasts("设置cameraMode失败");3 x% Q$ n# o7 N% V
                                }
    ) s7 e1 h  b; M: X; U, i7 ~2 i                        });1 o( }# t1 G7 s( D/ K0 i6 a; I
                        } else {
    9 x( h# c3 t/ i9 h+ `* i                        ReceiverApplication.getCameraInstance().setMode(SettingsDefinitions.CameraMode.MEDIA_DOWNLOAD, error -> {+ ?# Q1 }* {# F1 b: _; N
                                if (error == null) {
    " c3 ?' L, {2 }, }: k4 u                                DJILog.e(TAG, "设置cameraMode成功");
    & F- p/ y- E1 B. x9 K# \4 i, O# ~                                showProgressDialogs();4 A. z, m4 B: O& w
                                    getFileList(0);* k9 C+ \7 U2 ~: T3 L- o
                                } else {
    : b6 \) `0 P/ m" a4 h7 u                                showToasts("设置cameraMode失败");
    3 B9 P4 \  \% |. P% A0 J! I( y3 P: D                            }  y+ h; @0 Y8 Y- I) Q+ ?
                            });
    6 T$ R1 ?- @& x3 H. p: \% I0 T7 ^                    }
    ! _8 [* }9 e) p" l% L0 j% \9 d                    if (mMediaManager.isVideoPlaybackSupported()) {/ |) \( {9 W) {# K. F1 E
                            DJILog.e(TAG, "摄像头支持视频播放!");' u0 O1 t9 ^8 k& T+ [
                        } else {& T% m, f3 l% v) I
                            showToasts("摄像头不支持视频播放!");
    : e( ]) w5 H6 _, G3 I6 u/ e                    }
    " n  v3 H. [" P! }- x0 C  g6 d" |                    scheduler = mMediaManager.getScheduler();/ B! h$ z- \) a" x5 c! X1 ]
                    }
    % g% `; O: u- q, b; L( F            } else if (null != ReceiverApplication.getCameraInstance()
    9 _9 k& W! ~  D3 o                    && !ReceiverApplication.getCameraInstance().isMediaDownloadModeSupported()) {
    & ]6 V: P; u0 S                showToasts("不支持媒体下载模式");% I3 D/ X" }* J5 Q% s
                }0 i( h7 n9 {9 ~: H
            }
    $ }2 y! C- q; G/ I; I" z        return;6 {7 E' b/ {) z% O; }6 Q  b9 K
        }4 ]6 }. P* h& |" q  x& F
        private void getFileList(int index) {
    9 A2 n' P( D" A5 h* y" H5 j        mMediaManager = ReceiverApplication.getCameraInstance().getMediaManager();
    + Z3 v' r* g' R3 t. ]; u* z        if (mMediaManager != null) {
    4 W& }' g* G2 i4 g+ I' f            if ((currentFileListState == MediaManager.FileListState.SYNCING) || (currentFileListState == MediaManager.FileListState.DELETING)) {
    1 T2 T/ w1 a( E: B+ V                DJILog.e(TAG, "媒体管理器正忙.");! k& W# p$ f) f4 `. b
                } else {$ u0 ?( _! X$ L+ V5 W
                    mMediaManager.refreshFileListOfStorageLocation(storageLocation, djiError -> {+ O, j9 V9 a# {
    //                mMediaManager.refreshFileListOfStorageLocation(SettingsDefinitions.StorageLocation.SDCARD, djiError -> {
    % I( t6 t) i& V$ W% s* {) H                    if (null == djiError) {% V8 j' H+ m% C' T, _
                            hideProgressDialog();
    8 j- F. w! M8 T# ^                        //Reset data: M+ P3 X# U) F. L
                            if (currentFileListState != MediaManager.FileListState.INCOMPLETE) {
    # o9 |# T. j9 K8 V. z. c5 w                            List.clear();- A- Z: X/ c, @4 }6 L
                                mediaFileList.clear();
    9 o+ l. o9 @! |, z9 q                            lastClickViewIndex = -1;( I  [6 I6 Y1 B; u1 J. |- ?8 y
                            }
    ) s" s/ G, P" ~  M# b//                        List = mMediaManager.getSDCardFileListSnapshot();! w# `8 @) h2 P
    //                        List = mMediaManager.getInternalStorageFileListSnapshot();7 h7 a; C6 W& [3 O  _6 g
                            if (storageLocation == SettingsDefinitions.StorageLocation.SDCARD) {- b/ C3 I8 L+ U/ D
                                List = mMediaManager.getSDCardFileListSnapshot();
    ( ~! C0 o, o2 s: S3 w. v- P: b5 @9 v                        } else {4 Z  A" e- [7 K1 \" I* _4 O/ A
                                List = mMediaManager.getInternalStorageFileListSnapshot();7 C+ w4 u4 u% c3 k7 Z9 L
                            }
    7 F' [( k- S, b- X1 j8 u                        switch (index) {" u& A* t! `/ U- @  C5 A
                                case 0:- N1 L" z) S( c9 e2 {
                                    for (int i = 0; i break;: p9 y. F% u2 {/ s- U
                                case 1:3 z& L# K2 Z  d" y. ]- h" X- i; I
                                    for (int i = 0; i if (List.get(i).getMediaType() == MediaFile.MediaType.JPEG) {& s6 d0 ?, T$ m2 L1 ^9 U* h1 l
                                            mediaFileList.add(List.get(i));( o: E; l" p- y( k! e6 n/ }9 N
                                            MyLog.d("图片名称:"+List.get(i).getFileName());
    1 V* D7 N( ^8 N& N+ g/ u                                    }
    $ J, c( @# x+ g, r" }0 y( y                                }
    0 X  j, ]8 _, y. l                                break;
    * a6 P1 C- U# [/ h* G                            case 2:
    6 g7 M1 d" j  C                                for (int i = 0; i if ((List.get(i).getMediaType() == MediaFile.MediaType.MOV) || (List.get(i).getMediaType() == MediaFile.MediaType.MP4)) {
    * J! k/ k- \5 o6 N6 ?7 `                                        mediaFileList.add(List.get(i));
    7 `/ T! `: @" c5 z; k  ?                                        MyLog.d("视频名称:"+List.get(i).getFileName());
    4 J0 A  _- g% V9 U& Q0 \% t9 q$ @4 k& ~                                    }5 ^* c! f  H. r( R/ }
                                    }! T$ q+ U. f' {5 F6 w
                                    break;/ k9 N) b9 c8 V) m3 m
                            }
    7 y. _4 f% T& e- y2 F% s- A8 s                        if (mediaFileList != null) {
    7 E" o- V9 X% W0 Z                            Collections.sort(mediaFileList, (lhs, rhs) -> {
    ' f6 }3 s! J2 g% X3 l0 _9 E# M                                if (lhs.getTimeCreated() return 1;
    ! g) v1 \) _. [4 M                                } else if (lhs.getTimeCreated() > rhs.getTimeCreated()) {/ e# T; I; p8 W" L0 j
                                        return -1;
    / B( h0 h1 Y, _6 [                                }
    2 ^: Y% k9 c$ v" b" }1 F, U" `                                return 0;
    - o% F9 L; r4 T7 V0 l2 h* T3 O- G$ b' C                            });8 H" l7 O: k" b, n. }6 Q
                            }) \0 i* R+ B  Q0 z- N) J% _
                            scheduler.resume(error -> {
    / \4 \8 l, r5 D" o7 d6 }: z  Z6 j                            if (error == null) {2 L5 F* p+ D) U& L
                                    getThumbnails();
    - K' b5 r2 |5 S8 u                            }' f+ _$ x/ @- }& N3 e" C, _! ^
                            });% n9 f- n/ p8 q2 J' x( U
                        } else {* r# ?1 L! r: T
                            hideProgressDialog();
      g8 L* R+ J+ {' P                        showToasts("获取媒体文件列表失败:" + djiError.getDescription());6 E3 B6 v* {+ C& I% M7 a2 h
                        }
    / P& x2 Q" P) T0 M                });
    9 E. n( L# u; o- ]. W1 e* z& V            }
    " L) l* n& S# U+ S/ y        }% x9 t$ j5 D; O/ V- h: r8 j
        }
    . R: W$ {: ?9 S( G( ]* ?( H. L    private void getThumbnails() {! F* b+ H" H4 `4 R
            if (mediaFileList.size() 0) {  R/ y/ u; @- U  i3 P, f/ ~
                showToasts("没有用于下载缩略图的文件信息");
    . H2 z% s0 B% o+ }1 Y5 j- [- V3 h            return;
    3 d' O  s/ i. j        }
    * `& ]4 f4 p+ X4 n" i        for (int i = 0; i private FetchMediaTask.Callback taskCallback = new FetchMediaTask.Callback() {: `+ N9 h# n' l/ _
            @Override5 M/ o( y. ~; @8 [' u& X' Z
            public void onUpdate(MediaFile file, FetchMediaTaskContent option, DJIError error) {
      I% Q# b# j+ O- `$ Y4 l3 m            if (null == error) {8 V- Q& j: ^( c2 K; N
                    if (option == FetchMediaTaskContent.PREVIEW) {+ @/ V  V/ x# \- j. [. I
                        runOnUiThread(new Runnable() {
    & {  F8 ^; p) e' [, V0 L- R                        public void run() {
    5 K: ]" c( E8 p                            mListAdapter.notifyDataSetChanged();4 Q, p3 J0 d. D
                            }
    3 @0 S3 P: i* [% t                    });
    ) M2 N! O3 N9 y4 I& g                }1 [, W8 b* P! q6 X2 X
                    if (option == FetchMediaTaskContent.THUMBNAIL) {
    3 F  b1 r& y% ?; L! \7 ?& o                    runOnUiThread(new Runnable() {
    4 x- @  D* e& U                        public void run() {5 W  ^/ k% C# q% `& P: x
                                mListAdapter.notifyDataSetChanged();8 B. |4 j0 \. c" R% G2 Y
                            }% u# h3 W+ \& m  I9 v
                        });1 c$ h- ]* c8 M0 p: J
                    }
    ; E: T  k! X: E/ Z            } else {
      d; v0 i& {! y) V2 \2 c                DJILog.e(TAG, "获取媒体任务失败" + error.getDescription());' N, m0 _% q( q! f3 T5 _$ k4 P
                }
    - O$ |2 z6 t/ `5 z: Q+ Y$ }        }
      s1 f9 j8 R" v7 D4 j3 a  F, X# P    };* {% L% n5 P5 c1 E% M+ T7 _
        private void getThumbnailByIndex(final int index) {
    ; ]1 b% [8 b% r: G+ Y8 \        FetchMediaTask task = new FetchMediaTask(mediaFileList.get(index), FetchMediaTaskContent.THUMBNAIL, taskCallback);5 {6 Y$ A8 m) C8 c* G9 `
            scheduler.moveTaskToEnd(task);
    7 Q; f) C/ }4 I    }
    , h9 e6 x' o- @+ y    class ItemHolder extends RecyclerView.ViewHolder {
    ) ]$ y' n: I8 z& ]$ {1 h; a5 \- E        ImageView thumbnail_img;
    " a- n- t+ N' ^& e7 y9 w' v: K4 I        TextView file_name;
    . H8 z+ ^4 d( g: l+ k8 f* q        TextView file_type;& z" D9 o+ b! H; T" f+ L/ Y
            TextView file_size;; c5 g1 Q. F* x  o; F  v# X2 z
            TextView file_time;/ Z4 E6 N" t% B
            public ItemHolder(View itemView) {4 n- _+ L0 s. l5 R7 `, ^
                super(itemView);- h4 a" h$ q  y$ x% D: O! m' I! h
                this.thumbnail_img = (ImageView) itemView.findViewById(R.id.filethumbnail);8 z. Z& _8 i; p8 g: a% K
                this.file_name = (TextView) itemView.findViewById(R.id.filename);
    3 `4 t- g; @" Y: `            this.file_type = (TextView) itemView.findViewById(R.id.filetype);9 u9 U4 h) f; f+ z& ]
                this.file_size = (TextView) itemView.findViewById(R.id.fileSize);
    + Y" M% u! A; a+ P- R! r& f& J& x            this.file_time = (TextView) itemView.findViewById(R.id.filetime);
    6 e1 W$ {% S1 v+ U        }
    $ k3 R7 j! `/ ?9 `+ Y& @) S    }
    / b. h3 B0 a7 X3 z  c$ c    private class FileListAdapter extends RecyclerView.AdapterItemHolder> {
    5 o5 N. m! X! s        @Override
    * H4 e; v* r6 c2 p& ^; d8 s; `& W        public int getItemcount() {  S8 T5 {9 C2 I$ k4 F8 k
                if (mediaFileList != null) {" _' f9 ^# x6 N+ F1 x
                    return mediaFileList.size();
    + O8 x7 J: g3 o# y$ z: w( k& l            }# a' g; P! j9 Z$ I" F
                return 0;3 l- K/ }% j9 H) Y
            }0 D6 w3 h+ T8 C  i) A
            @Override/ T* U& a" T9 M7 f  b, P  c( [  [
            public ItemHolder onCreateViewHolder(ViewGroup parent, int viewType) {3 g2 U7 d4 N% L5 T  I* }2 U
                View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.media_info_item, parent, false);
    - q- h: ^, E9 F( g6 U$ h. B            return new ItemHolder(view);1 Q( y/ V+ v( r
            }# T9 y+ w0 o2 u5 A. q9 p
            @Override
    ) F8 Q$ w$ `! H0 }        public void onBindViewHolder(ItemHolder mItemHolder, final int index) {
    8 z3 X' K7 w  q' Y& G* m4 z            final MediaFile mediaFile = mediaFileList.get(index);. U* Y: y( o. ~' w, I
                if (mediaFile != null) {+ f2 V7 @5 @0 C7 I: Z
                    if (mediaFile.getMediaType() != MediaFile.MediaType.MOV && mediaFile.getMediaType() != MediaFile.MediaType.MP4) {
    * O" z5 z2 j( |8 q                    mItemHolder.file_time.setVisibility(View.GONE);
    1 N  ~- d8 l- b1 `' o0 m: T                } else {8 O+ X2 u1 z5 p! U  F0 M
                        mItemHolder.file_time.setVisibility(View.VISIBLE);+ @$ N! y+ v, d) X' n, n. l
                        mItemHolder.file_time.setText(mediaFile.getDurationInSeconds() + " s");
    3 a8 y$ J8 f2 c, A                }
    0 W( ~$ [+ l% H* r  L                mItemHolder.file_name.setText(mediaFile.getFileName());
    ' S: ?& w4 Y2 B% E) W- m: }& _8 N" i                mItemHolder.file_type.setText(mediaFile.getMediaType().name());
    - y+ W9 g- w' b! o% W+ e                mItemHolder.file_size.setText(String.format("%.2f", (double) (mediaFile.getFileSize() / 1048576d)) + " MB");& {3 L7 [: ?3 J# B  q; p8 R
                    mItemHolder.thumbnail_img.setImageBitmap(mediaFile.getThumbnail());4 S% s: r. f. g+ X2 Y' k4 T
                    mItemHolder.thumbnail_img.setTag(mediaFile);
    : |8 h# X  }+ _( h/ {% @                mItemHolder.itemView.setTag(index);6 u8 g  n. U, |; m! B
                    if (lastClickViewIndex == index) {' m0 D! v- M& @1 \0 B
                        mItemHolder.itemView.setSelected(true);: V! p" ~9 M- S+ \& r
                    } else {9 j$ i; U. I9 l6 C
                        mItemHolder.itemView.setSelected(false);
    7 _0 O) e7 n; g8 v6 c4 T7 N: y! P                }0 q' Y$ j9 E4 w. j% L2 a6 d$ O
                    mItemHolder.itemView.setOnClickListener(itemViewOnClickListener);
    2 v7 l  Z5 M: `            }4 s2 R0 W1 B, e5 l
            }
    3 ?9 q4 _' z; ^& a5 H    }
    1 x2 b1 \1 z' v0 P9 {/ r! S    private View.OnClickListener itemViewOnClickListener = new View.OnClickListener() {
    4 K$ x1 c! h" E+ J        @Override
    * R9 A  i# n4 G8 @        public void onClick(View v) {+ B1 `) M8 p. T
                lastClickViewIndex = (int) (v.getTag());
    - a: o2 _3 ~% K/ _+ u. v2 k7 ?            if (lastClickView != null && lastClickView != v) {
    7 \# C/ {( ~* q7 C. b                lastClickView.setSelected(false);' [# L6 v* W; \9 |6 ^6 C/ \
                }7 ]. s. c: v( a% ~4 A0 c
                v.setSelected(true);0 R- F5 z" t7 q! o  P
                lastClickView = v;
    . Q8 ]% u2 \1 p8 B# Z            MediaFile selectedMedia = mediaFileList.get(lastClickViewIndex);
    ! ^$ l: ^( o1 t" c            if (selectedMedia != null && mMediaManager != null) {) [9 }% E0 ?% k- c5 t
                    addMediaTask(selectedMedia);
    % g# @6 u( z$ Y. T            }
    5 c2 M# x4 t* N& t6 \' @        }
    . ]  V# K0 L2 F4 F! y' A8 r    };
    - o! M6 k" m5 s    private void addMediaTask(final MediaFile mediaFile) {
    # }6 S% S* l5 [; ~8 U! r. Z9 R( I        final FetchMediaTaskScheduler scheduler = mMediaManager.getScheduler();) v, Z7 ?# R0 p4 p) t5 v
            final FetchMediaTask task =
    / s; K+ m; N) {0 g+ U7 {                new FetchMediaTask(mediaFile, FetchMediaTaskContent.PREVIEW, new FetchMediaTask.Callback() {
    & i/ t0 n( G4 C# z+ a* Z4 {+ f& T                    @Override% h9 K& Q# o1 W* t! m+ @3 B
                        public void onUpdate(final MediaFile mediaFile, FetchMediaTaskContent fetchMediaTaskContent, DJIError error) {
    * J7 d0 k3 [3 ]8 n                        if (null == error) {
    ! n& W, D4 j1 J% y0 Q9 z, F                            if (mediaFile.getPreview() != null) {
    * }, k1 {5 Z2 i: Z4 s2 l( d                                runOnUiThread(new Runnable() {
    , N' Y( z( h  P7 N                                    @Override$ m! j" Y3 }, k9 E' J% E5 T
                                        public void run() {
    & P1 t+ F/ _  n6 b) W                                        final Bitmap previewBitmap = mediaFile.getPreview();) g7 U. Y5 _4 ?& p
                                            mImageView.setVisibility(View.VISIBLE);
    ) j* u6 Z3 k8 h3 E$ o4 w$ a% `                                        mImageView.setImageBitmap(previewBitmap);  e% G: y% h0 n6 {* e8 s
                                            if (mediaFile.getMediaType() == MediaFile.MediaType.MP4){4 x; G' K$ e; U& n
                                                mLinearLayoutVideo.setVisibility(View.VISIBLE);
    # `% V5 {- Q" x* s6 D( a                                        }else {2 ?4 R# A6 `0 U0 q5 T4 e
                                                mLinearLayoutVideo.setVisibility(View.GONE);' `) @6 _" K3 `( T5 N
                                            }
    - `$ w' r/ O; s5 _5 G5 M' s                                    }. {; A( p; {* g8 g( {  z
                                    });! c0 q( k: G0 @
                                } else {
    ) G/ Y! Q5 `2 d% {, e# C9 B0 i                                showToasts("没有图像bitmap!");
    9 A6 X, M, G1 Y7 r/ E                            }
    3 O6 k( `/ p2 o* k1 {                        } else {! F/ U% B1 O: m8 l: P& E0 A
                                showToasts("查找图像内容失败: " + error.getDescription());+ X* P3 ~5 B# ]
                            }5 ^" B! Y% A: t) Z4 J
                        }
    6 |  p0 R) D+ E% d7 r                });
    $ |0 \) F: A) J" `5 D        scheduler.resume(error -> {
    . R& D2 S4 E: N; E# G            if (error == null) {
    5 V6 S( {! z/ U+ Y                scheduler.moveTaskToNext(task);
    4 q) d2 w5 h% a            } else {) ?+ c4 C: K3 N* v
                    showToasts("恢复计划程序失败: " + error.getDescription());# W; h% f7 c7 v; n& s  L
                }
      X& K' \, C2 [$ C  W( |6 s$ }        });0 ]4 Z3 `: {2 H& X: g/ Q1 ]
        }0 p1 j5 o, j6 @8 J* M" ]
        //Listeners
    - R8 |. s, a$ G; u; G    private MediaManager.FileListStateListener updateFileListStateListener = state -> currentFileListState = state;
    0 Y% y. a# Y; D
    6 z6 k! T+ B$ m- q8 y5 E+ ^    private void deleteFileByIndex(final int index) {
    ' X3 `2 S. Q( n( S( [3 ^. q  B        ArrayList fileToDelete = new ArrayList();
    - o; @' `; v  ]- M- T1 c. ?7 W        if (mediaFileList.size() > index) {
    ( ^: ^5 ?/ C; t9 k  R2 Q9 b; T7 q            fileToDelete.add(mediaFileList.get(index));  ~: o0 f! t4 [, G- d9 l
                mMediaManager.deleteFiles(fileToDelete, new CommonCallbacks.CompletionCallbackWithTwoParam, DJICameraError>() {
    7 {) n1 l" A5 w  ]+ Y1 A) Q                @Override
    4 U( ?6 V  W0 \0 L; y                public void onSuccess(List x, DJICameraError y) {2 S! O2 ]: a2 C" k
                        DJILog.e(TAG, "Delete file success");
    6 _0 B; W- X0 ]                    runOnUiThread(new Runnable() {1 l; I6 G$ b& J
                            public void run() {3 e& B; l/ O6 o) `. d/ m/ D
                                mediaFileList.remove(index);
    ; e) ~- W( `4 ~$ u                            //Reset select view! b8 W1 ~3 s$ y  E- @. Z5 u6 _- u
                                lastClickViewIndex = -1;* h) Z# _9 ^; D4 m. j7 x- U
                                lastClickView = null;; ~: U" H9 D( g1 M% ^% F7 x6 i
                                //Update recyclerView& l4 a: @4 g3 f5 K# ]
                                mListAdapter.notifyDataSetChanged();! x9 A- J9 h0 B9 c3 m
                            }
    6 |7 K6 Y6 _% A: m! s                    });, d; b* t5 ?) e- t5 z/ y
                    }) t3 J9 G8 K; P' D
                    @Override
    & R/ y0 ^' m9 S                public void onFailure(DJIError error) {  O+ j9 G8 J$ Z: w* l
                        showToasts("删除失败");
    $ O) V0 G1 c" I$ r# U3 l                }
    " g% f" A& d- v  h( E$ G3 U6 M            });
    4 r% l% v# S. o9 p- ^- J        }8 v% s! z; {3 N( S( m) M/ P
        }9 Y; j' _# r# N+ V9 C
        private void downloadFileByIndex(final int index) {
    - _. [+ g7 o- E# m9 X5 g0 ^  y        if ((mediaFileList.get(index).getMediaType() == MediaFile.MediaType.PANORAMA)9 r" R% T9 u+ w3 ?' p
                    || (mediaFileList.get(index).getMediaType() == MediaFile.MediaType.SHALLOW_FOCUS)) {$ s. [& Y$ K2 {& n  E
                return;0 g1 o4 {4 N/ t
            }& u. L$ p$ g1 i6 S" q: B& x& j
            if ((mediaFileList.get(index).getMediaType() == MediaFile.MediaType.MOV) || (mediaFileList.get(index).getMediaType() == MediaFile.MediaType.MP4)) {" N. s9 |. W! t# k6 ]0 F
                SavePath = MyStatic.FLY_FILE_VIDEO;
    / Y, ?/ o! |6 Z! D; I7 \2 ]        } else if (mediaFileList.get(index).getMediaType() == MediaFile.MediaType.JPEG) {
    + k8 i; f. p! T! w2 }% u/ f* x            SavePath = MyStatic.FLY_FILE_PHOTO;
    $ d7 A6 x8 P5 G$ Q        }2 d, i' b; @. j9 P- G3 T7 f# n2 @
            File destDir = new File(FileUtil.checkDirPath(SavePath));
    - Y' B7 y# S0 H3 W1 q7 q" }% ]. p( z        mediaFileList.get(index).fetchFileData(destDir,null, new DownloadListener() {
    ( L) U8 O, E1 s            @Override
    ) ]+ N( j# J" a9 j. E# N1 S$ K            public void onFailure(DJIError error) {
    $ W9 D! b3 w. W* v9 l; Z! t                HideDownloadProgressDialog();
    , ~; u( A# c9 K6 H8 Y) s1 W! H                showToasts("下载失败" + error.getDescription());# l  |. ?' [; @3 {6 S& t. |. V
                    currentProgress = -1;
    / z  S, I( w/ o$ Z4 l3 h8 F- }            }5 q# K5 Q$ M. A$ B! g/ a5 g
                @Override
    ( n& l& c# i9 k% L            public void onProgress(long total, long current) {
    3 w6 h* U# f7 k            }7 @( \! V6 t: ^1 e/ t
                @Override
    4 Y% Z8 G: Z6 a2 B            public void onRateUpdate(long total, long current, long persize) {+ c) F. n1 G- C4 E
                    int tmpProgress = (int) (1.0 * current / total * 100);- L5 i; k" m6 P" R  ?
                    if (tmpProgress != currentProgress) {1 e& U+ w! |+ U. s, A! \6 \
                        mDownloadDialog.setProgress(tmpProgress);6 v# z) P7 J; R5 \
                        currentProgress = tmpProgress;' K9 I  m' q6 G' N
                    }& `$ R. ?: \. P
                }
    6 N! ~$ Z- x3 ]6 k7 L6 X7 V; ]# s            @Override
    4 v( @8 r% w1 @$ T" ?0 W            public void onRealtimeDataUpdate(byte[] bytes, long l, boolean b) {
    % ?$ Z! i1 P8 O            }4 {' c9 w. z: R. t( l
                @Override
    # q. g) u( Y0 G6 p3 H1 X4 e            public void onStart() {: X- c( b4 K, y- I
                    currentProgress = -1;
    4 W4 x: O" i) Z0 r: Z% ~                ShowDownloadProgressDialog();7 ^/ k# W# ]  I8 \  D7 |
                }/ _/ o0 y/ l8 ?! s9 ~; X& i$ @
                @Override
    - s! S* `+ k( D5 V9 n8 J& u& l            public void onSuccess(String filePath) {6 y% c4 F, C! M1 X2 j! _
                    HideDownloadProgressDialog();
    ( p2 u! v8 h" G" g9 {4 A& J4 @                showToasts("下载成功" + ":" + filePath);
    $ A# t/ o) I# Z1 @$ L* P8 k! Y                currentProgress = -1;2 l3 F( u/ |; N3 @
                }
    . h+ Y9 Q. V% x. w        });* f. ?- M5 A+ y/ I
    //        mediaFileList.get(index).fetchFileByteData(0, new DownloadListener() {
    5 u% [+ D+ {+ F0 A* f- g//            @Override4 q( N/ d, X( _: @. ?
    //            public void onStart() {
    7 t. m! l5 l& }* w  J0 A//                currentProgress = -1;
    2 I* F9 u0 H  [: ]' d0 E//                ShowDownloadProgressDialog();
    5 Q8 r3 {) P, |; J8 u' m//            }
    0 F" k% [% t, x//$ J3 E4 e8 P0 n8 R$ O/ f
    //            @Override1 G  i, S, Z: u/ p/ _8 b
    //            public void onRateUpdate(long total, long current, long persize) {* m) a! R) |8 ^7 h* _% j
    //                int tmpProgress = (int) (1.0 * current / total * 100);/ q, Z" d4 @4 N
    //                if (tmpProgress != currentProgress) {. J7 y' \# a( O8 \3 V: Z
    //                    mDownloadDialog.setProgress(tmpProgress);( j9 Z0 ], |, B0 B2 y# A8 m, A: i, i
    //                    currentProgress = tmpProgress;
    2 ?1 D1 i) Q' `# L( F//                }! j0 ]: O, E2 z/ l: w; c2 p' Q
    //            }% `8 O5 m3 b; c' |6 w! Z
    //
    ( k  u) D. N) M# v//            @Override
    . O7 q! q* u" ?! w: A/ P7 I//            public void onRealtimeDataUpdate(byte[] bytes, long l, boolean b) {
    ) {: X$ ~- s2 B( `! j3 u% x//                byteToFile(bytes, FileUtil.checkDirPath(SavePath)+mediaFileList.get(index).getFileName());
    0 Q: _/ f, t, E7 F+ w+ r+ O# K' ?6 }//            }
    5 {+ w; d1 X% O* q) S//: `; y! Z1 b/ b/ \. F5 N
    //            @Override: W5 g. j. q6 T! n( ?
    //            public void onProgress(long l, long l1) {
    : s3 E7 M# p, P3 {5 }) T' }//
    5 L: p6 ?% u- S2 O//            }! k( j: j) D( C/ l  a! w1 C
    //  F: t, L$ f% q3 Q8 L1 x5 ], I
    //            @Override% {: @2 U" ^4 p* C; N  S
    //            public void onSuccess(String s) {
    ! ~5 i2 v% }: S2 ?/ O0 j& O//                HideDownloadProgressDialog();1 V' n7 C3 H7 B( j. t
    //                showToasts("下载成功" + ":" + s);+ P4 C: r3 G9 Q0 @; t
    //                currentProgress = -1;/ `* Y# g) Z5 V; _& G
    //            }2 j% v+ v: P# c! U8 M4 g
    //- ~* _, C0 R* o. y: x
    //            @Override/ L8 I8 }# P3 M
    //            public void onFailure(DJIError djiError) {2 A. m' s" s9 {
    //
    0 w, a5 b4 l# @3 W2 T% R//            }2 n3 s& R; l! m3 W
    //        });
    ! x4 w- c( p. n    }7 {/ K) Q+ Y; f; x8 V
        public static void byteToFile(byte[] bytes, String path)
    $ w. Y9 `- D6 O* p+ n( M    {
    ( Y8 k5 F, a( S  O0 @        try4 e+ E: e. a! {! X# o
            {
    : F7 k" m5 L7 E            // 根据绝对路径初始化文件
    : g# n3 |  Q; y$ i            File localFile = new File(path);
    # u9 Y; Y# `9 S/ B            if (!localFile.exists())8 H) T. N4 f$ C2 K$ W6 Q% H! u
                {
    ) ~5 J0 ]1 F1 k7 e1 U                localFile.createNewFile();
    + d$ E! r: q& @- w* ?            }3 c9 A. [) g4 T
                // 输出流& x% g7 \1 V* y7 k/ N
                OutputStream os = new FileOutputStream(localFile);
    0 i8 i* v, [* ?0 o2 f: L            os.write(bytes);
    % `, C7 n# r4 J3 i) s: j            os.close();; q2 I) V$ V+ a4 {7 s
            }! \7 r1 H4 s$ T4 i) o) A4 }5 ]7 p
            catch (Exception e)+ Q5 n9 }& @0 D' V. I  S
            {
    " F: e8 r1 ~- n) n; C            e.printStackTrace();
    , {# w5 Y8 z1 G" t& _- T        }
    / x, d' `7 \  r+ z) m- j/ ?: c    }
    ' Z3 K5 `; S) v% t! c- Q    private void playVideo() {
    ) N) c2 e7 N6 {" q3 i$ K        mImageView.setVisibility(View.INVISIBLE);7 T2 q  }+ ]" E8 l& e
            MediaFile selectedMediaFile = mediaFileList.get(lastClickViewIndex);
    9 D. r  U/ n9 F% V        if ((selectedMediaFile.getMediaType() == MediaFile.MediaType.MOV) || (selectedMediaFile.getMediaType() == MediaFile.MediaType.MP4)) {
    + r; a! r9 v7 r( `% b/ L/ G( @, X            mMediaManager.playVideoMediaFile(selectedMediaFile, error -> {
    * y& E- M8 S! s- i; M  m+ O                if (null != error) {+ ~* t; Z5 L& {, Y5 Z: P
                        showToasts("播放失败 " + error.getDescription());
    ; Z; r! m8 d+ @' o, [* ~8 t, F                } else {
    6 m4 v6 L1 z) ]7 b; W! y3 Q                    DJILog.e(TAG, "播放成功");. I4 A+ \% [" ], @: G# Q. j
                        runOnUiThread(new Runnable() {% ]+ K! S5 x* M  c! {
                            @Override' q$ D. V) ^3 {
                            public void run() {
    . A' |: N' H' t8 B                            mImageViewVideoPlay.setEnabled(false);
    / k+ H8 X+ K( h+ Y* M                            mImageViewVideoPause.setEnabled(true);
    ; V% ^9 n! b* m% r) K" J6 {! b                        }
    8 V/ V6 a) T0 q! H% t$ _                    });
    + V$ _% i% T4 m6 L8 m" c: Q9 n                }' ~/ A0 J$ G/ `5 e" c( M0 n2 y5 U
                });7 X: \9 A' C5 F' x* o6 H. R, ^
            }
    / A9 C" a+ F5 O    }
    - E8 N8 ]5 D! j    @OnClick({R.id.img_back, R.id.img_delete, R.id.img_download, R.id.img_upload, R.id.img_video_play,
    . ^) q1 Y- V9 y4 d  f: O- W            R.id.img_video_pause, R.id.img_video_stop})
    4 D4 Z/ ]1 d( X0 s! b* h% c6 Z$ p    @Override
    3 v! N8 F/ [4 v. ]    public void onClick(View v) {
    / ?/ o5 Z4 g, l2 U# g  {' k        switch (v.getId()) {
    + w& l9 F1 j2 g* [3 t% V            case R.id.img_back:
    : H/ [: s* Z' K: J" Z. z) S                FileManagementActivity.this.finish();
    7 B5 B2 y% H0 Z; d; v: n  J                break;
    8 Y% Z/ c$ k# G9 [0 \% H            case R.id.img_delete:
    ! ]# t3 k' m+ p4 h0 r' I6 y                if (lastClickViewIndex >= 0) {
    " C/ @+ n+ _) I0 l- m. s( e                    deleteFileByIndex(lastClickViewIndex);2 Y4 l! i# }  [& f) |
                    } else {
    " ?5 U. {) T. k; K5 Z4 Q8 P0 @                    showToasts("请先选择文件。");
    6 g0 \) W: j0 Q+ E                }
    5 V- S' F2 c( Q" Z, N                break;2 J! _5 G7 U6 X0 b, w
                case R.id.img_download:
    6 ?  ?! H; o: g( k& H                if (lastClickViewIndex >= 0) {
    2 T* \. ]/ e# S% b4 [  o. i1 s4 v                    downloadFileByIndex(lastClickViewIndex);9 j5 i# q) |1 G5 v9 Y
                    } else {
    7 g1 ^+ i0 |7 k$ }& x                    showToasts("请先选择文件。");
    0 [: {" k' P  e/ v1 M                }
    * }$ g  f6 j  V7 @0 V                break;
    ( i4 G; T4 N9 Q0 D: g6 y7 l            case R.id.img_upload:3 F- H; W) Z; h
                    if (lastClickViewIndex >= 0) {8 j* l7 P$ M! s1 u/ o7 }
                        uploadFileByIndex(lastClickViewIndex);
    2 Y6 c3 F0 \6 C  D  T( J2 e                } else {( a: P0 H1 s% }
                        showToasts("请先选择文件。");! E/ c( A: }0 I1 s4 h  ^
                    }. m" v9 W( k3 X7 K+ i
                    break;
    8 C" B8 w1 R: H: ]' W; Q# `            case R.id.img_video_play:$ l/ ]$ p" C; d) ]
                    if (state.getPlaybackStatus() == MediaFile.VideoPlaybackStatus.STOPPED){
    7 n6 Z1 E( ?( `( {& r, p1 Q3 T                    playVideo();0 w5 z( p, m4 ?2 s. J0 A* N. A. a
                    }else if (state.getPlaybackStatus() == MediaFile.VideoPlaybackStatus.PAUSED){
    ( r5 [2 B  ~; o6 V5 y! [                    mMediaManager.resume(error -> {
    4 _' L4 |" ~) s! k) Z                        if (null != error) {
    ( t' z3 y* K* [* A! V                            showToasts("继续播放失败:" + error.getDescription());( z, I) U! G) D" V2 ~
                            } else {
    $ U) t2 _/ B# l* T                            DJILog.e(TAG, "继续播放成功");5 B) s  H; I5 J8 M
                                runOnUiThread(new Runnable() {
    . E9 c4 V% ~1 n                                @Override8 w6 ~/ H% ?3 u$ \4 W6 f" O
                                    public void run() {
    % i+ c0 v2 z3 f5 y+ k% F! w                                    mImageViewVideoPlay.setEnabled(false);
    ( W5 C; J2 m, Q                                    mImageViewVideoPause.setEnabled(true);
    5 e6 l) P/ s# H' ~& X* t! P                                }
    ! H4 }! }% e; [$ H                            });
    3 d) D) Z: |3 y# ~% ^/ }; w+ \* h5 T                        }
    & J0 I( W9 @  n1 o* x                    });
    6 v' P8 h! b3 G+ a9 n+ Z6 [                }
    % I* t; n1 c) s# a! y                break;
    & r2 Q. i: h# G; e            case R.id.img_video_pause:
    7 ^  P% w( M  G7 r  o7 ]. R! d                mMediaManager.pause(error -> {
    7 {+ o0 T+ J) Z3 r4 P                    if (null != error) {4 O4 ~$ ~2 Y. `3 @5 R6 t
                            showToasts("暂停播放失败:" + error.getDescription());/ h5 F# d# u0 ?  T+ C4 k
                        } else {1 N( E) \. f  L0 x7 u
                            DJILog.e(TAG, "暂停播放成功");. W4 z- j3 }2 y! q
                            runOnUiThread(new Runnable() {
    / V' m& D$ m/ g" N                            @Override! A! Y3 w& A& E) H2 L1 B
                                public void run() {% u' D- k+ m% v! g) {; f8 t
                                    mImageViewVideoPlay.setEnabled(true);$ e; g) ?2 E* Q: A1 W% E) y
                                    mImageViewVideoPause.setEnabled(false);
    , p3 p" m' O& P/ L! e                            }0 q+ O) F  g6 I+ n
                            });7 d4 M' Z0 X+ O! n: [  W- Q0 v
                        }+ X8 Q4 ~5 V0 M/ q8 K8 I9 t, S
                    });
    : V' ?0 h& y. w                break;
    . I. q" `/ L) B            case R.id.img_video_stop:( U) W; Z5 h. o1 _$ O8 `
                    mMediaManager.stop(error -> {
    3 L! M0 g  G- l3 y9 R                    if (null != error) {3 n. |% }/ u" I: h$ F8 c' k
                            showToasts("停止播放失败:" + error.getDescription());7 b1 n7 M* q8 D% _1 V( E. H$ X3 P
                        } else {
    * X4 v* k) k/ d- R+ a2 I                        DJILog.e(TAG, "停止播放成功");2 D* b: W8 r5 u" H8 E$ R
                        }
    8 Q# U4 j$ w' E. b                });* \' S) Q( v$ y+ ~( v
                    break;: L. N2 d* T3 ]' Q
            }
    " s4 Z' F: X8 \6 D    }) ]5 c3 J: Y- x4 x0 [
        private void uploadFileByIndex(int index) {
    . l6 G8 [- L+ a2 ?7 V        if ((mediaFileList.get(index).getMediaType() == MediaFile.MediaType.MOV) || (mediaFileList.get(index).getMediaType() == MediaFile.MediaType.MP4)) {
    6 C- q3 e- u$ O9 ?3 x; q* ~            showProgressDialog("正在上传");5 y; l. b+ j/ ]5 P& r
                new Thread(new Runnable() {& ^0 ~/ Z0 X9 ?  u% W
                            @Override; o) B, d* u0 `: B( z2 Y3 u
                            public void run() {
    $ X7 h, O" \9 D2 s" a, ]                            boolean isConnect = sftp.connect().isConnected();
    % m+ f9 o: X+ k& X* t. Y$ z                            if (isConnect){+ {1 H6 c2 v6 w. M9 }5 K
                                    boolean isUpdate = sftp.uploadFile("/mnt/uavFtpFolder/",mediaFileList.get(index).getFileName(), FLY_FILE_VIDEO, mediaFileList.get(index).getFileName());) b/ _: A9 v# ]1 `
                                    if (isUpdate){
    ( w9 F& a& K- b" `( t4 }6 C% C                                    runOnUiThread(new Runnable() {3 n2 j) v! W; ?# F+ A! H9 Y, b% x! S
                                            @Override5 i! e# h2 y/ [
                                            public void run() {8 k; k) _, N/ Q0 u7 d: B
                                                removeProgressDialog();
    8 e( W5 v; H; Q( b( C                                            http.getHttp(GET_VIDEO_INFO+"?fileName="+mediaFileList.get(index).getFileName(),"GET");9 p$ ?* l6 _9 ?/ I4 V
                                            }
    4 c7 X% ~1 Y3 _                                    });
    ) \9 X5 |3 J: s7 v                                    sftp.disconnect();
    3 _+ i( o! A3 R; Q" T                                }else {& J# U0 M, k: j6 P) o: T* [
                                        runOnUiThread(new Runnable() {, _0 [! l& L' n4 J8 t( E# f  n
                                            @Override
    4 P/ |3 k9 x# F6 O  ]" w- l                                        public void run() {8 A" }  R7 k$ o! M, J4 n* |
                                                showErrorTip("上传失败");! {6 v7 U# c* W" C% b' B
                                                removeProgressDialog();/ x' m, W2 T! j7 C1 [* u! _
                                            }; f" e( q% x# r" X
                                        });
    ' a  g2 N, y5 ^3 h                                }
    " g9 h1 C* s9 t% c                            }else {
    ) X3 O+ R3 B2 O                                runOnUiThread(new Runnable() {
    - y, b1 P, a- ?5 ]                                    @Override
    + z6 P% _* T: n9 a. e. x3 I                                    public void run() {" v/ t; F# L; W1 |; U8 @& X3 m$ V
                                            showErrorTip("服务器连接失败");7 r$ _- W1 U8 [, V& e
                                            removeProgressDialog();( H+ t/ c. y# w0 M
                                        }! }- |' @  I! L; ^4 ~% ]/ `
                                    });
    . z8 o! r& C2 [5 x                            }
    * {% p- ^+ \' w3 @$ ]8 F: y3 q$ r                        }) v% X" L( e# D. T* ?
                        }).start();
    $ t8 G0 a5 p7 T3 Y7 V        }else {) Z9 h/ C; s' u
                showToasts("当前仅支持视频上传,请选择视频文件!");
    6 W0 H2 Y# g/ ?* B& z/ u) v        }& o" B6 R" B1 w4 i4 a4 w+ F, n4 \
        }; I/ p! I- q" T( a+ I$ ^1 R
        private boolean isMavicAir2() {% m0 c# _* X& X0 @" T9 Z. v9 Q
            BaseProduct baseProduct = ReceiverApplication.getProductInstance();
    ) J& @0 S+ M2 ~: [1 v        if (baseProduct != null) {
    9 m6 a  K* R0 X# z/ \8 @8 M) d            return baseProduct.getModel() == Model.MAVIC_AIR_2;) h; r5 P( Y1 Q# U6 U9 y6 L9 M
            }2 `& h" N6 A* S7 c
            return false;
    ' X, Y, J' n8 `7 ?' }    }3 I. H1 V% `7 c1 c5 C7 T, U. _
        private boolean isM300() {
    0 m3 b! N- T( _7 P, w        BaseProduct baseProduct = ReceiverApplication.getProductInstance();3 o7 N3 q, T- P. h8 ?+ ?- v1 b
            if (baseProduct != null) {" S/ w. B0 _1 y; ]0 V" j; F
                return baseProduct.getModel() == Model.MATRICE_300_RTK;% F8 I- b+ T# m) c
            }
    5 `1 g$ q9 m  Y+ B9 q( p        return false;7 n0 l: P3 F# G6 N: _
        }
    * q: {2 t$ Z/ A  U6 e}% O1 t1 D6 m, A. y+ \5 [! [1 E8 o
    运行后界面如下:
    : q: p8 j( ^# `8 [, l  m

    hrljml3xg3e64015971351.jpg

    hrljml3xg3e64015971351.jpg

    3 {: W7 T) w. o/ ]
    - d7 n/ {8 l& d" o& w

    uemfnayen3564015971451.png

    uemfnayen3564015971451.png

    6 s( Z7 @: U3 h+ L0 \$ R5 f往期推荐LabVIEW OCR 实现车牌识别
    & g6 x0 U: d5 j0 C和12岁小同志搞创客开发:有意思的激光切割技术
    & L4 W' j* n" H2 X/ W+ I. J% PJavaScript+TensorFlow.js让你在视频中瞬间消失$ x2 x  A4 j/ e8 l3 p3 y0 z
    使用OpenCV测量图像中物体之间的距离) j8 `( K/ l9 S' V" T
    全网仅此一篇:工业级压力传感器设计及实现
    " z, n2 o7 O+ n0 m  {
    5 d" K! ^* n" C1 n- A+ B  z' Z) J! F

    5jbojgjpvyd64015971551.jpg

    5jbojgjpvyd64015971551.jpg

    5 Z) b) I# s7 u7 X* ]% Y- A$ J3 I

    kmbq44rlnd564015971651.gif

    kmbq44rlnd564015971651.gif

    % o( V& k% `  t点击阅读原文,更精彩~
  • 回复

    使用道具 举报

    发表回复

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

    本版积分规则


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