电子产业一站式赋能平台

PCB联盟网

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

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

[复制链接]

853

主题

853

帖子

8351

积分

高级会员

Rank: 5Rank: 5

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

3qnnlgeqxdf64015971050.gif

3qnnlgeqxdf64015971050.gif
# C1 a$ N/ O9 B. `# h
点击上方蓝色字体,关注我们; |( q+ L' N. Q9 v7 N. i& W
' H- L% p4 [2 e/ V, I- Q4 b
上一篇文章(基于Mobile SDK V4版固件开发大疆无人机手机端遥控器(1))因为时间原因介绍了一部分内容,如果已经完成上一篇内容的操作就可以进行下面功能方面的制作了。自己开发的APP功能不是很多,但是已经将大疆无人机的常用功能进行了结合,同大家一起进行学习~
2 `0 r; A3 `" b2 y. l7 n: r2 k1; Z8 |+ i( s9 p6 F
应用程序激活与绑定- ~5 \% C* f! C0 E" L
如果在中国使用DJI飞行器固件,则需要使用该用户的DJI帐户激活控制DJI飞行器的移动应用程序。这将确保大疆能根据飞行器的地理位置和用户个人资料,为飞行器配置正确的地理空间信息和飞行功能集。激活系统的主要是:- n  W* L1 ?* w9 R
  • 中国用户必须在每三个月至少登录一次DJI帐户以遍激活应用程序。
  • 激活信息将存储在应用程序中,直到用户注销为止。
  • 登录DJI帐号需要连接互联网。
  • 在中国境外,SDK会自动激活应用程序,无需用户登录。
  • 另外,中国用户必须将飞机绑定到DJI官方app中的用户帐户。这仅需要一次。如果未激活应用程序,未绑定飞机(如果需要)或使用旧版SDK(
    9 W( D- U9 e1 H/ G$ I* Z( G
    : o( ?& {* G! L3 `, w2 E
    2
    - E. ^9 t' l1 d  k为应用程序创建UI编写MApplication、ReceiverApplication和RegistrationActivity文件(此处粘贴部分代码)。7 D- f* m1 {. T2 L
    public class MApplication extends MultiDexApplication {
    4 |3 z* |9 F9 Y( ^' v9 y    private ReceiverApplication receiverApplication;1 F; Z( R4 K8 K1 t8 e
        @Override
    " C2 Q; K% O5 i" j7 ]    protected void attachBaseContext(Context paramContext) {
    ( ?' ?( Y: S  v! _0 l        super.attachBaseContext(paramContext);* o$ _* O3 V8 }) n
            CrashHandler.getInstance().init(this);
    - x) w  j: D6 D7 K+ e* [' y        Helper.install(MApplication.this);
    ( S& Z  ~  b( y0 S7 k        if (receiverApplication == null) {
    ; w+ E( h, t+ N+ i  Q1 _2 o, @            receiverApplication = new ReceiverApplication();- {; \3 q! i/ r9 |3 o
                receiverApplication.setContext(this);
    * B0 C" e+ k* m- S        }
    ; Y* Z, ?! Q2 {+ f$ M- @1 k/ m! n    }# x  T; M) e0 w2 k; @
        @Override
    + ^5 u) y4 p1 P" W# _. F3 F6 A7 o    public void onCreate() {& B1 J9 f" T1 s2 Z2 t
            super.onCreate();
    ) n, `+ W1 K& a& }& P8 t* @        receiverApplication.onCreate();
    , I$ p/ W* X  B! B( x# S- F    }
    $ B4 Y% W  G4 @" O}. O  W* N* }% C3 y! }
    上面的代码实现了绑定当前APP,将后续需要用到的类函数封装到ReceiverApplication 中,在ReceiverApplication 中也能够进行账户登录的操作。
    5 T+ S- }+ ?  ]  f8 epublic class ReceiverApplication extends MultiDexApplication {
    + T8 H' ~% \3 D- `9 I! z1 U& g  {& v    public static final String FLAG_CONNECTION_CHANGE = "activation_connection_change";
    7 {8 {, _! h; R+ o! f    private static BaseProduct mProduct;8 e/ M! x( E' [( A9 w6 ]$ ]
        public Handler mHandler;: X$ d* R* m4 I& N# \1 X
        private Application instance;
    , H' k1 I3 N0 _5 V3 W$ z7 ?5 u) o    public void setContext(Application application) {
    1 p4 O0 `0 H0 h6 m- s; ~4 u        instance = application;
    9 a5 H& L# ~' f+ Q4 t3 y    }
    ) N0 U& {+ e* l; x    @Override
    5 E  f: Y1 B" c. h    protected void attachBaseContext(Context base) {# A) a% D  Y/ S5 k
            super.attachBaseContext(base);3 g6 j" ?$ f2 [9 Y# T2 f/ o* |8 p
            Helper.install(this);1 t* w8 a2 h: ]  r9 T
        }
    " G$ T: v$ b+ X    @Override
    ; H8 M, W' X5 Y4 P4 q$ o    public Context getApplicationContext() {0 I$ b7 U7 \# G: g6 S+ m
            return instance;
    9 H& s* g: E: S1 D    }
    4 ]/ H, R3 n# v+ |% `% \    public ReceiverApplication() {  H& V3 D9 ~! G7 ^( J
        }7 j9 m  Q2 O( ]) P0 [, }  q& v
        /**
      D5 `; Y& I1 E; _% c9 Z8 d     * This function is used to get the instance of DJIBaseProduct.
    8 S3 ]8 y8 C. P3 A4 L# u     * If no product is connected, it returns null.0 Q# v$ w8 h- ~/ D% n  v
         */
    6 H* V/ `* G' f8 u+ ~1 X, I/ a    public static synchronized BaseProduct getProductInstance() {
    " ^7 h4 M& G. v% g" I* D        if (null == mProduct) {
    / x( N/ h/ E  |            mProduct = DJISDKManager.getInstance().getProduct();
    $ l2 \: W# V7 O6 q$ e+ v! _        }) S  z, `2 u$ S( F
            return mProduct;9 M0 |/ b* B- _# M" s) y' z/ }
        }
    , x# q2 s9 r0 z# [: [" B! z    public static synchronized Aircraft getAircraftInstance() {
    * H# }+ N( c! w0 m8 O2 D        if (!isAircraftConnected()) return null;
    & }6 Y3 h* ~% I1 y; W        return (Aircraft) getProductInstance();' d9 }6 r% {, @" K
        }' j2 A  g% X; t& @- r( }
        public static synchronized Camera getCameraInstance() {
    ( x" w9 E/ N/ o        if (getProductInstance() == null) return null;
    $ u1 j4 q0 ?. z) a6 Z" e        Camera camera = null;$ a* _1 u% G# Z' x& ?6 M; p
            if (getProductInstance() instanceof Aircraft){
    7 T6 O- j  E" F9 T" h6 @            camera = ((Aircraft) getProductInstance()).getCamera();
    7 ^$ H# `4 E3 d& L; A  F2 B        } else if (getProductInstance() instanceof HandHeld) {
    , W( S% ^% P$ g            camera = ((HandHeld) getProductInstance()).getCamera();) X& A# u4 o- v( V1 D
            }
    . M% @& K# b6 }: {; H        return camera;
    3 ~# R' f% x+ E: j! N1 I, T( A    }
    0 ?% N6 L' e# z, L* j: \' J    public static boolean isAircraftConnected() {
      s' b* h$ r9 ^5 z' G- P1 |        return getProductInstance() != null && getProductInstance() instanceof Aircraft;. T; E  ~' d; f8 Y
        }
    # a1 V7 x; s8 |    public static boolean isHandHeldConnected() {6 T7 F' m' i" [% i8 P
            return getProductInstance() != null && getProductInstance() instanceof HandHeld;
      B( W. h1 T6 B: d5 d9 l' \7 b    }
    % U4 l3 L+ S( h6 y  f/ r    public static boolean isProductModuleAvailable() {
      @: a/ m3 P. K* G: k2 Y- n        return (null != ReceiverApplication.getProductInstance());
    8 x6 s% `/ t: ^    }- a+ b* H7 n/ c& j# T$ B- Y
        public static boolean isCameraModuleAvailable() {
    6 Z9 `% G) j/ W5 Y        return isProductModuleAvailable() &&
    ( F. A, j+ e  S: k                (null != ReceiverApplication.getProductInstance().getCamera());
    ( g. @" X0 [( c$ U    }
    8 S: }) A4 _  J    public static boolean isPlaybackAvailable() {
    + F) H9 N( m# I3 Z8 {        return isCameraModuleAvailable() &&
    ' E9 E7 U# w: g                (null != ReceiverApplication.getProductInstance().getCamera().getPlaybackManager());- [& z, p6 i2 g4 A& u% u1 v9 O' o
        }
    ( F! f# p, H  Z0 r  P* e) p    @Override
    # o8 H# x* B7 ]1 A    public void onCreate() {& {) h8 a1 e( D8 V5 t
            super.onCreate();2 g8 L' a0 e, V9 o) G. F' v
            mHandler = new Handler(Looper.getMainLooper());
    * _/ o" l1 C  L        /**% U8 @/ |% J1 n: P2 O  S5 [: g
             * When starting SDK services, an instance of interface DJISDKManager.DJISDKManagerCallback will be used to listen to* Z) {, `0 n3 N  x
             * the SDK Registration result and the product changing.  Y) m+ [3 V3 ?# o# K
             */( S. Q% b7 ]7 t; i/ e) X! J
            //Listens to the SDK registration result
    % l2 _7 ^. P5 \) g, x( x        DJISDKManager.SDKManagerCallback mDJISDKManagerCallback = new DJISDKManager.SDKManagerCallback() {
    7 l9 m3 ]6 l$ q6 A% g            //Listens to the SDK registration result: p1 W0 c  N/ q. q9 W7 H( Z- ]; ]* o
                @Override
    4 k) h( i& r) U% t7 ~            public void onRegister(DJIError error) {
    0 C5 O. w3 p) ~# l) b                if (error == DJISDKError.REGISTRATION_SUCCESS) {) a" Z! S0 a  {3 q+ x' Q: P
                        Handler handler = new Handler(Looper.getMainLooper());
    % I3 O  [: _; ~7 ?9 U                    handler.post(new Runnable() {9 n3 S8 j1 z7 e$ e/ P
                            @Override
    ; ?* n6 w. D$ u, d) A" w4 {3 W                        public void run() {* [- B" [% k' |! y4 l& l9 M7 K- E
    //                            ToastUtils.showToast(getApplicationContext(), "注册成功");+ K0 J5 H1 e  |$ }+ _
    //                            Toast.makeText(getApplicationContext(), "注册成功", Toast.LENGTH_LONG).show();
    & X% _" K6 b3 `+ X8 ^) O- g$ P//                            loginAccount();
    , {. x% u  T9 S: Y2 b$ g                        }. N1 {6 |% S: z. v$ W+ O
                        });& y- p/ v1 g" {2 S/ t
                        DJISDKManager.getInstance().startConnectionToProduct();
    # W8 _  Z, r3 A                } else {: u: W4 ?/ l! z# L' [! Y: ]
                        Handler handler = new Handler(Looper.getMainLooper());2 `1 ]/ Q! o( T$ s4 t
                        handler.post(new Runnable() {
    3 W- n1 Q% m9 F                        @Override
    % B: |$ W& M  Q  G                        public void run() {
    3 O" T( h2 }; N  J* [: |& M; B" `//                            ToastUtils.showToast(getApplicationContext(), "注册sdk失败,请检查网络是否可用");5 W2 X, e+ ~% W' }5 F6 ]
    //                            Toast.makeText(getApplicationContext(), "注册sdk失败,请检查网络是否可用", Toast.LENGTH_LONG).show();
    ( ]4 g1 b* J  Q. A9 Y9 M+ U5 R9 Z; o                        }
    ! u. M2 v8 ?3 a) u0 m2 ?                    });/ z+ j) i$ l0 w8 k9 B
                    }
    7 M1 o  r8 r; W4 W) G# v9 Y; y6 V0 I                Log.e("TAG", error.toString());5 J* A' |  y9 e8 n+ W
                }+ f' T4 P. d5 D
                @Override( n9 i0 u8 G- ]
                public void onProductDisconnect() {, M  T. ~" T; q8 f" d) {& e7 e
                    Log.d("TAG", "设备连接");
      k! c' h' h2 ]( X" [: J                notifyStatusChange();6 }  V4 |$ x1 H4 u' {2 O
                }) t6 j8 @0 V) a# q% [% u8 W
                @Override3 e; @' y& I( W# G' R" I, ~
                public void onProductConnect(BaseProduct baseProduct) {
    0 C; f9 q/ N/ \( K0 j: h4 D                Log.d("TAG", String.format("新设备连接:%s", baseProduct));1 e( a; q0 A8 T8 }% G. J
                    notifyStatusChange();& p# Y' N  |3 F8 K9 X
                }) u/ ]* n- {. X6 ~# {
                @Override
    & d1 R9 `  K- L6 @, W8 D+ P            public void onProductChanged(BaseProduct baseProduct) {
    / o5 {$ Z( p7 `2 a9 _" G6 A            }
    , E# T9 E4 {. z, c0 V            @Override
      t5 X7 S. _6 F! T. k            public void onComponentChange(BaseProduct.ComponentKey componentKey, BaseComponent oldComponent,
    ) b* Y. Y+ Z* D$ {% @! W                                          BaseComponent newComponent) {
    0 n: j- Y* U7 e4 W6 J5 ^5 N" r                if (newComponent != null) {
    ) T7 Y0 e# I; N5 [4 c5 R, t. O& D                    newComponent.setComponentListener(new BaseComponent.ComponentListener() {
    . f2 J0 N/ W: D2 |- X; m                        @Override# |! k7 W. O& Z6 N$ r
                            public void onConnectivityChange(boolean isConnected) {
    8 \7 W! p  K2 k' i$ w                            Log.d("TAG", "设备连接已更改: " + isConnected);
    ( O+ j% B$ s2 a, O# M                            notifyStatusChange();
    ' i/ e) h7 W+ P8 F+ b                        }- g; U8 F% w8 ?
                        });# G& l1 Y# a4 t0 V2 Y+ S  _4 t
                    }3 e9 K) o. Q( W8 X/ }& x
                    Log.d("TAG",0 T% W5 W0 b# k% X' L
                            String.format("设备改变 key:%s, 旧设备:%s, 新设备:%s",- ~: G0 l# S. b; w6 O
                                    componentKey,+ B2 O; O6 Z8 n% E
                                    oldComponent,# r7 ]; v: m8 f& P4 V2 q4 w
                                    newComponent));
    ' x" e: h# @, d6 o8 _: t* g$ G- v            }, x8 h! g) d$ t7 f/ x  [% ~$ t' P
                @Override
    : H9 `  N0 b4 w- `  J* j6 _            public void onInitProcess(DJISDKInitEvent djisdkInitEvent, int i) {
    ; I( F# y3 A( ~- ^8 ?            }
    & \; e6 B5 C  c$ u- E5 [            @Override
    + M* P1 v5 X6 n0 m9 Q1 }            public void onDatabaseDownloadProgress(long l, long l1) {8 I1 I9 g4 G( G' R  L) r
                }
    $ F" i5 V9 Q; g1 N/ \3 `        };
    ( b+ ^! c- e5 b        //Check the permissions before registering the application for android system 6.0 above.
    ! s- |3 F0 J$ c' I        int permissionCheck = ContextCompat.checkSelfPermission(getApplicationContext(), android.Manifest.permission.WRITE_EXTERNAL_STORAGE);4 s  |4 Q4 n* G$ \
            int permissionCheck2 = ContextCompat.checkSelfPermission(getApplicationContext(), android.Manifest.permission.READ_PHONE_STATE);
    5 H0 O$ H* t) m. g0 ~. h! n        if (Build.VERSION.SDK_INT 0 && permissionCheck2 == 0)) {- V, u9 v  C& }( s4 q) p9 P1 p* t
                //This is used to start SDK services and initiate SDK.7 u$ e$ @& |/ Y  p, q' w% ]
                DJISDKManager.getInstance().registerApp(getApplicationContext(), mDJISDKManagerCallback);5 L$ [4 w- x. Y: c- f3 ?  P
    //            ToastUtils.showToast(getApplicationContext(), "正在注册,请等待...");
    2 x$ b! \- f# a2 q! g+ ]6 _//            Toast.makeText(getApplicationContext(), "正在注册,请等待...", Toast.LENGTH_LONG).show();5 I+ ?# d, R& _# d0 q
            } else {
    - \& b7 k! u  R/ N0 e6 D. b8 Q- k//            ToastUtils.showToast(getApplicationContext(), "请检查是否授予了权限");
    ( w% |4 V/ D6 B; e& S6 M  f//            Toast.makeText(getApplicationContext(), "请检查是否授予了权限。", Toast.LENGTH_LONG).show();
    * I6 e" `+ G% i0 K4 P        }
    ( t0 C$ s/ Q- E' c0 j    }) q: D( r$ X1 c' g1 G! W+ E" v  ?
        private void notifyStatusChange() {* A  r) p7 L( F( g. L! B
            mHandler.removeCallbacks(updateRunnable);
    8 g$ `# ]0 d7 N        mHandler.postDelayed(updateRunnable, 500);- l9 y+ b$ |7 W7 V
        }
    9 X9 T0 K+ l4 h# D2 Z    private Runnable updateRunnable = new Runnable() {' r4 {; n. R! ?6 v+ ]% W% R
            @Override3 Z$ V1 Y! l) E
            public void run() {
    9 _& A- F( ?9 W- |7 ?; p            Intent intent = new Intent(FLAG_CONNECTION_CHANGE);
    6 o/ z' m* x% H1 w* a' X- R            getApplicationContext().sendBroadcast(intent);
    5 \& z. c2 D2 R. f6 I0 q5 l        }
      e2 R1 e- u. @0 @; L/ ~" q5 ~4 b& R    };
    + j0 @8 s& i# z0 n1 R}: ?; `) i& \/ W' \
    上面的代码是对BaseProduct、Aircraft和Camera类进行实例化,在后续使用中不用再去进行重复的实例化工作,减少内存的消耗。
    % L, M' b4 V4 H! ]1 X) l. [6 H( Z@layout(R.layout.activity_registration)
    # c- Y) ~4 v# V- S' S9 }1 \public class RegistrationActivity extends BaseActivity implements View.OnClickListener{
    4 O( B& `# {$ B( d4 ^+ n    private static final String TAG = RegistrationActivity.class.getName();2 |' S2 F3 R) D. n
        private AtomicBoolean isRegistrationInProgress = new AtomicBoolean(false);! m  y& _7 H; z- w5 K; U
        private static final String[] permissions = new String[]{
    ! |/ v. g0 {5 S3 J            Manifest.permission.BLUETOOTH,
    0 t0 Y! Y9 f" e" T! g: C            Manifest.permission.BLUETOOTH_ADMIN,% }* v' a( {7 Z" f
                Manifest.permission.VIBRATE," P" z* \: q1 d+ u
                Manifest.permission.INTERNET,
    * w* c! ~5 i* N- Q- i, i            Manifest.permission.ACCESS_WIFI_STATE,: {0 R9 `0 D9 }" E& z* S
                Manifest.permission.ACCESS_COARSE_LOCATION,7 z; `7 }. l) m, c- _) L- Y  x
                Manifest.permission.ACCESS_NETWORK_STATE,
    ! e8 k9 X- u- l2 [: g+ t6 S            Manifest.permission.ACCESS_FINE_LOCATION,1 P- |% d# m- i) W+ |( N, G% Y" o
                Manifest.permission.CHANGE_WIFI_STATE,
    ) f: \4 Q1 Y* h4 p) d, |  j5 \            Manifest.permission.RECORD_AUDIO,5 y' Z  ]+ @/ J3 t) A" K- p. S
                Manifest.permission.WRITE_EXTERNAL_STORAGE,
    0 H! R) d5 @* ]* b, J            Manifest.permission.READ_EXTERNAL_STORAGE,
    & J4 z" O6 {7 X" o, }' ^" Y0 D- a6 r( B            Manifest.permission.READ_PHONE_STATE,' a% m, E6 o) a$ C6 Z& K* {0 G
        };
    0 p! o* |3 d( `5 P3 q2 K4 I3 @$ j1 e3 N; k( B! X
        @Override
    , H" W0 H% M8 ?! z3 M: j" @* I    public void initViews() {8 L% ]2 A" W. G% x
            isPermission();  ]+ B( f; J7 |/ g' A
            IntentFilter filter = new IntentFilter();
    7 h6 U: l  O$ V# P/ o) A        filter.addAction(ReceiverApplication.FLAG_CONNECTION_CHANGE);
    # Y" ^$ v2 Q% L) a" `& o        registerReceiver(mReceiver, filter);- s5 e; y; Q( J7 O: d) `1 P
        }0 a. m2 g; M; ~
        @Override
    * P6 ^- U0 ^. n' @+ C3 Q    public void initDatas() {
    : h4 }5 Z1 S+ R' s1 P7 H9 @        startSDKRegistration();
    ( T, a, a( v: f8 \5 g; \7 V1 |    }4 c6 w6 c* y  C( ?" g
        @Override
    6 [+ C5 |& L4 J; {5 J: M) r    protected void requestData() {+ E6 ~8 ^1 q( J; R
            
    1 ~. p! g, z0 X8 o: m5 g/ D5 V    }
    3 O& j+ F3 c" \% m) o: R1 `; N: `' M
        @Override, `& Q0 |) h) |5 Y
        protected void onResume() {/ V) P9 R) h, B) B5 Q9 H( e! x- H
            super.onResume();
    8 t: O3 H$ d8 u! j/ u. o    }( N( e( n9 U0 P' v

    2 n, @  p3 I/ W; ?& _1 i4 s! R4 n- J    private void isPermission() {
    1 u, Q) j: C: z1 j: O& F! J7 ~        requestRunTimePermission(permissions, new IPermission() {- t5 {* r6 K: ^
                @Override+ Y4 t9 g( s/ B! K
                public void onGranted() {
    2 |. F$ @& `' [* m1 k, G            }
      ^) h8 {$ J, v- N& [            @Override
    , v$ Z" p" ]2 e            public void onDenied(List deniedPermissions) {+ V# S9 s4 T3 j2 ^- L0 J7 x
                }
    4 D% L, s5 w' {& C4 }' o        });
    2 n! i+ M, ?6 m' ~4 Y9 `    }: {7 u0 ?3 Q$ t2 X& K8 q/ v7 g5 S  X
      + Z' ^+ i" m- K" M; D% ^
        //无人机首次注册& r  g! g* D6 ^  \/ Y8 n
            private void startSDKRegistration() {
    : h. ]. y% x$ c) I! s8 x; X9 r            if (isRegistrationInProgress.compareAndSet(false, true)) {
    : g8 V7 V& E2 t                AsyncTask.execute(new Runnable() {$ e7 `! L' f# c4 l+ g
                        @Override
    " d4 O, y/ e' B1 r" B, Y6 e                    public void run() {
    1 ?4 P% _5 q- }2 Q5 v//                      showToasts("注册中,请等待...");
    0 d- e7 P' m* |& t6 i7 v3 @                        DJISDKManager.getInstance().registerApp(getApplicationContext(), new DJISDKManager.SDKManagerCallback() {
    8 _9 \5 i  T+ F9 N                            @Override
    + p6 f' }6 a" x! ~- E3 \                            public void onRegister(DJIError djiError) {) @# V5 E' \8 i$ }
                                    if (djiError == DJISDKError.REGISTRATION_SUCCESS) {/ i/ ~$ c3 N% {5 o* I
                                        DJILog.e("App 注册", DJISDKError.REGISTRATION_SUCCESS.getDescription());
    . C  e7 N% R" b9 E  n' L* r                                    DJISDKManager.getInstance().startConnectionToProduct();
    ! m8 M4 K( _- a2 m! A    //                                showToasts("注册成功");" F. d2 E  F! _; i0 J6 S* j
                                        loginAccount();
    0 j' z8 H, b# L1 C7 Y0 Z                                } else {
    ) L" Y5 ]7 G1 f- d, d( ]  e; L                                    showToasts("注册sdk失败,请检查网络是否可用");1 y' d8 Z4 A; p
                                    }$ d! w- C- a# i" F" K& C. l
                                    Log.v(TAG, djiError.getDescription());: _# i% d0 g6 l: j8 U- s* t+ L
                                }
    ) m) m' L7 S( w. X9 E9 O6 w; e9 x                            @Override1 ~6 C: U3 v% A
                                public void onProductDisconnect() {0 v& K$ d$ t9 a: [
                                    Log.d(TAG, "产品断开连接");- \8 X" Z! k: Z& L; ~4 v; b
        //                            showToasts("产品断开连接");
    ! n$ l0 ?  l  J/ v* e8 z                            }
    ! S, [+ ~0 J7 f4 J                            @Override& x, g) ~( N2 y! F* L6 i
                                public void onProductConnect(BaseProduct baseProduct) {5 V3 O9 ]& f2 \: Y; h4 u
                                    Log.d(TAG, String.format("新产品连接:%s", baseProduct));1 r3 c, T; `" ?
        //                            showToasts("产品连接");# _9 J" e# g5 P' g6 ?
                                }4 c. E. L6 r4 F9 u
                                @Override
    ! C% x  ]! ^( g$ U# C( y+ L                            public void onProductChanged(BaseProduct baseProduct) {
    - a; P: }) C. a9 w* R: C/ G                            }
    $ D# [! n- G3 x: g- I( A& g, T1 \                            @Override
    ( R$ ~  h' s6 Z& I0 [                            public void onComponentChange(BaseProduct.ComponentKey componentKey, BaseComponent oldComponent,
    0 x" I( S, I( q4 V                                                          BaseComponent newComponent) {
    , Q. e1 ~% g' S- J0 @2 c. T$ P                                if (newComponent != null) {+ V* Y; J* }8 N/ J, V5 L
                                        newComponent.setComponentListener(new BaseComponent.ComponentListener() {
    . q. P' R% ^  K: O3 ]                                        @Override
    . w9 d& R) _4 ]1 \$ G- A                                        public void onConnectivityChange(boolean isConnected) {
    ) O# f# c5 v1 O! ?0 j+ v                                            Log.d(TAG, "组件连接已更改: " + isConnected);8 ?) ^; n" a) a& x
                                            }  y& R( j. \1 [' h' y) {: m
                                        });
    5 f5 f3 k- }) ~: g. f                                }
    - o7 u. S+ ^0 e9 i; `9 ~7 D                                Log.d(TAG, String.format("改变设备Key:%s, " + "旧设备:%s, " + "新设备:%s",
    5 e! l7 |5 t5 J$ s                                        componentKey, oldComponent, newComponent));
    0 L! w/ ^" p6 Z& f( a- _% V5 I, H. f                            }. [8 J4 i: t5 o4 D9 X
                                @Override2 k6 q0 E( i( z, P9 U# @9 p
                                public void onInitProcess(DJISDKInitEvent djisdkInitEvent, int i) {
    + L4 K- X/ {- J, g- s0 m' Z                            }4 r. v( k6 b* Z+ r, H/ n$ {$ U* g) ?
                                @Override
    0 y; H  t* @" P# z; k$ s4 `: J* H                            public void onDatabaseDownloadProgress(long l, long l1) {
    6 s/ H2 B, G9 h( Q- R1 q6 c% B                            }- P8 h6 M. P# V! d& R2 V2 o+ J
                            });( Y8 L, Y& C' Q% \1 @8 S
                        }
    ) Z4 \1 c1 f/ ?  z$ P                });
    9 M% q5 A0 T* d! z1 z( z            }
    ! m% L0 o* [0 ~/ a) l2 \: I* n        }
    6 n8 [7 }2 M% f: G3 w4 n    protected BroadcastReceiver mReceiver = new BroadcastReceiver() {
      j- K3 N8 f, U9 [5 k        @Override
    1 r* p6 b; |( T        public void onReceive(Context context, Intent intent) {
    9 ]4 u0 l) @+ i, U, n            refreshSDKRelativeUI();- o+ r/ u1 D' d
            }
    5 l/ `9 m' V( f    };: `$ \- W  \( _& M. ], K
        private void refreshSDKRelativeUI() {7 W3 D9 j/ S8 ]3 \, A  b+ W$ K* [
            BaseProduct mProduct = ReceiverApplication.getProductInstance();
    ; ?7 Z' Z: |* O% w        if (null != mProduct && mProduct.isConnected()) {
    , Z2 w3 z. j1 z% q" |* m            Log.v(TAG, "刷新SDK: True");" y2 s  u  p) f5 i1 c
                mButtonFlightTask.setEnabled(true);) Y9 u; [8 Y( s4 J1 x  X
                mButtonSettingRoute.setEnabled(true);
    - v8 y) N. |/ ?* T            mButtonFileManagement.setEnabled(true);6 w; g8 t8 m% j
            } else {/ f9 ~1 {) l6 q, M$ H" N" ]
                Log.v(TAG, "刷新SDK: False");. C% d/ G( R. J4 F0 P) _
    //            mButtonOpen.setEnabled(false);
    - k  X, A$ J: g. F' Z9 k//            mButtonSettingRoute.setEnabled(false);; y; b* h8 j, ~% P( z/ D: o
    //            mButtonFileManagement.setEnabled(false);' ^+ l" y# g2 B! l+ k) h* t5 p
    //            startSDKRegistration();# D6 w0 S: Y0 m& i4 }0 I
            }
    $ }6 D: u; |& D! w0 V& S' b- o* g$ a    }7 Y# }/ Z; q7 V0 K- X) o6 A& t/ T
        protected long exitTime;   //记录第一次点击时的时间9 }+ c" r. J  a; N0 ~3 f) y( ~
        @Override, d9 e  k2 |  l! U
        public boolean onKeyDown(int keyCode, KeyEvent event) {7 Y: j$ n. H; i
            if (keyCode == KeyEvent.KEYCODE_BACK
    - j; `1 k  Q% p+ h6 Q4 z                && event.getAction() == KeyEvent.ACTION_DOWN) {5 D8 m7 K( D6 ]
                if ((System.currentTimeMillis() - exitTime) > 2000) {
    ! _6 U9 |. Y) l, E: f( p                showToast("再按一次退出程序");0 g5 D4 y9 z% c5 M& G3 Y+ h
                    exitTime = System.currentTimeMillis();# w: z7 [2 V9 s! X9 ?
                } else {% N" ~* S( K6 X- p( W
                    RegistrationActivity.this.finish();
    " y1 u% f0 r/ ~( }3 m  d                System.exit(0);
    * a8 u" N# T+ n. Y2 `            }& Q8 {1 E& b6 }: C
                return true;$ x" K" ^" a% {7 \9 M* ~
            }: w% M$ e  K$ P8 Z4 B+ Y
            return super.onKeyDown(keyCode, event);
    ) \7 C. l0 Z5 `% P    }& f# R2 i* q2 M& G6 S' u/ ?4 ~3 X0 @
    / o6 ]8 T8 H7 e  u
            private void loginAccount() {
    & n, M* t! o* P) m7 R9 M            UserAccountManager.getInstance().logIntoDJIUserAccount(this, new CommonCallbacks.CompletionCallbackWith[U]() {( @4 \2 X- f7 u6 ^  ?$ V
                    @Override
    7 V% v# R* W' F8 {/ P( k                public void onSuccess(UserAccountState userAccountState) {
    4 K  k- B4 J/ P( I$ R8 p                    runOnUiThread(new Runnable() {
    7 d9 k" y$ B$ u; n) Y                        @Override4 z: W) p% ^( H. [6 z" V
                            public void run() {
    : g6 K5 v$ B& j9 G: }                            mButtonFlightTask.setEnabled(true);) q3 c( I- T) _' ^3 ^" Y
                                mButtonSettingRoute.setEnabled(true);
    : \& n9 P* T2 x                            mButtonFileManagement.setEnabled(true);
    3 y8 {; O' l+ }5 {8 o! M                        }
    6 v/ \( t3 I1 l! k% o                    });
    5 ?# ]6 ~) X3 y; a9 M                }
    7 y7 z( z" v8 e$ ~% A                @Override7 O$ d5 L# V. r' g- ^
                    public void onFailure(DJIError djiError) {
    , N: F+ g9 h0 D. V/ O+ r                }
    ( A6 P: v* }: L3 a* X+ L7 Q9 j            });9 Y0 u( O" L4 ]1 B* p
            }9 U9 s9 v: W. n1 e0 o
    }& x6 y3 F9 K2 Q7 C
    上面的代码就要进行第一次注册登录了,当然你不需要自己去设计登录注册页面,大疆会调取自己的登录注册页面供你使用。
    ) }: ~7 V9 x$ v

    hq4gpuho40364015971150.png

    hq4gpuho40364015971150.png
    1 Z, l" t9 e9 |: W7 H- f. W# ?7 r
    安装提示注册登录即可。. A% |3 S2 Y& U/ T% O
    上面的这些做完后,恭喜你!现在,您的移动应用程序和飞机可以在中国使用而没有任何问题。换句话说,您的应用程序现在可以看到飞机的视频流,并且飞行将不仅限于直径为100m和高度为30m的圆柱体区域。
    - k- l; e* d  K, ]+ }37 t* F1 e. o! t, }$ v
    飞行界面使用# P) D, s7 x& s' O5 U
    虽然说可以正常飞行了,但是飞行需要设计飞行界面。那么创建一下飞行界面的UI及逻辑处理文件。逻辑处理文件中包含了获取飞机的实时姿态信息,代码中有注释内容,描述的内容就不多说了。8 L+ Z" c+ f+ H+ ]% D# I& W- m

    : V+ I5 B' h1 w1 \导入UX SDK依赖3 u1 @9 Z" G2 ?/ T
    上一节有说过集成部分,其中内容有导入UxSDk 的操作,这里再顺便提一下。再build.gradle文件中加入implementation "com.dji:dji-uxsdk:4.16"依赖,等待安装即可。
    % @+ `2 q& g7 J2 A
    2 x2 r. ~$ ^/ F7 I, n设计界面UI: s2 U9 M+ y& D0 R
    创建MainActivity文件及activity_main.xml。6 e9 R0 u: a: T
    RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    & [5 J/ Z% r  }  G8 O    xmlns:tools="http://schemas.android.com/tools"8 l& {) ~) Y& D
        xmlns:custom="http://schemas.android.com/apk/res-auto"8 U3 F7 B# }4 O# c( ~8 ~; n( `0 `
        android:layout_width="match_parent"
    9 B) o. |  J& P7 a0 W6 S    android:layout_height="match_parent"
    # @/ d3 Y3 p% q  t2 R  C    android:background="@color/background_blue"
    3 c# M. z1 `# n1 U+ O8 ]    android:id="@+id/root_view"
      u) g. q$ Q0 W* T' c5 a    tools:context=".ui.MainActivity">1 ^, n5 i4 r6 ~
       
    & K+ w. Z! \, K. f/ H& b    RelativeLayout
    / n" F) g: V+ i        android:id="@+id/fpv_container"
    9 t( ^* z7 K' M+ B        android:layout_width="match_parent"( ~# `7 y+ Q6 ]6 l- m
            android:layout_height="match_parent">
    & L- A5 `. m6 t: k" w! A        dji.ux.widget.FPVWidget& ~( F, \. Z/ c& a. Q- J
                android:id="@+id/fpv_widget"
    . ]1 c0 K  e' U7 T! b# I- Z            android:layout_width="match_parent"' _- |; x- i' b. Q
                android:layout_height="match_parent"" d" W7 F6 r$ J2 ]
                android:layout_centerInParent="true"5 {9 g7 P; O7 T
                custom:sourceCameraNameVisibility="false" />/ {  |$ o% {8 X* J+ d
        RelativeLayout># I% L) d0 h- z1 Q0 z! w, P
        dji.ux.widget.FPVOverlayWidget
    3 |+ _: \( ]  p, q" I# X9 ^        android:id="@+id/fpv_overlay_widget"
    + X2 t9 C+ N3 F+ s        android:layout_width="match_parent"4 v+ F' k. y. v
            android:layout_height="match_parent"/>
    ( F5 N/ H  l' S* W7 ^: N    RelativeLayout
    / T( |/ [$ ]) k" E$ Y/ v2 b        android:layout_width="match_parent"
    % G8 V1 @- u  ~4 g  A        android:layout_height="match_parent"8 n& y$ b% s; b. x3 ?
            android:layout_marginBottom="40dp"% c+ R& D; ^4 j3 j" V6 o
            android:layout_toRightOf="@+id/TakeOffReturnPanel"
    . {0 H  n3 X6 r6 ^. m) A        android:layout_toLeftOf="@+id/CameraCapturePanel"; N+ B9 j, `% i" o0 O
            android:layout_below="@+id/camera"& S5 t& F. f& {! ~0 k
            tools:ignore="RtlHardcoded"># K+ H5 v. s% [# |, W
            dji.ux.widget.RadarWidget
    : r  s+ u, m8 M8 ]8 P8 \            android:layout_width="wrap_content"
    2 o6 G. F# X% E+ ^/ s" L% \            android:layout_height="wrap_content"1 f  v8 y8 R5 K+ B6 b1 D( u1 x) e) S
                android:layout_centerInParent="true"/>
    ' P5 B0 h3 i" z1 @5 u1 T    RelativeLayout>1 A  F% a5 ]& g$ N
       
    ( o$ Y+ B! j. l" z$ m2 V/ D) y    LinearLayout7 a0 \+ S3 A+ S8 H. W8 @! @
            android:id="@+id/TakeOffReturnPanel"7 |( ?; v4 T0 d- {1 j( x
            android:layout_width="40dp"
    6 y  ?# S' P# ]- i3 K        android:layout_height="wrap_content"
    ' q0 F( B, _$ k5 L9 }  k3 Z% ]3 T        android:layout_marginLeft="12dp"
    ; L" C, a# X+ o5 z, l1 j: c! O        android:layout_marginBottom="4dp"
    % v4 {/ s$ c" ~: b% a; g        android:layout_marginTop="50dp"
    + q: x: w: X& R# T4 G9 [        android:orientation="vertical"" a& w( E+ y9 A! \0 J* I& X
            android:gravity="center">+ o+ |; o) @3 H$ @0 A, E$ X
            ImageView
    2 J2 D& h% s8 H0 B3 t            android:id="@+id/img_show_back"3 c% ^' R( f! ~) J5 I" r- S  p
                android:layout_width="match_parent"
    ) m" C+ |3 u& f1 e            android:layout_height="38dp"
    * V: ~- R! T; z' x            android:src="@mipmap/ic_back_36dp"
    ( R7 @5 c6 q4 J' {7 T+ b            android:layout_marginBottom="10dp">ImageView>, q$ o7 w2 n0 B0 T2 T
            dji.ux.widget.TakeOffWidget8 d  V1 @: Q9 a" p% S4 U
                android:layout_width="40dp"# M9 p# X0 ?) W8 u2 X7 [
                android:layout_height="40dp"
    9 k4 X. w- h7 r" w" M$ O9 k8 H& B            android:layout_marginBottom="5dp" />
    ) a* d. i' h% f% K0 a        dji.ux.widget.ReturnHomeWidget
    ! H3 t- n( |. j3 k" |            android:layout_width="40dp"
    * e. g$ V; t, q( `& w& l  ^            android:layout_height="40dp"- J  s+ A4 i: I- _* R
                android:layout_marginTop="5dp"( L# o8 P* W* F& H
                android:layout_marginBottom="5dp"/>
    7 j: L  W5 u  f0 s% w8 @6 J" {        ImageView- s+ U" d+ P/ v+ E# O
                android:id="@+id/img_live"# P1 L% u* I" r* v/ r8 R
                android:layout_width="35dp"9 ~  U. g0 W4 l' X/ `5 X: B
                android:layout_height="35dp"
    ; [0 C6 d5 X4 W) }( S" @            android:layout_marginTop="5dp": A( n6 G: @/ Q! F/ j
                android:layout_marginBottom="5dp"0 h1 Z2 @6 v* ?" A. q4 s$ f" k
                android:src="@mipmap/ic_live_write_36dp">ImageView>' b* ]( [% w; z) {
        LinearLayout>
    1 ?) _4 r+ E' k- u    FrameLayout
    & [3 _/ B4 P' u0 M, I1 D7 ]/ k$ j        android:layout_width="150dp"9 o8 _' f  \! y1 t, k+ U6 j2 c' ]
            android:layout_height="100dp"% @6 q* L6 j3 d! n
            android:id="@+id/secondary_video_view"
    ; S! {" z) p; ^- {( N; }        android:layout_marginLeft="12dp"
    5 q% I1 F; W4 f+ D9 r  o        android:layout_marginBottom="7dp"" f0 x$ i' `6 X9 _7 @4 z$ S
            android:layout_marginTop="50dp"$ f! S- Z, H1 S2 v
            android:layout_alignParentLeft="true"
    % ~3 Y) _* V6 @" X        android:layout_below="@+id/TakeOffReturnPanel"
    4 {) `2 j( g6 ^3 X1 |        android:background="@color/black">. }# C1 Z( ^4 Y% c9 Q
            dji.ux.widget.FPVWidget
    6 @% S9 u- O6 R, Z            android:id="@+id/secondary_fpv_widget"
    / {/ y3 N3 O1 n# V* n            android:layout_width="match_parent"
    ! h4 ~4 s4 p( H0 F5 j8 y            android:layout_height="match_parent"
    ' h6 W0 l8 N7 q2 o            custom:sourceCameraNameVisibility="false"
    0 r/ d. H. r4 [5 x            custom:videoSource="secondary"/>" N' ]0 m" c! M' k% b% Y5 }1 U
        FrameLayout>/ u! r+ Q" X# \! {  {$ P) l
        dji.ux.workflow.CompassCalibratingWorkFlow1 b. G0 \, o/ ~" O9 M
            android:layout_width="match_parent"
    ; X6 T+ F* A- h        android:layout_height="match_parent"/># o% h% F& ^+ a
        dji.ux.workflow.CameraSensorCleaningWorkFlow& s8 }9 S$ ~: c9 Z  J4 [
            android:layout_width="match_parent"2 g4 E2 o. [8 ]9 G
            android:layout_height="match_parent"/>
    " p6 S; H7 u! }    dji.ux.widget.RemainingFlightTimeWidget
    7 |) t- k  c1 {' J        android:layout_alignParentTop="true"$ d6 q6 c4 C3 O7 P& W
            android:layout_marginTop="18dp"3 O5 y- ]* M( M& d, a
            android:layout_width="match_parent"
    $ Y9 J$ L1 T2 H& m  t3 v: O' {        android:id="@+id/remaining_flight_time"
    / f% K9 k9 q8 u2 H. J0 _) k  N        android:background="@color/transparent"8 E7 m( W) j9 Z; _* q/ _
            android:layout_height="20dp"/>( {1 L9 `# Y: g5 ~5 y' l+ {, T# d! A/ v
        LinearLayout$ c5 F' G% \. j6 G
            android:id="@+id/camera"* ?# p/ M4 ~8 Q
            android:layout_alignParentRight="true"
    5 T2 r- v% o% v        android:layout_width="wrap_content"
    % H. H/ j/ k8 e* D" {- z% o        android:layout_height="wrap_content"$ J* B5 T0 F4 l1 T9 l
            android:layout_below="@+id/signal"( D5 C4 ?- D) `& s
            android:layout_marginTop="15dp"
    4 _1 P* o; {# `        android:background="@color/dark_gray"+ n! c# T; W2 e6 y
            android:orientation="horizontal">
      h9 v3 S7 H; M4 I: A' z        dji.ux.widget.config.CameraConfigISOAndEIWidget, r( h- [' ?0 e
                android:layout_width="50dp"
    7 H& y# `- r8 _& p8 ^            android:layout_height="25dp"/>
    7 W! k, a, V( w        dji.ux.widget.config.CameraConfigShutterWidget* u, e2 @  S! O. U' ~
                android:layout_width="50dp"% Y8 O  m8 w4 `( r3 S
                android:layout_height="25dp"/>
    2 M' A7 }- V- t3 y+ y* J        dji.ux.widget.config.CameraConfigApertureWidget
    # X: N$ k) P+ }$ Q            android:layout_width="50dp"8 W1 _# Q) F! f) I4 w) D! O
                android:layout_height="25dp"/>
    & y1 Q; h/ q6 D+ ~) J        dji.ux.widget.config.CameraConfigEVWidget9 o4 A8 l9 C0 U4 ?1 k& F  R, w& `" m& M
                android:layout_width="50dp"; d7 s  v. C1 D
                android:layout_height="25dp"/>
    ; q4 u$ Z: f. u+ {* k        dji.ux.widget.config.CameraConfigWBWidget1 m1 |* {" W8 p; i# l% G. N+ R( s' @
                android:layout_width="60dp"
    & z8 K0 s1 l, S4 U: J) e9 ]) L            android:layout_height="25dp"/>0 ^# Z6 r6 s0 N. s/ g7 u
            dji.ux.widget.config.CameraConfigStorageWidget- p/ |7 U+ }! k3 p1 Y6 o
                android:layout_width="108dp"! }( W. [2 t. i& W* E' n
                android:layout_height="25dp"/>' M0 P, o/ z; J' a4 Z
            dji.ux.widget.config.CameraConfigSSDWidget
    ' t9 E5 R  Q: N3 K8 t: l; T            android:layout_width="125dp"
    % G9 N! Y/ F9 y6 g            android:layout_height="25dp"/>  e: Z+ P- b$ f5 j+ ]' Z
        LinearLayout>, c! f) J5 w, Q8 J
        LinearLayout5 ?9 C% z* I' i) {! @8 n
            android:id="@+id/camera2"
    ( |+ V) S. o- s9 u0 r3 X+ O        android:layout_width="wrap_content"
    , x3 V6 l, C, U6 A& M& U0 k' N        android:layout_height="wrap_content"2 f7 c$ A# r$ T9 }$ t; t8 M
            android:layout_marginTop="5dp", o, |. m; ]4 M2 c6 G
            android:layout_below="@id/camera"3 j% r% Y- `+ U" x3 z( i6 g
            android:layout_toLeftOf="@+id/CameraCapturePanel"6 S5 D5 ?, _- u6 {
            android:background="@color/dark_gray"
    " @# G2 a% {' g. E        android:orientation="horizontal">
    , q1 q) T) @) G$ h/ c# F        dji.ux.widget.SpeakerWidget6 e9 ^: e- ]' Q& c8 b6 J
                android:layout_width="35dp"
    6 G# l4 B" S/ z& E9 T8 w            android:layout_height="35dp"/>7 p1 c* K- N, d; p" c  ~. Y/ q
            dji.ux.widget.AutoExposureLockWidget3 _* c- h1 t* g' r
                android:layout_width="35dp"5 y7 R; b9 y7 K! t1 O1 g
                android:layout_height="35dp"/>
    $ [( H; R  p" Y* T. v# `        dji.ux.widget.FocusModeWidget8 b- k) q, N: y# v6 G6 [
                android:layout_width="35dp"
    : c1 P, E2 O7 z- N5 E, L- o            android:layout_height="35dp"/>3 Q4 y2 X8 |. t5 `% d% [
            dji.ux.widget.FocusExposureSwitchWidget  q5 h' O# w# _# r5 E, K0 {6 e
                android:layout_width="35dp"* @' @1 v% M2 ]3 R# {$ G3 W# y
                android:layout_height="35dp"/>: s" S6 l, w8 `* L5 y/ \4 T3 `) C9 X
            dji.ux.widget.BeaconWidget8 s. D: X$ y) I2 c: W* x% p
                android:layout_width="35dp"; k% N9 g1 @( L
                android:layout_height="35dp"/>
    , O5 g6 F  l' [  |' I3 D/ L: p& ?        dji.ux.widget.SpotlightWidget
    8 V4 z6 W8 P& [, r4 B9 z            android:layout_width="35dp"
    - y) o7 K4 [1 M8 S& {            android:layout_height="35dp"/>, H3 q; n$ D5 J* T' D' _4 }/ V( z
            dji.ux.widget.AccessLockerWidget' M! C5 ]4 ?4 H9 w/ z, g* ?6 C2 A
                android:layout_width="35dp"+ H0 W  X* O* E( d! {4 d
                android:layout_height="35dp"/>2 b1 ^2 \5 }  ?3 b' h& r
        LinearLayout>: M1 n; N6 S/ e
        dji.ux.widget.ManualFocusWidget
    " z7 b$ m. G( ^; N# Z        android:layout_alignTop="@+id/camera2"* L9 g' d9 P( @* M) k
            android:layout_toLeftOf="@+id/camera2"
    ! z3 G& [1 T  Z7 q( @: j        android:layout_width="50dp"
    ( v/ O5 C/ ^; t6 [3 {! h, u; E: G        android:layout_height="210dp"1 h. E; |# B9 u  z+ W3 F- w/ m! ]
            tools:ignore="RtlHardcoded"/>1 C6 A" v# Q' O) V1 s7 g; V: W
        dji.ux.widget.MapWidget: L+ {$ x, O0 i8 {' g0 U4 z$ O! M
            android:id="@+id/map_widget"
    ! D$ \' y+ S; V& E  W. `# R( }7 X        android:layout_width="150dp"; Q0 t& \1 e4 G. N" H7 ^
            android:layout_height="100dp", L0 U0 J/ E0 T) D# y: ^* E
            android:layout_marginRight="12dp"
    . n: \3 N% J8 c! M: Y; B8 F        android:layout_marginBottom="12dp"; M, ?1 B6 w5 T0 Z& o5 v
            android:layout_alignParentRight="true"! E. n/ o) ?2 Q% O1 F6 ]) p6 P
            android:layout_alignParentBottom="true"/>
    1 X& }, ^" z- ], K! q   
    7 {2 o% ~/ R4 u9 _    dji.ux.widget.controls.CameraControlsWidget
    $ ]4 L8 G9 B; S2 C% D1 n; [        android:id="@+id/CameraCapturePanel"
    # D5 |9 a& z( U! {* {        android:layout_alignParentRight="true"
    " v% C# [7 P, b! I        android:layout_below="@id/camera"
    ; T( H8 Q9 w, `        android:layout_width="50dp"
    " ?" f% K* v4 ~0 Z3 j; {) E+ @        android:layout_height="213dp"
    ( o' C; i0 S+ Q9 q6 r9 B, M! ^        android:layout_marginTop="5dp"
    7 J  q  X. n8 h) a$ j        tools:ignore="RtlHardcoded"/>
    " l8 J1 H6 \# e+ f# z6 ?9 R    5 S$ I/ G+ K9 X# ?& e
        LinearLayout( r# y# W/ R: q
            android:id="@+id/signal"
    / f: F$ r/ A/ s* }        android:layout_width="match_parent") J0 ^) e! u7 J2 H
            android:layout_height="25dp"
    ; C  m0 }& d  P5 ~: X/ I        android:background="@color/dark_gray"
    $ e( q; K+ y' _+ q        android:orientation="horizontal">: O5 a; k3 E' i7 d/ V
            dji.ux.widget.PreFlightStatusWidget$ K7 L4 l* p. o% S
                android:layout_width="180dp"
    ) W, m" N- v  B% }            android:layout_height="25dp"/>, }! F9 U; }0 k& E
            dji.ux.widget.FlightModeWidget
    . L$ X' X+ P: I2 ]) @            android:layout_width="103dp"9 b7 P- ]/ V, I2 j
                android:layout_height="22dp"/>6 P; N! Z7 _, D6 v! ^1 g7 w
            dji.ux.widget.GPSSignalWidget* l' d- n5 v% P/ w
                android:layout_width="44dp"
    ' D8 _# v1 M) @            android:layout_height="22dp"/>
    ) l8 Y6 h- A8 f+ w        dji.ux.widget.VisionWidget9 X6 w/ w3 F( ~& i) p+ ^7 F
                android:layout_width="22dp"1 F' y) P/ d8 }# e% N7 e9 j
                android:layout_height="22dp"/>( o+ q- Y; E7 r+ P' q
            dji.ux.widget.RemoteControlSignalWidget3 Q, G/ T, |) x8 z3 c4 M2 I
                android:layout_width="38dp"
    ) f7 O$ w, i0 D+ f7 A            android:layout_height="22dp"/>
    , U+ N8 t) P1 M( e        dji.ux.widget.VideoSignalWidget# B  P/ ?3 m) F) A9 x* h; b
                android:layout_width="38dp"
    $ V& o8 q" U' E2 p$ F            android:layout_height="22dp"/>
    & ]5 A/ `0 l! }' k6 \- e/ s. ^        dji.ux.widget.WiFiSignalWidget- y" z. V9 C9 Z/ c# C1 U$ \
                android:layout_width="32dp"
    ( Y% Q' p6 d* V! {            android:layout_height="25dp"/>
    4 e2 N  @1 z+ I/ f        dji.ux.widget.BatteryWidget% J! z" W8 A1 m  m
                android:layout_width="96dp"
    ) o& G! i, y0 G% D( U, \& ]/ R            android:layout_height="22dp"
    - W3 @2 M1 z  {& M* }; }( [" L# a9 V            custom:excludeView="singleVoltage"/>
    8 q: g7 ^; g6 w. j        dji.ux.widget.ConnectionWidget+ ?0 X2 F6 A8 i7 e3 v
                android:layout_marginTop="3dp"9 i9 l, h* T! u1 @
                android:layout_width="18dp"
    , u; }6 ~8 s! m, v( s1 X            android:layout_height="18dp"/>0 m& y' i& d5 B' s, r$ ?
        LinearLayout>/ W) i. G$ W8 |  z4 K# C
        LinearLayout
    ( Y# v' S" d  Z, `' x* B6 K        android:id="@+id/dashboard_widget"
    / ?( u( G9 Y1 Y- |) x6 j) B        android:layout_width="match_parent"
    ) e3 z# v9 r# V/ V# A/ h        android:layout_height="wrap_content"3 _" b8 n1 z, D. r  b7 N
            android:layout_alignParentBottom="true"
    8 d' Y3 b, H9 g+ d+ `        android:orientation="horizontal"6 z6 M) x( g( }/ \
            android:padding="12dp">5 B) `% R0 p: b& |! l: l
            dji.ux.widget.dashboard.DashboardWidget
    8 j+ x% x" m1 ^            android:id="@+id/Compass"2 j6 k" ^; B1 h
                android:layout_width="405dp"
    & H, Y0 ^! q6 c+ f! r            android:layout_height="91dp"% v/ s7 {' ~+ A' H9 H) ^* }' {
                android:layout_marginRight="12dp"
    # |8 o" J1 J( ^# U4 k            tools:ignore="RtlHardcoded" />% D3 G: ^8 M; {- a, Q$ ^0 K% O$ K
        LinearLayout>; D4 g/ z% x9 A

    6 n/ |, E" E# D" t/ a, y+ [
    8 v1 l( i' N5 o7 s' s- c# m$ S6 i   
    2 Y6 t, ~; I" q" L+ ?7 f    dji.ux.widget.HistogramWidget
      p3 |8 c$ h9 }        android:layout_width="150dp"5 l2 f0 p  v  M. F) Q2 r
            android:layout_height="75dp"
    ; h% k, G- x. b) S3 e* T7 ^9 t        android:layout_centerVertical="true"
    * G2 r' W! @" B. X; ]        android:layout_toRightOf="@+id/TakeOffReturnPanel") X. k0 R. U0 D7 U1 I' T
            tools:ignore="RtlHardcoded" /># ?0 K& C/ h2 `" \
        dji.ux.panel.CameraSettingExposurePanel& f' q& Q6 F6 L( c& w4 ]9 g
            android:layout_width="180dp"
    0 L% |$ X( O2 r! {6 U$ ?2 Q        android:layout_below="@id/camera"
    , ^) D1 ]) b. y* D# |. g+ p        android:layout_toLeftOf="@+id/CameraCapturePanel"+ c" ?! \/ ^8 h  ?+ H9 ~1 E( Q
            android:gravity="center"
    * u# e$ y- j" H- R; Y        android:layout_height="263dp") M1 p7 v" {, s0 d+ o, T
            android:visibility="gone"
    % w' n1 a+ Z+ V. o6 t7 y( W- h        tools:ignore="RtlHardcoded"/>
    5 v, i+ T1 z6 k    dji.ux.panel.CameraSettingAdvancedPanel
    ; m5 @% d9 F' T        android:layout_width="180dp"- @" R; Z% n% ?8 o7 C8 @: a/ d9 Q% O
            android:layout_height="263dp"
    % E1 c# v6 p& _& j6 T# M  `, E3 I, r        android:layout_below="@id/camera"
    4 k, U5 }, G  Z9 X  {: V0 E        android:layout_toLeftOf="@+id/CameraCapturePanel"
    7 G3 o5 J, T& Q0 _  x: w        android:gravity="center"- m# `$ G& F$ G$ w! t7 v1 ]  B
            android:visibility="gone"
    3 [$ |" z4 k6 ?) w. b8 k        tools:ignore="RtlHardcoded"/>
    & |  e5 V/ Q, C$ z    dji.ux.panel.RTKStatusPanel
    * Z; D, e8 ^5 `6 V3 T/ P        android:id="@+id/rtk_panel"# Y  _; |7 k9 u
            android:layout_width="500dp"8 E5 ?/ q9 l/ p) I) z
            android:layout_height="350dp"
    ( Q4 f! v( m& p. |) s% @" x        android:layout_below="@id/signal"
    8 E7 W# e8 d1 r4 H6 z/ }        android:gravity="center"& s$ x  q* A" {( D$ [
            android:layout_centerInParent="true"
    : m2 j; ~7 I& E9 m2 W, U$ _        android:visibility="gone"/>' P) @7 h1 E7 B# T4 U( i- A
        dji.ux.widget.ColorWaveformWidget
    1 D4 q& _! l2 D  W! o0 }$ R% D: k/ T        android:layout_width="394dp"  \: l% Y) v8 P) I2 c2 `8 u
            android:layout_height="300dp": j, _) p7 F2 H4 i. z! V! t
            android:layout_below="@+id/camera"4 z/ k0 K( M5 \- i8 D
            android:gravity="center". n4 I) y1 G/ U: k
            android:layout_centerInParent="true"! a4 H0 t  H6 \2 B8 a6 g+ n0 e
            android:visibility="gone"/>" w6 v( q% Z1 r0 j
       
    : G% f3 T4 N( C; h6 h8 C    dji.ux.panel.PreFlightCheckListPanel
    & v' I& K- K# l3 m, F& t8 C        android:id="@+id/pre_flight_check_list"
    : B# h% ?, M+ I; S2 p1 t# I" Q        android:layout_width="400dp"6 I4 O. z2 l0 ]$ Z( }/ z+ L
            android:layout_height="wrap_content"! K) j3 @' A8 Y" W3 N& h0 S
            android:layout_below="@id/signal"
    ) {+ Z1 v6 p8 [        custom:excludeItem="ESCStatus"3 V7 A' ?3 B; y: i7 L
            android:visibility="gone"/>
      k, e6 b9 r& b8 V    dji.ux.panel.SpotlightPanel
    . c2 ]. I# i+ u; M& t7 Y: v6 ~* I        android:id="@+id/spotlight_panel"
    8 a: V3 l, _! O" g8 Y        android:layout_width="300dp"
    ! `2 i, c5 Z/ k& S& h5 U        android:layout_height="wrap_content") E3 J6 |" U. A4 V+ H$ t+ N) z
            android:layout_below="@id/camera2"
    # [! j7 Y/ `" v& q* n  S& N3 l        android:layout_alignRight="@+id/camera2"
    - }- r6 r+ J# }! x        android:visibility="gone"
    9 ]* i8 U1 I6 g! m( w8 j' }% I        android:gravity="center" />
    1 [% Z( y0 N& u    dji.ux.panel.SpeakerPanel  R( ]( [; D; A5 `
            android:id="@+id/speaker_panel"
    0 F7 n- W2 ?: c! b* F! a% Z( h. ^        android:layout_width="300dp"+ G3 V7 z& r) ?, L0 m! Q  x
            android:layout_height="match_parent"2 J# k2 |, Q# m# \
            android:layout_alignParentLeft="true"
    : n8 J! |: ]( B$ U. b% H+ ~) e        android:layout_below="@+id/signal": z1 z8 X1 r( {- K! z% ]6 i$ o7 H" @
            android:visibility="gone"
    / P2 `- E* y+ `* N( T        android:gravity="center" />
    % c) [( |; E$ jRelativeLayout>
    + H& {1 I3 R6 A- o) U: M, Q, P* z@Layout(R.layout.activity_main)* f! g$ `+ Y6 l* Q
    public class MainActivity extends BaseActivity implements View.OnClickListener {# {0 K3 Y& c2 x* m  U  _( ~
        @BindView(R.id.img_live)4 f* g. c" K5 z7 q
        ImageView mImageViewLive;
    9 Y  ~/ N7 W& B4 g    private MapWidget mapWidget;" L7 [0 d7 G5 s7 w. U. I
        private DJIMap aMap;. O0 f/ m% R4 M0 E9 ?, `3 ^
        private ViewGroup parentView;$ s* ~' j. m) C/ M
        private FPVWidget fpvWidget;
    1 b2 c( D* O# |    private FPVWidget secondaryFPVWidget;5 e( s& W5 X8 c6 p
        private RelativeLayout primaryVideoView;. y( ?+ E, Z0 o, f8 ?
        private FrameLayout secondaryVideoView;
    . R9 K4 W$ [) [# H) l. q    private boolean isMapMini = true;! A% N- ]$ g/ D0 D1 V+ Y
        private String liveShowUrl = "";9 K, H( a. S. O  W+ B8 B) ~" m! N
        private int height;, n$ r$ l4 c3 d4 |" T" f# z3 j( S1 b
        private int width;
    8 u9 y8 o# [9 _( o8 l% c4 L    private int margin;
    9 G5 E. A( E8 o/ e    private int deviceWidth;1 m& R7 Q& @4 T8 H, v% e* P7 q
        private int deviceHeight;$ Q* f8 b' X* n. f6 b
        private SharedPreUtils mSharedPreUtils;, [. m/ n# X9 y% B
        //unix时间戳9 u' P1 S' X2 m4 G- w+ i- J
        private String dateStr = "";# X6 q! o6 X! M
        //飞行器管理器
    # ]2 o8 J( b; G$ U: W3 [    private FlightController controller;
    3 l* f- Y* V- \  K& W5 m; P  s2 c    //经纬度
    ) s! s" t9 x" |. ~    private double lat = 0, lon = 0;
    2 `2 \' M3 ?) l. O4 z    //高度
    7 h* W7 e& X9 G2 A/ _( I    private float high = 0;  I5 [) q% u. B2 ]7 o8 }
        //飞机的姿态4 m1 ^/ v; F1 p7 c, R1 ~5 I- t
        private Attitude attitude;
    . h7 \7 I7 E5 ?7 R    //俯仰角、滚转、偏航值2 W0 j  _0 v8 d
        private double pitch = 0, roll = 0, yaw = 0;
    ) |9 x# P2 R& p1 e* ^: B    //飞机的速度
    6 C, u! k2 @' b' z3 `. u* R    private float velocity_X = 0, velocity_Y = 0, velocity_Z = 0;
    2 o9 r3 Z% s; p+ U$ W9 y( ?4 R    //飞机/控制器电池管理器" u: L9 o% E0 B# g# p$ J
        private Battery battery;- D& `6 O$ n* O" p. ?
        //电池电量、温度5 [, G$ c( p; P7 E
        private int power = 0;% I! ?6 F' p3 y" v. ]$ ?
        private float temperature = 0;* F0 Q8 [3 H5 P, U
        //云台管理器% h/ y* x! @; ^) c2 ?3 S& L' E
        private Gimbal gimbal;8 m/ K+ w  l. q- ?# l
        //云台的姿态
    8 g# ^: c* }% K" M( ^, E    private dji.common.gimbal.Attitude g_attitude;
    2 e" H8 W+ B6 l: N. g- `    //俯仰角、滚转、偏航值
    + Y* g4 j& E' r    private double g_pitch = 0, g_roll = 0, g_yaw = 0;) R/ C* ^$ z( @
        private Camera camera;: ?# D  ?8 \  M0 U4 g  y
        private List lens = new ArrayList();5 f1 i7 f" O; Z* D) Y( f
        private List djiList = new ArrayList();
    * P" n1 B1 I4 \0 G7 L9 D( U    //手柄控制器
    ! a: Y9 D+ m0 i; B! `% z    private HandheldController handheldController;0 I- S/ E+ A7 u7 J
        //手柄电量
    ; d' P! f( m! H    private int h_power = 0;
    " l4 H" P% t  I& j- F    private static List list = new ArrayList();
    + {0 g0 q# m7 ~' |; h/ c    private static List getList = new ArrayList();
    $ \% a. `" m4 @/ t, x0 S2 n    private MediaManager mMediaManager;
    4 @5 D# `+ U0 v7 E9 W$ O# ], x3 W3 U* C    private MediaManager.FileListState currentFileListState = MediaManager.FileListState.UNKNOWN;; W- Y9 P6 L- N# U) s; Q! J
        private List arrayList = new ArrayList();3 C8 |4 u, g' H
        private List startList = new ArrayList();" B& F; P' j+ ^8 X+ M/ n1 x* v
        private List endList = new ArrayList();6 \" `1 w- K) I
        private boolean isStartLive = false;2 B- b+ U3 N& C- ~- U4 B
        private boolean isFlying = false;  k, u* a0 p7 Q" W
        private boolean start = false;
    ! m/ s& _" y* w% q4 n6 V    private BaseProduct mProduct;
    - t8 `7 B2 m( |9 R    private String posName = "";: g" c' w' D- [1 Q, @5 f
        //webSocket
    0 ]& w, k% @9 S! ~& f1 S    private JWebSocketClient client;% l& G! N. f7 K" R) g
        private Map params = new HashMap();
    8 w/ e- F* i( S0 b    Map mapData = new HashMap();
    - g6 M% Z$ D! G    @Override. ^  o) w/ z/ `# l' H% o5 r3 F
        protected void onCreate(Bundle savedInstanceState) {3 z7 ]5 q; S# I
            super.onCreate(savedInstanceState);
    : k9 v" W" a' B) w. x9 t        height = ToolKit.dip2px(this, 100);
    2 m& N: V, V+ L' V$ F+ K& \; U        width = ToolKit.dip2px(this, 150);- U0 A. s8 Y% |+ z- ?5 I
            margin = ToolKit.dip2px(this, 12);) y6 f  n4 `0 O
            WindowManager windowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
    # @7 O. f& J5 O$ m7 `6 D        final Display display = windowManager.getDefaultDisplay();
    / Q1 {; O' i$ _) p" \        Point outPoint = new Point();
    # e. _) ?. a! {5 a        display.getRealSize(outPoint);/ M, L2 U" s+ [' u0 Y, C
            deviceHeight = outPoint.y;0 `- l' O, C' u
            deviceWidth = outPoint.x;& Z! J- u$ r& H& s
            parentView = (ViewGroup) findViewById(R.id.root_view);
    ' ^) f; X: _5 O5 c4 \) x        fpvWidget = findViewById(R.id.fpv_widget);% V; G5 B' F8 t3 `( ]  O
            fpvWidget.setOnClickListener(new View.OnClickListener() {
    3 T/ ^( v- f5 |$ x  L0 e/ c. B            @Override
    / ~8 J8 l! o5 r* f$ K            public void onClick(View view) {0 [' d& ?2 `! e2 M4 c$ O- g
                    onViewClick(fpvWidget);
    * Y+ F7 D6 U6 h( C+ Q3 J) \/ l. Q            }5 |7 }* w3 C/ r% L8 s
            });7 U& ~- P# z5 x- h5 Q
            primaryVideoView = (RelativeLayout) findViewById(R.id.fpv_container);! s( ^. }$ B1 P
            secondaryVideoView = (FrameLayout) findViewById(R.id.secondary_video_view);' @: w3 O. O! O6 |2 W
            secondaryFPVWidget = findViewById(R.id.secondary_fpv_widget);+ @4 Q2 I% K" n9 Y* P7 p
            secondaryFPVWidget.setOnClickListener(new View.OnClickListener() {
    1 D. K# ]2 Q$ S$ v+ T            @Override1 o: b$ D3 M, S) ~' h3 A
                public void onClick(View view) {
    1 N% b- {* T) E4 n. x# B                swapVideoSource();6 n" w9 Y3 j2 B& f: T6 T$ K, x
                }, U1 q4 c* x& W% d" G/ Q) Z
            });
    5 j* R- w! ]# ~6 |  w( f        if (VideoFeeder.getInstance() != null) {
    % u5 P" i3 z# k+ o8 a! ?- a            //If secondary video feed is already initialized, get video source/ z: ]+ `3 s8 X8 w
                updateSecondaryVideoVisibility(VideoFeeder.getInstance().getSecondaryVideoFeed().getVideoSource() != PhysicalSource.UNKNOWN);- s$ v, Z& o7 C
                //If secondary video feed is not yet initialized, wait for active status
    / m! O4 Z' c( O* s: g1 R: r            VideoFeeder.getInstance().getSecondaryVideoFeed()
    2 j( c9 l; w' g% o4 U                    .addVideoActiveStatusListener(isActive ->: o1 g( V1 \, e
                                runOnUiThread(() -> updateSecondaryVideoVisibility(isActive)));/ v% `0 w4 D+ h9 n
            }
    $ [  r% ~# X2 z- B7 w        mSharedPreUtils = SharedPreUtils.getInStance(this);
    1 j& ^* ^) @. |3 h2 B, V: H$ T+ I        this.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);& a; z$ E4 P; L# y/ O; ]: V
            mapWidget = findViewById(R.id.map_widget);8 M- U; b' O. h* V* q6 _
            mapWidget.setFlightPathColor(Color.parseColor("#2fa8e7"));
    $ K4 \8 @. `6 Y  Q        mapWidget.setFlightPathWidth(15);
    # n- y, E0 G* c2 w. N/ Y" k        mapWidget.setDirectionToHomeVisible(false);
    9 ~+ w' @2 |1 m        mapWidget.initAMap(new MapWidget.OnMapReadyListener() {
    ! Y3 @7 ]$ G: c6 g$ ]7 C" c8 C            @Override
    3 f# n% d2 g) V            public void onMapReady(@NonNull DJIMap djiMap) {
    % Q% ^6 v6 z# ]. G$ q$ z                djiMap.setOnMapClickListener(new DJIMap.OnMapClickListener() {4 j4 k  U$ m- @: M* w# q" X
                        @Override
    0 Z" b( V* E% W: q6 @                    public void onMapClick(DJILatLng latLng) {8 c1 g) {( X' e( I0 I- V
                            onViewClick(mapWidget);
    5 B2 c4 C9 @" T# c& P                    }1 s) d! h* k' n
                    });/ O3 ], S7 @# Z0 G: [  p
                    djiMap.getUiSettings().setZoomControlsEnabled(false);
    # V" O+ w/ t0 ~* ^; d" q) s' M            }
    % q# `8 A9 G( d  l( s        });- X3 g/ i1 z/ L7 U0 P
            if (aMap == null) {' b6 r4 x( q" @  r+ N6 W* ]* f9 O
                aMap = mapWidget.getMap();
    : k  u% f5 Z4 S( C  ^$ E- c        }4 n$ i! M: f: L: V( g6 s
            mapWidget.onCreate(savedInstanceState);
    / U+ S& O5 N3 I4 i, c$ m        mProduct = ReceiverApplication.getProductInstance();% F2 B- J, d3 S/ q3 X0 _
            if (null != mProduct && mProduct.isConnected()) {
    ' x6 R& k8 j! m% j8 P- u# V" {" W& X            flyInformation(mProduct);
    . i2 q2 J7 T; b' b  f, k% A, V            batteryInformation(mProduct);; \6 x" s/ P; w5 y: y) x9 }0 Y; E
                cameraInformation(mProduct);
    " `( P8 C, L6 s) X7 T- E            camera(mProduct);. J. W# n/ a' S
            }
    8 Y: {6 J8 _+ G        Timer timer = new Timer();# c9 o: p( W& M! O
            timer.schedule(new TimerTask() {% K0 u) j4 r8 P. S
                @Override
    7 Z) T$ x) m: g            public void run() {
    8 {1 V: k9 y9 y4 q" e8 x+ }' q8 [4 T                Message msg = new Message();  Q& {: z1 P% ?6 e/ A6 |
                    if (isFlying && !start) {
    ; E: q! s: x% b7 r. h. ]                    start = true;
    / A  F% t- K! R4 a$ l) i( R                    
    # P  E0 q* R8 N( D0 g2 t1 F3 V            
    2 W, C8 R6 ^! m                }
    ) ]# i& S; S4 F                if (!isFlying && start) {& @6 }* {! [1 Y( Q
                        start = false;0 q) R" i, ^- H6 Z; {$ P! C
                  
    6 ?) l, Y! V/ n2 X8 F                }
    1 v  g+ e+ ]& a. }* J9 c                if (isFlying && high >= 0) {
    ) k% {2 ?2 \# H% t% k- \8 p$ m                    msg.what = 1;
    & K8 V. A1 w# l, o  ]# @$ ?; E2 K                }
    ' b, f& r$ b  _4 R* e                mHandler.sendMessage(msg);
    , r; {* D7 Y. X$ ^) Y. V- V# Q            }' o7 U: a4 b9 Q
            }, 200, 200);
    ! ~7 |1 M5 ^; ~8 E    }! `: _8 A  D* `3 ?5 a+ H
        Handler mHandler = new Handler() {
    + P# u" C( l) A9 u! n5 F5 f        @RequiresApi(api = Build.VERSION_CODES.O)
    : E3 L9 l+ M  u3 V) [        @Override8 L) @* c: p) r$ r6 i% ]4 K
            public void handleMessage(@NonNull Message msg) {$ @- {" s/ r3 N5 U: `/ w0 J+ E- e, A; G
                switch (msg.what) {1 }( {7 _* q3 d$ i" [
                    case 1:
    / a$ D) K+ M$ m! ?* }* {% o  w" d                    Long time = System.currentTimeMillis();
    5 o* `9 B, I* T//                    MyLog.d("时间:"+time);% M4 G3 u/ J  X7 J! q" K
                        RecordModule module = new RecordModule(String.valueOf(projectId), String.valueOf(planeId),5 J* x) Z0 u6 v8 f! w  P
                                trajectoryId, time, String.valueOf(lon), String.valueOf(lat),+ c7 i6 ]0 _% c2 m1 f2 s
                                String.valueOf(high), String.valueOf(yaw), String.valueOf(pitch), String.valueOf(roll),
    / y* S9 m( J. w  _6 C* N                            String.valueOf(""), String.valueOf(velocity_X), String.valueOf(velocity_Y),( K4 V: r/ R4 z$ z: R- d3 m
                                String.valueOf(velocity_Z), String.valueOf(g_yaw), String.valueOf(g_roll), String.valueOf(g_pitch));, |& x7 a0 C+ R- e1 k
                        http.getHttp(INSERT_DATA, GsonUtil.GsonString(module));
    0 b, P2 Z3 a' m! B3 D1 J                    break;! ^: |2 D6 n/ v! Q. f$ w
                    case 2:
    # Z# x0 ~- f# J! ~; c. t                    MyLog.d("飞机移动的数据:"+msg.obj.toString());& a+ Q( ]$ h" M7 F8 j
                        ControlModule control = GsonUtil.GsonToBean(msg.obj.toString(),ControlModule.class);
    % ~* ]2 A) ^4 C  U1 ^) ]0 h) ]                    if (controller!=null&&isFlying){* A" q$ V  i  K$ z
                            if (control.getContent().isBack()){
    / G* J0 q9 m0 S2 K3 P                            controller.sendVirtualStickFlightControlData(new FlightControlData(-10,0,0,0),null);0 ^$ r% Z7 Z9 q, g7 D
                            }
    & p3 Y# s, ]+ j% x2 ?- q0 L5 i                        if (control.getContent().isFront()){
    * `4 j# O/ }2 y$ u* ~0 v                            controller.sendVirtualStickFlightControlData(new FlightControlData(10,0,0,0),null);5 x) w% ?( V8 T8 q
                            }
    ( J$ Z3 h" r6 g1 w+ m' y                        if (control.getContent().isDown()){7 h* K, R9 P5 }  E; ~* P& a
                                controller.sendVirtualStickFlightControlData(new FlightControlData(0,0,0,-4),null);
    4 T/ z/ t) d) F& h3 B                        }' t" Q1 v" h9 n3 t
                            if (control.getContent().isUp()){
    $ W" a9 h$ R6 u# k2 f- d: k                            controller.sendVirtualStickFlightControlData(new FlightControlData(0,0,0,4),null);
    3 e) h2 ]4 X3 n# u  I+ l                        }
    9 R* M* q" B6 b5 J                        if (control.getContent().isLeft()){% k: u  q2 O( j3 c2 H+ `. h5 y9 ^
                                controller.sendVirtualStickFlightControlData(new FlightControlData(0,-10,0,0),null);: t  m) x2 v, d
                            }
    - W! D' p+ ?* p, U+ Y2 _1 s                        if (control.getContent().isRight()){8 k9 `4 E% |( g& j; ]0 ?
                                controller.sendVirtualStickFlightControlData(new FlightControlData(0,10,0,0),null);
    1 ?$ v' F& `$ s" g$ }                        }: q* i: z+ |1 G5 g8 I/ @
                        }else {
    ) k* d2 P, d' @, i" d                        MyLog.d("controller控制器为空");
    ! m2 A! S1 ?/ Z- P1 J" i                    }' S& B7 ?, N: y
                        break;+ A$ L9 S0 M2 v
                }
    - O, ?5 v% c( `! I( @* ~        }) g7 A1 r) s! S' O. \
        };; D* l$ O' l9 W9 `8 C* D
        @Override
    8 E& P9 \# J" M, e3 J/ R    public void initViews() {
    , E  W5 [0 @' z+ C/ ]        mMediaManager = ReceiverApplication.getCameraInstance().getMediaManager();* w. V( q0 }$ T7 J& q& o) C
            getFileList("start");
    , ?2 X0 v/ J: I+ G    }
    9 C) H% w3 u9 Z* B    @Override
    : F  \0 F1 H: j  b5 P    public void onComplete(String url, String jsonStr) {9 i, d/ {" H  |: ^& J  ?5 Y) v( y1 {
            super.onComplete(url, jsonStr);
    ) U+ n9 W, j3 v( j" R     
    0 O8 H: g( }+ ~5 {    }
    2 L' m$ |3 l9 @$ t" S5 s5 T    @Override# U$ h" f4 z* n& }9 F+ }
        public void initDatas() {; O! U2 J8 `2 S% m3 a
        }
    * e0 e1 E- b3 i' n* A    private void onViewClick(View view) {
    0 |* E$ Z* N& I& k1 E- G        if (view == fpvWidget && !isMapMini) {. C' F; w1 P4 c5 F
                resizeFPVWidget(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT, 0, 0);
    2 C) N& I/ k6 _. t' _% e            reorderCameraCapturePanel();
    8 k+ k7 {/ U2 F5 S& r, C# @* l            ResizeAnimation mapViewAnimation = new ResizeAnimation(mapWidget, deviceWidth, deviceHeight, width, height, margin);
    # h. G( C) j/ K  m            mapWidget.startAnimation(mapViewAnimation);
    + k  B; ^8 D: b5 R! F7 E            isMapMini = true;
    . t+ O; `+ E! G7 G        } else if (view == mapWidget && isMapMini) {! ?' ^5 n# m4 T# S3 t
                hidePanels();! R6 U' g8 O! p0 R! x3 S0 n
                resizeFPVWidget(width, height, margin, 12);
    5 |" R* w7 f4 Z9 p7 g( M            reorderCameraCapturePanel();2 c4 d1 N4 Z% \3 E- P3 a+ m
                ResizeAnimation mapViewAnimation = new ResizeAnimation(mapWidget, width, height, deviceWidth, deviceHeight, 0);1 `% C$ U; X' b
                mapWidget.startAnimation(mapViewAnimation);1 S2 V6 `$ w0 z$ Q9 j8 L
                isMapMini = false;7 ^$ n, M% T% u* D( h
            }
    ; ^8 S0 d/ g5 `: v' [  e1 U    }4 j+ p2 H) p- a2 M+ I& _
        private void resizeFPVWidget(int width, int height, int margin, int fpvInsertPosition) {
    2 L4 a9 e  S7 W& {& r# o7 q# z        RelativeLayout.LayoutParams fpvParams = (RelativeLayout.LayoutParams) primaryVideoView.getLayoutParams();
    + `: p4 y% u) x' x' }2 j1 ?* `        fpvParams.height = height;
    1 S0 A0 U& E& m4 I) O2 D        fpvParams.width = width;/ K( B4 B' c! L. k* G0 [7 I
            fpvParams.rightMargin = margin;. d" f/ U& l' z# @2 L9 I; W" u/ I6 }
            fpvParams.bottomMargin = margin;0 ]7 H2 A% w" n' w1 n8 q
            if (isMapMini) {- ^' @3 A  Z6 {+ c" O" F7 C
                fpvParams.addRule(RelativeLayout.CENTER_IN_PARENT, 0);
    , t6 |7 A. M7 z            fpvParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT, RelativeLayout.TRUE);
    ! h8 u  P2 R. |3 f' g0 ^  `            fpvParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, RelativeLayout.TRUE);
    6 g. Z# ~5 e! t# D" Q- o! z! p8 v        } else {
    - l! C; V3 s2 i# x            fpvParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT, 0);
    & Y' m6 s7 w1 A' L6 h0 W3 G            fpvParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, 0);5 x* ]' ]# G, X- V
                fpvParams.addRule(RelativeLayout.CENTER_IN_PARENT, RelativeLayout.TRUE);6 ]/ L4 d7 u5 L
            }
    7 L! Y7 J; f& {; H, ]; a        primaryVideoView.setLayoutParams(fpvParams);+ w( g8 }! `8 R# N6 ]
            parentView.removeView(primaryVideoView);/ k5 F: v! r$ ^: }/ T3 @8 \
            parentView.addView(primaryVideoView, fpvInsertPosition);; h$ a6 _- u7 |; j4 e
        }* N" D3 @; w6 T, w- x3 x. h0 S
        private void reorderCameraCapturePanel() {
    5 N( d! C0 a! X! u        View cameraCapturePanel = findViewById(R.id.CameraCapturePanel);8 u% F2 m( z* D0 ^& i; u# D* }
            parentView.removeView(cameraCapturePanel);
    7 ]3 ^: m3 U' u1 |2 d1 y        parentView.addView(cameraCapturePanel, isMapMini ? 9 : 13);( l+ r! m% `, ?
        }
    1 S' x. R9 J  ^- ]# W* a    private void swapVideoSource() {
    $ R2 A% _" R: Y' ~        if (secondaryFPVWidget.getVideoSource() == FPVWidget.VideoSource.SECONDARY) {
    7 i/ R& }3 h$ n2 W7 c            fpvWidget.setVideoSource(FPVWidget.VideoSource.SECONDARY);  F% W8 E- R; Y5 G8 e/ A
                secondaryFPVWidget.setVideoSource(FPVWidget.VideoSource.PRIMARY);
    ) k* l/ |& E+ h* U" d        } else {
    . e+ t  G) W/ G            fpvWidget.setVideoSource(FPVWidget.VideoSource.PRIMARY);! ~: w0 ^5 M( i
                secondaryFPVWidget.setVideoSource(FPVWidget.VideoSource.SECONDARY);
    ) R- w- Y+ V9 s( q: C) R3 U        }
    $ H! m3 I1 p, Q) I- P/ G, e; V& y7 U; M    }
    1 I: |9 P/ D5 _( _. }, L  s- h: [    private void updateSecondaryVideoVisibility(boolean isActive) {9 s( d0 S) p/ h
            if (isActive) {
    9 N: }6 D! s" l6 S1 R& @( ^4 F            secondaryVideoView.setVisibility(View.VISIBLE);# _/ v4 v4 [8 Q" w3 U
            } else {: q7 H' k' m2 x5 [- \
                secondaryVideoView.setVisibility(View.GONE);- N1 g. i% C' g6 o( `
            }
      t/ k& i  P) H! X1 m    }+ `$ C) R6 v8 U" ]3 z
        private void hidePanels() {, O1 d, T1 D% G) o+ d( L- q
            //These panels appear based on keys from the drone itself.
    2 K7 I+ {0 I/ Z        if (KeyManager.getInstance() != null) {0 M0 |) N8 Q5 h; X
                KeyManager.getInstance().setValue(CameraKey.create(CameraKey.HISTOGRAM_ENABLED), false, null);
    . Q& H0 ?/ L3 [            KeyManager.getInstance().setValue(CameraKey.create(CameraKey.COLOR_WAVEFORM_ENABLED), false, null);8 V( g0 _5 H6 {$ N& E! M; U+ [; `
            }: K. B) j; L; r4 ^9 i
            //These panels have buttons that toggle them, so call the methods to make sure the button state is correct.3 O+ V9 I8 j" q+ {
            CameraControlsWidget controlsWidget = findViewById(R.id.CameraCapturePanel);/ v$ N) i" B/ i# f5 X$ h
            controlsWidget.setAdvancedPanelVisibility(false);7 A9 D% C2 S- g. d5 z+ M
            controlsWidget.setExposurePanelVisibility(false);
    # f. {1 y; I, w7 Z2 u        //These panels don't have a button state, so we can just hide them.1 p! b8 h. Y" `5 ^
            findViewById(R.id.pre_flight_check_list).setVisibility(View.GONE);2 O0 ], P; `. E7 e- G. j  {  l% j
            findViewById(R.id.rtk_panel).setVisibility(View.GONE);+ j: a. l. F/ t0 Q) \& _* |
            findViewById(R.id.spotlight_panel).setVisibility(View.GONE);5 w6 i  p1 u6 I) |! }$ }# I
            findViewById(R.id.speaker_panel).setVisibility(View.GONE);
      g4 O& D* P  C    }
      r7 ~0 K, r# Z4 i0 d    @Override
    5 R5 }4 R& N& a! \, R- Z    protected void onResume() {0 j$ U$ L* M' z4 d0 m2 Q$ \  B- d6 {
            super.onResume();# v5 S* _3 Y; E
            // Hide both the navigation bar and the status bar.
    $ E4 q) ?. E6 c" `        View decorView = getWindow().getDecorView();
    " ?. C$ Y  C$ a5 F        decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE
    " w0 i# U/ G3 P: ~* H# t% X2 D                | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
    2 w( `1 L, Y( @! U+ h3 u/ |9 Z                | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN! j- m( ^/ e9 z, w
                    | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION( _0 `) h& u3 F6 W
                    | View.SYSTEM_UI_FLAG_FULLSCREEN
    ) v( `; X- Y0 e# E( a+ B* d                | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
    3 V4 C/ T' ?+ e6 h! l6 o* }        mapWidget.onResume();
    3 j$ f& {6 d8 t  c$ {% o        if (client == null) {6 J" c6 K7 z* u: I, G# i& B
                MyLog.e("``````````````````````onResume");
    ( b6 r2 r0 i* E//            initWebSocket();
    % c( ~8 b. S+ X# o% m. A6 n+ E        } else if (!client.isOpen()) {
    0 z8 j( @+ d- B. [2 L& z( N0 x" L            reconnectWs();//进入页面发现断开开启重连: h0 n" h' z$ h& g
            }( C8 O! W( N: S. e6 ^$ {9 u
        }
    2 w4 A. F3 L0 w7 Q    @Override
    ; S7 V: p. [, z' O. h* z6 g    protected void onStop() {% P5 \& f# c1 v; p
            super.onStop();
    / ?8 Z+ z4 e% Z# {        MyLog.e("``````````````````````````````onStop");
    + U7 j* g6 Z4 D( @9 d( c' |/ I    }8 p8 |" ]) G, `1 T, O9 o
        @Override
    $ T' c$ U3 [& l3 h' H+ p) e    protected void onPause() {
    ! G' a5 P+ z) |  X9 n* g        mapWidget.onPause();. }0 g2 c- C; o8 b3 U4 C* P; H$ q
            super.onPause();0 C+ T- D# d1 U9 a$ b) n2 V
        }- \) z3 n5 r+ B* V1 D: Z# i5 r! L
        @Override
      R4 m  F( R. n. |    protected void onDestroy() {' B* H: @# ]6 c7 c' J8 G  I$ v
            mapWidget.onDestroy();
    4 Q$ M0 J$ T- g! t$ b6 r. W        super.onDestroy();
    , ?/ _! @  l  F' F9 t, Y9 c7 j! G+ G2 d        MyLog.e( "`````````````````````````onDestroy");9 q: K) l* R2 A1 v7 t
            closeConnect();
    : ], P, i8 t' ?5 ?    }
    4 \1 r) [5 g. v) N4 [9 i    @Override
    - g1 ~! g$ `: \2 H1 _    protected void requestData() {
    : W- [! M7 `+ w- k0 }% j, s    }
    " b- `3 y5 e( o    @Override
    $ Y1 `( p1 X, u! ?9 a* P9 X    protected void onSaveInstanceState(Bundle outState) {
    " g. A. L/ F& n( Y5 T2 m        super.onSaveInstanceState(outState);8 [& l  u8 y$ J5 t6 Q7 V- W
            mapWidget.onSaveInstanceState(outState);: p4 @5 v8 @  J. E" `1 Q
        }
    1 C& |: {' Q6 l    @Override2 V! g2 z' V, n9 U. b
        public void onLowMemory() {8 t9 a6 I& R; N$ W
            super.onLowMemory();
    1 A* N& i; `& s- Y        mapWidget.onLowMemory();; L9 ?4 m* c4 \0 r9 K3 G8 C$ v
        }
    ' F. X3 w+ ?3 [, W    private class ResizeAnimation extends Animation {8 o) j  \9 ~( V
            private View mView;
    " k2 _' T' M7 d5 Z6 \9 B  D        private int mToHeight;* {9 `. ?* Z7 H; }# l& i# G* v
            private int mFromHeight;
    / E! c% e" ?# z+ s6 _! i4 X        private int mToWidth;3 `; Q$ L& \9 t
            private int mFromWidth;
    & H8 h) N) A# ^/ C. m        private int mMargin;
    2 P+ G% s; y5 S7 ^        private ResizeAnimation(View v, int fromWidth, int fromHeight, int toWidth, int toHeight, int margin) {
    " o2 }+ X# W) `' L( M            mToHeight = toHeight;
    9 M7 A. k% j) j3 j            mToWidth = toWidth;7 o; C# j7 b- S
                mFromHeight = fromHeight;& c1 p1 m2 j5 L" A/ a
                mFromWidth = fromWidth;% G( P2 ~0 _1 L. v4 y3 s
                mView = v;
    ) G7 m( `3 V- V& w1 O            mMargin = margin;
    * f% m& ^5 X- n2 _4 \; F5 r            setDuration(300);$ Y: q- d4 K4 t0 y
            }7 a3 f$ `2 a  E3 _1 s
            @Override/ F9 n8 n# Y, E4 {
            protected void applyTransformation(float interpolatedTime, Transformation t) {
    ! I. v6 U* B+ ^: v0 ?            float height = (mToHeight - mFromHeight) * interpolatedTime + mFromHeight;+ a1 U4 o) G2 R3 p
                float width = (mToWidth - mFromWidth) * interpolatedTime + mFromWidth;5 k5 l# f3 Y' d6 d, F; k! I
                RelativeLayout.LayoutParams p = (RelativeLayout.LayoutParams) mView.getLayoutParams();' L8 V; E* g% m  V$ o
                p.height = (int) height;
    7 k; h) m0 ^8 f; _% Q$ h            p.width = (int) width;
    - v9 P( n, I% i* {* m2 p            p.rightMargin = mMargin;- p& F5 I/ b+ N) x9 V
                p.bottomMargin = mMargin;
    % A+ Z  w! h8 M            mView.requestLayout();% ~; g9 K9 A" \. e- c; q, c
            }% z1 F" c$ T4 C/ I( P
        }3 z5 k6 g+ O) a* p+ W& U

    ! J, _# q& e1 x8 s* X# P    //直播流推送
    ' d9 @6 Y% J1 j1 ^% D    @RequiresApi(api = Build.VERSION_CODES.O)
    ' g8 H/ \% R- V" z9 @2 {: W: W0 N    @OnClick({R.id.img_live, R.id.img_show_back})
    ; R* @9 h2 ^; |; g: e7 q" B& K. w    @Override0 a! n1 \  o7 B( X/ p1 C
        public void onClick(View v) {6 J+ y; M! a1 {: R. ~- R, R
            switch (v.getId()) {, a" h& p% f. a( j: ]& _: A
                case R.id.img_live:
    / g  C- x7 q9 \) G$ ~6 n9 x                params.clear();
      V4 H% G; g% ]5 T, ?) N                mapData.clear();/ @9 n" K1 Y: ]9 h, c3 ]
                    if (!isStartLive) {
    ; z& @( t" ]9 M9 \9 i1 L% D- t! U                    if (!TextUtils.isEmpty(mSharedPreUtils.getStringSharePre("rtmp_url"))) {3 I1 n& F" I' w$ {& F, _; e1 G
                            liveShowUrl = mSharedPreUtils.getStringSharePre("rtmp_url") + trajectoryId;
    ( k/ E6 |( j, g7 ]' z//                        LiveModule module = new LiveModule("liveStreamStateChanged","plane",planeId,true,trajectoryId+"");
    % c2 ~, x( j7 U* c$ e! \                        MyLog.d("地址:"+liveShowUrl);+ N! `" U" M6 X# _! P! l
                            startLiveShow();7 Q* z# T7 j% D+ J. H
                            isStartLive = true;  c' @6 I0 J- \* T
                            showToast("开始推流");) N$ o" Q: ?9 A! T8 C% M/ o
                        } else {8 F; @3 B0 r$ j5 v' ]7 H3 ^0 K
                            showToast("请先进行系统设置(RTMP)。");
    : x# \2 u: S$ U* |( n1 b9 E; S5 Y                    }
    ) R& G$ }! \+ B. T7 ?1 t9 m; i# R0 y                } else {5 Z" _5 q% n& P+ q. F; r7 |
                        stopLiveShow();
    - v; O+ L* Q) [" m- V6 E& j                    isStartLive = false;! |/ c6 Z; ^' b2 D
                    }
    5 M0 N% f+ `5 i1 k3 a7 ?+ m) Y                break;9 p7 L$ ^2 e, V/ e/ o( J3 r
                case R.id.img_show_back:
    # G4 }' l4 b8 {. G% M- E//                controller = null;% y( J5 u3 u: B/ _; S
                    closeConnect();
    # Q. g  a& P- F0 T. e$ ]                MainActivity.this.finish();4 Z" g" i9 W/ {% D5 e% }4 U( \
                    break;
    8 R2 g3 T! [; @0 C0 D/ X        }/ c; }2 D6 F' f( W, J
        }
    / _' z* T+ ^. ]& e    private boolean isLiveStreamManagerOn() {7 }" C" V" w& `3 A. a8 W
            if (DJISDKManager.getInstance().getLiveStreamManager() == null) {6 X  E; }, [' k0 s2 {6 p
                return false;5 t% `& h' F" U* r
            }8 ]. M- t# n5 j4 A
            return true;
    7 N) f; ~9 O* |2 t% e' f    }& b# Q. j6 ?+ A/ A' v
        private void startLiveShow() {
    , E6 }9 M' N& X3 D4 X2 ?0 R        if (!isLiveStreamManagerOn()) {+ T" ]( Q" q/ H
                return;; `: R2 O4 W: ^) \
            }8 b" V1 A3 X: G
            if (DJISDKManager.getInstance().getLiveStreamManager().isStreaming()) {
    + k+ U/ g- \# B) {- `3 C% q            return;( Y; S1 B8 e6 g$ c( S
            }
    & s' I  |0 Z2 A: P" Z5 `5 V2 B( k        new Thread() {
    9 u% c6 W) y$ R* J  e            @Override
    8 _7 Z+ B7 n! o, I            public void run() {  C1 d8 X- s/ n0 N* j! y
                    DJISDKManager.getInstance().getLiveStreamManager().setLiveUrl(liveShowUrl);
    : E" @+ i- p! {4 W- p) j8 W                DJISDKManager.getInstance().getLiveStreamManager().setAudioStreamingEnabled(true);$ _0 U* U4 T" K! A, U2 b) g
                    int result = DJISDKManager.getInstance().getLiveStreamManager().startStream();, u1 e2 d, [! m/ y' M- Z
                    DJISDKManager.getInstance().getLiveStreamManager().setStartTime();3 k6 W: R% h5 _  U1 p# _$ e
                }
    , m, B! F' E, E' N0 C. x$ ?        }.start();, m+ p; O7 i( g7 a$ R
        }  i5 l) P% _1 ~* l  v
        private void stopLiveShow() {" I  n  x; x! V/ X- g" Q
            AlertDialog.Builder Builder = new AlertDialog.Builder(MainActivity.this);
    $ r0 l* i1 [, L% Z        Builder.setTitle("提示");$ D! P( g& Z" o# ^5 W
            Builder.setMessage("是否结束推流?");0 j8 S, C( b( W# P) D8 K- v
            Builder.setIcon(android.R.drawable.ic_dialog_alert);( A3 r: O6 ^; D4 M
            Builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {
    , t: l- Q7 E: w1 Y            @Override
    9 D/ g$ _+ b1 y) y4 r            public void onClick(DialogInterface dialog, int which) {/ H7 O$ M- p  t# U
                    if (!isLiveStreamManagerOn()) {4 e# X" J: B* B6 F* m
                        return;
    7 ~3 |2 t7 G" S& x7 z% C# R- V$ O8 v                }
    - p$ T9 d& `0 C                DJISDKManager.getInstance().getLiveStreamManager().stopStream();
    : `' ]2 t1 O# `2 M5 J                showToast("结束推流");
    , M( X; [0 s' P- M            }
    0 c/ q$ A9 q3 f4 P! e6 B) a, o! o        });. H3 C6 f( M/ P0 ^
            Builder.setNegativeButton("取消", null);
    ! ~5 F6 G( L3 S' c5 t5 Y        Builder.show();" ]$ ~/ v+ U& F! _% w
        }0 b# K6 f& l* ]4 \! L3 f9 p5 m- Q

    " K; y, ?0 a7 O4 T    //获取飞机信息、云台信息/ O1 t0 Z# K7 {' D8 F: E, q0 t
        protected BroadcastReceiver mReceiver = new BroadcastReceiver() {
    ' U5 k+ D/ H# H6 ~3 s1 w        @Override2 O, o+ `+ N; y  {. E0 _$ C! r
            public void onReceive(Context context, Intent intent) {( }1 G  D+ `! `9 h4 W
                BaseProduct mProduct = ReceiverApplication.getProductInstance();3 w% K+ r. s' a# @1 \: z
                if (null != mProduct && mProduct.isConnected()) {4 c& O4 \2 H) v1 m
                    flyInformation(mProduct);  V9 W5 w8 K" ]' i  M  v1 @$ d
                    batteryInformation(mProduct);  ?1 m, B, K" g( q6 b* l# G
                    cameraInformation(mProduct);
    5 Q: w7 n6 L6 ]9 D% M                camera(mProduct);% Q' y( y$ l3 g3 p7 H* w9 Z+ Q7 {
    //                MobileRemote(mProduct);
    ' J$ F% F# U3 j$ Q* c1 x1 m) O$ |            }
    4 I" ~' N( z( w7 x: ^/ y        }
    0 m( T  e% `" d+ f! L" A' A    };
    " T4 u  U5 ?, f& Z- q1 f//    private void MobileRemote(BaseProduct mProduct) {
    - u+ a8 {+ ~. {5 s# j" l! y% e( a  Z//        if (null != mProduct && mProduct.isConnected()) {
    ; S3 J2 R0 U( [; V8 R5 u4 S/ e//            mobileController = ((Aircraft) mProduct).getMobileRemoteController();
    + o$ z" [; R! P  ^) {7 g- I//        }4 Q+ x& W: S3 r% D: w1 p! `
    //    }" K! g% b4 d& c; x' e) R; W" f) t
        //获取飞机信息
    9 _- w8 E6 F4 m, v2 O. H    private void flyInformation(BaseProduct mProduct) {
    / q6 M4 j) J6 R! i  h        if (null != mProduct && mProduct.isConnected()) {" ]! g+ h  G* M# ~0 ^) ~* ?' h) _
                controller = ((Aircraft) mProduct).getFlightController();6 ?* l# y8 l8 N& z
            }
    $ X1 i" @+ K! Z; P        if (controller != null) {- _5 F2 F2 b6 p; _2 y- J/ Y
                controller.setStateCallback(new FlightControllerState.Callback() {3 J& Z" k! @2 F' q* S4 g
                    @RequiresApi(api = Build.VERSION_CODES.O)
    ( R  Y) N' j. F( V2 F& C                @Override/ s7 P# e$ n+ Y$ v$ ~9 ~5 T# X
                    public void onUpdate(@NonNull FlightControllerState flightControllerState) {! {0 [$ q4 g2 G) ?; T; C
                        //纬度、经度、高度、俯仰角、滚转、偏航值、速度: i$ r! U( {( Z2 S. ?
                        lat = flightControllerState.getAircraftLocation().getLatitude();+ }' |. k; t. S3 B6 ^
                        lon = flightControllerState.getAircraftLocation().getLongitude();
    ' V! O3 q6 ~' V+ I8 }; i# B4 A) b" G                    high = flightControllerState.getAircraftLocation().getAltitude();
    ! K( T4 b) L: ^  ?6 s                    attitude = flightControllerState.getAttitude();
    1 ~. M3 R7 s8 I                    pitch = attitude.pitch;
    & _0 k6 C- p2 o3 o. Y" {+ m                    roll = attitude.roll;, r$ k1 D* @& T/ P, m# X7 w; Q) H$ Q
                        yaw = attitude.yaw;0 L& B, b: a) J2 o6 C
                        velocity_X = flightControllerState.getVelocityX();2 t! f, @5 k2 n! A+ i. {
                        velocity_Y = flightControllerState.getVelocityY();
    3 z9 P, O/ W. R2 n3 Q: [) P                    velocity_Z = flightControllerState.getVelocityZ();
    - S* E1 K" u' j" H& A                    isFlying = flightControllerState.isFlying();& ~: ?" g& z7 G0 u! n  f
                        //                    MyLog.d("经度:" + lat + ",纬度:" + lon + ",高度:" + high + ",角度:" + pitch + ",速度:" + velocity_X + "," + velocity_Y + "," + velocity_Z);! K9 p# f4 U$ h# q9 [
                    }
    ! K3 m3 ^+ [8 O# {            });
    " z* l$ H/ _. p) j            controller.setVirtualStickAdvancedModeEnabled(true);- }3 q5 l; s8 O8 Z( V2 K
                controller.setRollPitchCoordinateSystem(FlightCoordinateSystem.BODY);
    + e; w  Y. W$ b( C  e3 G            controller.setVerticalControlMode(VerticalControlMode.VELOCITY);
    : s8 D. @' _: J4 {: l            controller.setRollPitchControlMode(RollPitchControlMode.VELOCITY);
    / ^/ u: g8 X6 N: H+ C            controller.setYawControlMode(YawControlMode.ANGULAR_VELOCITY);
      }. F: q. G4 q2 z//            controller.setTerrainFollowModeEnabled(false, new CommonCallbacks.CompletionCallback() {, ^4 x. f+ C9 V6 B
    //                @Override
    9 S5 J5 ^& o% y3 G+ _' J# C//                public void onResult(DJIError djiError) {
    ( M) k6 y" ]! p; x1 C3 x) m& \& w//                    MyLog.d(djiError.getDescription());
    3 v! a2 w0 b9 ]7 n9 ~1 _//                }, d! ^/ [+ y% ?+ g8 J) q8 B. k. d0 j
    //            });
      g: |; K0 h- M2 l  q" `//            controller.setTripodModeEnabled(false, new CommonCallbacks.CompletionCallback() {! Q/ H. x% W% T  @) O: R' N+ S
    //                @Override3 Z7 x0 s0 ^: N+ k6 K
    //                public void onResult(DJIError djiError) {
    4 r4 d' V* p% ~& Z6 _//                    MyLog.d(djiError.getDescription());
    ' h( a3 c+ \- b( _) n//                }
    3 `9 K9 W% k' R. y. [" T//            });9 q/ N% T& O6 I+ s: p. _
    //            controller.setFlightOrientationMode(FlightOrientationMode.AIRCRAFT_HEADING, new CommonCallbacks.CompletionCallback() {
    . I1 Y+ \: h* L' T7 T  f: h//                @Override
    : b2 Z. |& a6 d1 S  c8 m//                public void onResult(DJIError djiError) {! P+ O3 @  H* u* y0 U. [, S" [/ }: @, |
    //                    MyLog.d(djiError.getDescription());
    5 q0 c5 V4 K: M7 c  I, f; k//                    if (djiError==null){
    # R4 u2 a- J7 m, k5 [//                        if (controller.isVirtualStickControlModeAvailable()){  n% z+ z; H, P5 d- A
    //
    7 X: f0 S( F& \) b- a' p( A//                        }else {( A) [6 A6 ]; Y. x7 u& z
    //                            MyLog.d("虚拟摇杆模式不可用");- E+ ]' K. W  _! U* t3 s
    //                        }
    $ o: F: ~( r' C//                    }; }, E+ @- v' u  d. x+ w6 e, q
    //                }
    - N2 y7 Q" P, T2 |/ s7 |, f; D. o//            });
    - d. ~, I% a7 I3 B9 b; C        }
    $ Z3 z% J# D" p    }8 L; G4 z" B- S3 A# ^9 E
        //电池信息$ K. Q  l% Y6 B: i% w8 T" [+ `
        private void batteryInformation(BaseProduct mProduct) {
    4 O3 c  `( H: @; }, L0 e        if (null != mProduct && mProduct.isConnected()) {  ?* c3 _7 U0 O; n# }6 k; E% ~7 O( H+ N
                battery = ((Aircraft) mProduct).getBattery();5 \1 z; L/ O! a7 f2 w8 i7 N! g
            }
    ' t" Y5 m7 Y" U7 |        if (battery != null) {
    , Q; D1 W2 P8 T# L            battery.setStateCallback(new BatteryState.Callback() {* V1 O9 r6 X8 e9 X3 b
                    @Override6 |! X' x1 `* J: d0 c2 U! C! M2 `
                    public void onUpdate(BatteryState batteryState) {& v4 s1 m( }. V3 p$ ]/ m
                        //电池电量8 B$ W  ]7 }  Q# _( I7 A( M
                        power = batteryState.getChargeRemainingInPercent();8 Q) w  h; J6 F
                        //电池温度
    , R6 W2 r$ Z8 E* [0 b* U! v$ V                    temperature = batteryState.getTemperature();
    9 W# A: Q7 T6 W2 m! `4 k" m                }" q# c" G8 q  x* |' t. i
                });
    2 Q; g& p7 v9 o        }
    - a( A1 ~! W; z; D% |2 m  L* T    }
    ( Q8 V+ C1 r- e. E3 r4 K    //云台信息! \8 W/ A: e( x: o' w
        private void cameraInformation(BaseProduct mProduct) {5 q5 H1 d( E: B5 n" c4 b
            if (null != mProduct && mProduct.isConnected()) {
    4 c) |7 G/ {( T! w. W- a            gimbal = ((Aircraft) mProduct).getGimbal();
    - T' N( p: V2 M, ?$ \9 G        }! b7 l5 s6 J# P" G7 J$ z
            if (gimbal != null) {
    + N1 Z  G. \9 P6 w3 w            gimbal.setMode(GimbalMode.YAW_FOLLOW, null);
    . e3 |% _, w2 q) _( n- R6 ?4 V! w) X            gimbal.setStateCallback(new GimbalState.Callback() {
    1 k4 y8 r5 S; b  ~2 m9 y                @Override
    & ^" Y1 x1 }" J9 I" W$ O                public void onUpdate(@NonNull GimbalState gimbalState) {
    5 Q3 V! k- x" s# A' r+ i                    //俯仰角、滚转、偏航值" X- {3 m, `% e( n0 B
                        g_attitude = gimbalState.getAttitudeInDegrees();
    * q/ v) S5 F+ X/ v, }" d7 D) p, M                    g_pitch = g_attitude.getPitch();
    ; y0 ?* V4 x- U( p9 w                    g_roll = g_attitude.getRoll();' I1 N; }( V' H& U
                        g_yaw = g_attitude.getYaw();1 T4 @9 I! o' T* H' ~
                    }
    & |6 f0 s8 U2 A7 T: Q, Q* D8 v( ]            });
    5 `! G7 c! R& ~4 o        }& X7 i; U# G( }4 A# P& ?9 s6 R. Z
        }1 p9 q& t5 S, B( w/ K$ h$ w
        private void camera(BaseProduct mProduct) {
    ' S: h3 i; \4 s  ~2 x        if (null != mProduct && mProduct.isConnected()) {5 b* t4 B! m0 p: x& @
                camera = ((Aircraft) mProduct).getCamera();, L1 `6 B# R0 T& Q
            }+ g' p$ H) u2 y' B7 F$ `( Q$ q
            if (camera != null) {2 o; b% S3 h! F; r
                //            camera.setVideoCaptionEnabled(true, new CommonCallbacks.CompletionCallback() {
    4 O; f& U4 I/ ^' h2 G' F' G% r# n            //                @Override
    ! `0 g8 |7 ]' x" g            //                public void onResult(DJIError djiError) {
    , |8 Z1 p! ~% z& l" `            //                    MyLog.d("VideoCaptionEnabled"+djiError.toString());
    . B5 w. ~/ g; q9 A5 p8 R8 T- B( I            //                }
    8 s8 F1 N+ n: v0 P            //            });
    6 ~7 n$ Q7 F; i/ w4 O5 C: v8 S            //            camera.setMediaFileCustomInformation(projectId +","+trajectoryId, new CommonCallbacks.CompletionCallback() {  y$ b& t  q3 t  t# @0 K, v
                //                @Override: l" l6 n$ ~# J1 q: N" u
                //                public void onResult(DJIError djiError) {
    1 T/ ]# h7 Z% E! L' U            //                    MyLog.d("自定义信息:"+djiError.toString());0 d4 i6 X! K1 A! l
                //                }  G9 t7 C# x1 X- A
                //            });
    / j6 c( i$ `3 R" x) R            camera.setSystemStateCallback(new SystemState.Callback() {, p6 n/ e" ?3 v% y* f$ b0 \. i" j
                    @RequiresApi(api = Build.VERSION_CODES.O)% l' l2 f1 g  @( e3 Z: E% P5 v
                    @Override
    . k5 N$ T$ s) v; Y! E% U6 {                public void onUpdate(@NonNull SystemState systemState) {
    . w1 X# B3 H9 K3 o& J                    if (systemState.getMode().equals(SettingsDefinitions.CameraMode.SHOOT_PHOTO)) {
    : q5 w& o8 d) C" H1 D8 K+ l                        if (systemState.isStoringPhoto()) {2 g) c* ]/ Z3 {& G
                                dateStr = Long.toString(System.currentTimeMillis());
    . d$ Y2 M$ ~) h; c+ Z& O5 |7 R                            list.add(new DeviceInfo(dateStr, lat, lon, high, pitch, roll, yaw, velocity_X, velocity_Y, velocity_Z, g_yaw, g_roll, g_pitch));
      [0 r# k8 E; j) F# T                            CsvWriter.getInstance(",", "UTF-8").writeDataToFile(list, FileUtil.checkDirPath(FLY_FILE_PATH + "/照片数据") + "/" + DateUtils.getCurrentDates() + ".csv");
    : ^) B; B/ R4 X                            list.clear();
    ' S- c# v( a" h" h0 O/ r* w- f- E. \                            return;, V3 D8 m( Y# c* Q7 E
                            }
    ' @: m1 V2 V" A                    } else if (systemState.getMode().equals(SettingsDefinitions.CameraMode.RECORD_VIDEO)) {
    ) B$ ~/ U6 E! L2 D& [7 ]                        if (systemState.isRecording()) {; |" y# W( V' L
                                try {+ J: e1 }, O( T3 F3 b
                                    dateStr = Long.toString(System.currentTimeMillis());4 ~: d; O( ^  E% k' L
                                    list.add(new DeviceInfo(dateStr, lat, lon, high, pitch, roll, yaw, velocity_X, velocity_Y, velocity_Z, g_yaw, g_roll, g_pitch));+ K5 ?8 I& k  g
                                    getList.add(dateStr);) e' ?) [) N& K4 b' R  S1 L( D
                                    Thread.sleep(100);$ \7 j+ `" s' s) w- R; v+ F# W
                                } catch (InterruptedException e) {
    1 k6 Y7 g" i' o9 |! G# {+ o                                e.printStackTrace();
    + K5 W; x1 E) c: K  M8 z3 j, u1 u# h                            }
    ! K: s3 |. Q+ V  p/ b* v' c                        } else {
    " V, `2 V5 y) X                            if (list.size() > 1) {- R* m3 Y, e# Q9 _( v
                                    posName = DateUtils.getCurrentDates() + ".csv";
    # o  L2 F8 s& z6 Q8 |2 c3 U                                CsvWriter.getInstance(",", "UTF-8").writeDataToFile(list, FileUtil.checkDirPath(FLY_FILE_PATH + "/视频数据") + "/" + posName);
    , n: ?, L9 M7 W4 c0 y                                list.clear();
    2 A  {+ }/ Z# ~& s4 s( A                                runOnUiThread(new Runnable() {# P* P3 R& Y5 q2 V% L
                                        @Override) c6 m. l) Z' h8 T1 Z
                                        public void run() {
    / I! u0 M6 C* Z; I# M/ G( w                                        getFileList("end");. b) ^2 ]7 n1 s7 z
                                        }
      ]9 p* d  A( b: ~0 M                                });
    1 S3 J4 w% w  A' X                            }
    7 B8 o" o2 x3 [9 c                        }
    + ~; _7 ?$ b* m! e0 c                    }
    ) |7 s+ ^7 w0 ]                }
    $ I; Z  r- R+ W% o% u+ P% M6 H            });- R3 }$ ~# x  n$ s
            }) W( _9 Q' q) N: u# z: ~3 j& T- X
        }# r9 _2 o! {  j+ d. Z
        //遥控器信息4 e/ C! n0 J/ F7 f
        private void handheldInforamation(BaseProduct mProduct) {& b  p# `" H8 v! N; ^9 h
            if (null != mProduct && mProduct.isConnected()) {
    5 k# V9 t& q0 ^7 p* {( S            handheldController = ((HandHeld) mProduct).getHandHeldController();
      @/ T) U9 S  U9 z) A" ~9 J& S        }: ?$ R$ J3 J+ }, w6 G
            if (handheldController != null) {
      L) ~; _  C7 @! l. N            handheldController.setPowerModeCallback(new PowerMode.Callback() {
    2 A. {: H. T+ L3 B4 r                @Override6 M! j4 o, b+ r2 p$ ?+ d) ?
                    public void onUpdate(PowerMode powerMode) {
    % Y$ A% H. f. m5 @8 K* O9 n                    switch (powerMode) {
    / P" U  T% L* N" a* x" j& s                        case ON:! m. c# s: P+ _" ?) H
                                Battery battery = ((HandHeld) mProduct).getBattery();
    % u$ P5 A1 X  [' B9 c0 r                            battery.setStateCallback(new BatteryState.Callback() {) m3 Q: \, T" g. B
                                    @Override
    6 z+ o7 ^( f! n; E. [                                public void onUpdate(BatteryState batteryState) {; k3 i( t5 x4 M$ o) l5 k; ~4 C
                                        h_power = batteryState.getChargeRemainingInPercent();
    & e/ X; _# X: J( ^* h                                }
    7 e8 l+ l9 @- R                            });# U. D; |* Q# P% p& N+ v- g+ a
                                break;
    8 n& G" F) Y' n0 b% F; x                    }
    5 w* H# i) B/ s" }) D                }' m, P$ \# x! {" ~
                });
    + T" _- j" N+ \8 _$ p4 z* o" P& T        }9 d, W( T4 n) O! x8 ~
        }
    4 A. ^4 s" x* p- R8 n# v" w+ C   
    9 H5 m* |' x: I0 d% s+ y7 z    @Override0 l8 e% ~* }& p0 ?+ D  r4 P) c
        public boolean onKeyDown(int keyCode, KeyEvent event) {7 U+ u) {: p. d$ P- S7 Z
            if (keyCode == KeyEvent.KEYCODE_BACK
    , i% n3 r: U3 ~                && event.getAction() == KeyEvent.ACTION_DOWN) {
    : r+ Z- z/ j1 s5 d. J" t5 N//                        closeConnect();) w& X" Y/ ^. a
                MainActivity.this.finish();
    ' V6 Y1 F0 }0 H1 P) ~        }$ _  D$ F$ n4 `( x8 {. D% k& A, z
            return super.onKeyDown(keyCode, event);
    8 ~$ o3 ?3 e' b& E# S    }+ \7 `4 J  D. ^$ V
    }
    6 S% @) G% \9 {( E/ O完成后界面如下所示:7 o0 t7 `+ r5 c1 }8 v4 Z; o

    noljwkfd5j364015971250.jpg

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

    hrljml3xg3e64015971351.jpg

    hrljml3xg3e64015971351.jpg
    + n  D: f4 \4 @0 L
    6 I2 H* `5 p- y. E

    uemfnayen3564015971451.png

    uemfnayen3564015971451.png
    , f$ {. Y- X, a. l# }! V; @5 u/ `
    往期推荐LabVIEW OCR 实现车牌识别
    1 g" v! g% k' G; ^2 G和12岁小同志搞创客开发:有意思的激光切割技术
    7 ]$ S, j; a! b( n3 j3 d+ _0 vJavaScript+TensorFlow.js让你在视频中瞬间消失
    $ B0 D! ~2 L5 s0 [使用OpenCV测量图像中物体之间的距离! H6 g7 z5 ^+ J& N% k6 c
    全网仅此一篇:工业级压力传感器设计及实现
    0 x- g% K/ ~/ X: e$ V- n5 ^
    3 t) Q9 X/ H# C8 Q% v

    5jbojgjpvyd64015971551.jpg

    5jbojgjpvyd64015971551.jpg

    4 S7 r- }0 B1 L- X- A1 k

    kmbq44rlnd564015971651.gif

    kmbq44rlnd564015971651.gif

    * Q% o9 |( ~' I- x! F5 f. A* t& Q点击阅读原文,更精彩~
  • 回复

    使用道具 举报

    发表回复

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

    本版积分规则


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