电子产业一站式赋能平台

PCB联盟网

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

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

[复制链接]

854

主题

854

帖子

8398

积分

高级会员

Rank: 5Rank: 5

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

n1njpvfuqfl64023083205.gif

n1njpvfuqfl64023083205.gif

# z- W2 i# y9 r% J0 v点击上方蓝色字体,关注我们- Y$ C, a, G$ f: Y& O, g& U0 _

0 I' e2 O$ U/ _0 |' n+ A: l$ [1 ^5 j! [上一篇文章(基于Mobile SDK V4版固件开发大疆无人机手机端遥控器(1))因为时间原因介绍了一部分内容,如果已经完成上一篇内容的操作就可以进行下面功能方面的制作了。自己开发的APP功能不是很多,但是已经将大疆无人机的常用功能进行了结合,同大家一起进行学习~( P' t$ Z, S( B; s4 b& k' `9 u
1  B2 k1 B" V1 f3 m$ x* H- q
应用程序激活与绑定
& E, W5 W1 s% C: p( t' {+ U* J& u如果在中国使用DJI飞行器固件,则需要使用该用户的DJI帐户激活控制DJI飞行器的移动应用程序。这将确保大疆能根据飞行器的地理位置和用户个人资料,为飞行器配置正确的地理空间信息和飞行功能集。激活系统的主要是:7 `" n( k- h- G
  • 中国用户必须在每三个月至少登录一次DJI帐户以遍激活应用程序。
  • 激活信息将存储在应用程序中,直到用户注销为止。
  • 登录DJI帐号需要连接互联网。
  • 在中国境外,SDK会自动激活应用程序,无需用户登录。
  • 另外,中国用户必须将飞机绑定到DJI官方app中的用户帐户。这仅需要一次。如果未激活应用程序,未绑定飞机(如果需要)或使用旧版SDK(
    $ D! i* m4 X$ K! m4 t0 O. F% b8 n  _

    2 S/ ]) p$ F# E2, o" r5 ]  T% Z7 v$ j
    为应用程序创建UI编写MApplication、ReceiverApplication和RegistrationActivity文件(此处粘贴部分代码)。
    * o5 i$ e, i- t5 Npublic class MApplication extends MultiDexApplication {
    , c3 h4 Y- ?+ P2 |' h# O    private ReceiverApplication receiverApplication;) r# \) q: C# X" M" G- @" c- ]4 o
        @Override; R# x( C9 C! w& r  D
        protected void attachBaseContext(Context paramContext) {
    $ [$ l9 `- |# U' T9 Q        super.attachBaseContext(paramContext);" [, M9 z2 J/ B- z1 `
            CrashHandler.getInstance().init(this);
    4 O, l! g" _1 d        Helper.install(MApplication.this);- p% U& O( J, p  I
            if (receiverApplication == null) {, F+ w8 |; ]* d, J/ b# Z% R* `" G
                receiverApplication = new ReceiverApplication();0 P7 v3 e; t! X" }
                receiverApplication.setContext(this);5 ~% O: p( i' v) @- {1 s8 x
            }
    9 o  l* V5 L, b  F# I    }
    . M3 R7 p3 g' W* `" r5 l    @Override
    0 M6 M2 C6 U9 n% o7 _0 v    public void onCreate() {
    / v5 t9 O6 }1 y9 `& ]' R        super.onCreate();
    0 j, Y0 O) S) T* _6 f( y' I6 q/ b* ~        receiverApplication.onCreate();
    ! z  S( _% m9 a% i# c    }
    " l5 S$ Z1 a& F}
    8 a% g) O5 D0 K* a上面的代码实现了绑定当前APP,将后续需要用到的类函数封装到ReceiverApplication 中,在ReceiverApplication 中也能够进行账户登录的操作。# T! ~! \/ K1 W, C' L
    public class ReceiverApplication extends MultiDexApplication {; w. o$ B# o* n3 k1 l+ C# M7 k
        public static final String FLAG_CONNECTION_CHANGE = "activation_connection_change";
    + ?& J( G8 d& w    private static BaseProduct mProduct;8 Q5 o; F( W& Z
        public Handler mHandler;
    " Q3 W& Q" ^. A, T/ f; f    private Application instance;6 s5 a2 z0 l# U8 [: Q+ p. j
        public void setContext(Application application) {
    $ ^. k2 N+ `' G' Y' S4 z- \0 R        instance = application;; K: p+ s/ E7 w/ J/ P- @6 |; P" `
        }* r, k4 I3 K7 ?
        @Override
      @5 f( [" `5 l! o& L$ Q8 ~7 d    protected void attachBaseContext(Context base) {
    9 {2 X; c6 v8 G+ Z5 R3 ^6 K8 L        super.attachBaseContext(base);
    0 K9 i3 G( l% |5 `+ z5 N. ?/ ?        Helper.install(this);
    ' [$ A( z$ _( Y) L! q3 O: `1 D    }
    4 A3 g1 P2 v! K+ n    @Override
    / p& O6 X& n3 Y8 m) H- W    public Context getApplicationContext() {
    + p: [0 Z$ r1 O" g3 g: m! c! O        return instance;
    1 Q3 ?+ ]/ T9 n& x4 F    }4 T/ U  |' I* w; L  S0 U& W3 e
        public ReceiverApplication() {! i% O& i; F  V3 I4 |
        }. g& W8 f# }, G
        /**
    5 L3 L5 t. g0 y0 Q4 |     * This function is used to get the instance of DJIBaseProduct.
    3 [% V# T7 S- ?" _. x- S6 E     * If no product is connected, it returns null.
    2 H; h2 G* K! B7 K. D0 G' ~* _" b4 c     */
    $ I1 ~" Z5 z4 ]7 ]  g/ [    public static synchronized BaseProduct getProductInstance() {
    4 ], g3 ]. G8 A- p  l        if (null == mProduct) {& U2 H+ k8 c+ z8 \
                mProduct = DJISDKManager.getInstance().getProduct();
    ' E: D7 v9 s0 |2 j        }
    $ S. M) A; c% k0 f( |- M% f        return mProduct;" k. B4 A$ _  A3 _
        }) M7 v: c  e0 Z# X6 G$ v; F0 v# a
        public static synchronized Aircraft getAircraftInstance() {& E% g7 [, J7 S; N3 _/ y& h( H
            if (!isAircraftConnected()) return null;
    $ O( t1 S: l0 F; @  ]: V        return (Aircraft) getProductInstance();
    9 Y9 b2 w. K8 V' R0 T+ W    }
    : o- a7 r# r- z# H+ O" `+ o    public static synchronized Camera getCameraInstance() {
    ( o2 _8 B! C( M( ?0 T; ^( A% P        if (getProductInstance() == null) return null;
    ( H2 S+ G3 y! t. G/ w! Y/ c        Camera camera = null;' P% ]9 R0 U/ m9 E& d3 @9 d
            if (getProductInstance() instanceof Aircraft){+ G' F0 ]. B5 {
                camera = ((Aircraft) getProductInstance()).getCamera();
    " f! F) c$ b; {% W, ^        } else if (getProductInstance() instanceof HandHeld) {
    $ w- ]" m3 j( t+ q! ^% W0 g+ j! C" L            camera = ((HandHeld) getProductInstance()).getCamera();
    * I3 p7 w& j3 I2 M  Z        }
    $ d) H) P. P" V$ {" K3 a: N7 r        return camera;# I' C/ J. [9 [" Y; V8 w) X  m
        }
    ' K7 x, o6 I. n* G0 I8 z3 `/ ~, Y: G    public static boolean isAircraftConnected() {
      ~' m5 g  ~/ `* p! ~        return getProductInstance() != null && getProductInstance() instanceof Aircraft;
    $ L( J4 T! l/ e5 W9 ~    }+ f5 M' p* ]1 j7 e1 U( T: J2 J
        public static boolean isHandHeldConnected() {
    1 b6 G& a! z$ X6 D% R0 u        return getProductInstance() != null && getProductInstance() instanceof HandHeld;
    * T5 S! F* W: c' r' K" ~5 n    }
      X' V5 h4 v- ?, B    public static boolean isProductModuleAvailable() {
    7 K$ m4 N8 u. s- }( A. k1 _        return (null != ReceiverApplication.getProductInstance());" B& D: ~1 }9 k& o
        }
    ; n, a  N1 V8 z0 a7 `6 _    public static boolean isCameraModuleAvailable() {
      G; j+ A( m' r/ k3 M; b        return isProductModuleAvailable() &&
    ; y* R3 Y2 g7 R& X* A                (null != ReceiverApplication.getProductInstance().getCamera());
    ( G4 Q5 H/ ~( \6 P1 C1 V- P' V! J    }: x3 B( c+ z. O4 h# Q
        public static boolean isPlaybackAvailable() {6 f* Y; ~( X* P6 s6 U- ]4 S* @; ~
            return isCameraModuleAvailable() &&
    & {$ x; G, l3 s2 n* W                (null != ReceiverApplication.getProductInstance().getCamera().getPlaybackManager());
    + N  d; x; |2 Q. _) ?. ?    }
    3 s4 T) y3 ]: r0 N5 s    @Override
    # i# ~: h, P& K' \    public void onCreate() {
    5 w8 {2 \: T$ S6 n        super.onCreate();
    ! Z8 O" j  f* J2 r4 ~2 F# ^        mHandler = new Handler(Looper.getMainLooper());
    / B! M( R# z3 Q- V* l2 ?3 f" c& j        /**
    7 ~& v, T) o; F. H+ s         * When starting SDK services, an instance of interface DJISDKManager.DJISDKManagerCallback will be used to listen to
    1 V% k$ {2 d7 B; \         * the SDK Registration result and the product changing.- d2 l+ M' }# H1 q0 Q
             */
    * J& j+ G8 j  G! Q, G& P$ l% G        //Listens to the SDK registration result
    * W: M! M6 \' D/ N4 e: N# ^        DJISDKManager.SDKManagerCallback mDJISDKManagerCallback = new DJISDKManager.SDKManagerCallback() {) v% C. T$ R! T: m3 S
                //Listens to the SDK registration result" }1 [8 R2 l' A/ Q7 g0 z4 J
                @Override, E0 {. B  h; I7 D
                public void onRegister(DJIError error) {) \9 r; c( n: `. ^" B5 m' P
                    if (error == DJISDKError.REGISTRATION_SUCCESS) {
    . K% q% I: }3 I/ _9 F9 Y  E1 b5 o5 p                    Handler handler = new Handler(Looper.getMainLooper());
    . V" x& c, C2 u: Y                    handler.post(new Runnable() {( P  X$ V* R; t4 G8 S0 G- y* L
                            @Override1 z7 x" h# y" E
                            public void run() {) k( w+ U% N7 ^* ]: p9 Y; T% S
    //                            ToastUtils.showToast(getApplicationContext(), "注册成功");
    6 x' t9 r' f$ Z7 H7 k0 J, a$ ?//                            Toast.makeText(getApplicationContext(), "注册成功", Toast.LENGTH_LONG).show();
    ) m1 k' ]$ I7 z/ z6 F//                            loginAccount();
    0 a* h" ]# ~# S2 i0 g4 q: Q/ y4 d                        }
    9 u' _2 D! T5 L3 q                    });) u/ s, Q* Q5 w  |, C8 A
                        DJISDKManager.getInstance().startConnectionToProduct();
    0 }0 W' |+ O+ @% {) N6 j                } else {1 O0 k' ]( T% v- R0 d2 h
                        Handler handler = new Handler(Looper.getMainLooper());
    ) l5 l, ^- [! N& M                    handler.post(new Runnable() {
      Y6 B% W  j$ N: r2 b; q0 h- H                        @Override
    0 T, k0 j8 g. _                        public void run() {
    . |5 I5 T1 W; M8 M9 H//                            ToastUtils.showToast(getApplicationContext(), "注册sdk失败,请检查网络是否可用");0 n! }1 {$ i1 b( i* ~) B
    //                            Toast.makeText(getApplicationContext(), "注册sdk失败,请检查网络是否可用", Toast.LENGTH_LONG).show();
    0 e2 C% B5 Z. R6 e; y  V                        }
    " u* h; B- e2 r( A* q                    });8 S; ^4 h' A/ B: \7 `
                    }
    6 }9 q  M* G  S9 |* K1 J1 e! w                Log.e("TAG", error.toString());
    * M8 c+ [7 M) R/ U$ G+ C            }- C0 g* ^9 b, i% Y" m. \4 O
                @Override* o# p1 t; V" c8 m' x) t! a1 ]% b
                public void onProductDisconnect() {% u" ~! ]5 ^- X$ j
                    Log.d("TAG", "设备连接");, `% W( @% Q( S' {
                    notifyStatusChange();
    1 O, x  i" |* n. f/ N1 V            }
    / v9 i2 p$ _) }1 w            @Override
    $ q4 o! T& }& Y9 c! N7 r            public void onProductConnect(BaseProduct baseProduct) {
    0 f" X0 H, Z; L4 z& P" Z  a" M                Log.d("TAG", String.format("新设备连接:%s", baseProduct));
    ; l/ G" {5 F8 n* L# ^# a* F                notifyStatusChange();( g. a5 A( |+ i1 V# f7 U
                }+ y. Y) m) h( a" k3 ]4 [
                @Override
    ; A* r' \3 w0 p. S; h$ r5 E            public void onProductChanged(BaseProduct baseProduct) {
    " V& h5 k2 _/ a& o  q& |            }
    # o7 V% P  R" `; Q3 t+ d' C: d/ ]            @Override: m1 Q; U# [' C8 d  i
                public void onComponentChange(BaseProduct.ComponentKey componentKey, BaseComponent oldComponent,4 Q& k( c# z0 \! P$ E% ~
                                              BaseComponent newComponent) {
    ) b3 m2 C) y. \, f8 H% w8 l- l                if (newComponent != null) {9 \" L( w. t9 W; n4 h2 N
                        newComponent.setComponentListener(new BaseComponent.ComponentListener() {  J0 S2 n6 Y4 z- |5 f5 R1 K
                            @Override
    * \* W! [7 y6 N9 t* o8 o8 E                        public void onConnectivityChange(boolean isConnected) {+ {* q. O' L8 U( F8 h2 D
                                Log.d("TAG", "设备连接已更改: " + isConnected);# a7 u* @7 }& I' v" B+ C
                                notifyStatusChange();/ U3 @- F& U! n
                            }0 E" E+ b# U0 Y7 K* L0 E
                        });2 C! W1 O% \4 O# r7 C5 U4 S2 Y* z3 D
                    }
    1 `% N6 \" f& }! b- M6 I0 G& |) x                Log.d("TAG",9 e# U( l* H7 K# F. }1 d1 ~- w0 W
                            String.format("设备改变 key:%s, 旧设备:%s, 新设备:%s",
    6 ~/ F5 i* k: R                                componentKey,
    % M  V5 L9 E; v                                oldComponent,5 C' Q& g' h" a; I& W$ @
                                    newComponent));
    ) W5 n4 m( ]8 l8 W) a            }
    , U; |7 ^$ V9 W/ g+ m$ \            @Override9 j6 l, B" p; b. O1 O" e% T& n
                public void onInitProcess(DJISDKInitEvent djisdkInitEvent, int i) {
    1 e+ o, I; z# e7 O* p" W6 c            }: G8 h4 k  X0 ?! L9 u( q0 ~7 c
                @Override$ }4 m- _( a3 C0 q: M$ m
                public void onDatabaseDownloadProgress(long l, long l1) {
    * c0 i( r4 H2 @, d2 a            }6 P) c$ ~/ `# S: Q: n  E' K
            };( k6 D: {6 p& Z6 A7 J' \& \
            //Check the permissions before registering the application for android system 6.0 above.
    " w% z9 ]$ ~+ C        int permissionCheck = ContextCompat.checkSelfPermission(getApplicationContext(), android.Manifest.permission.WRITE_EXTERNAL_STORAGE);
      X  b4 J+ p7 [5 R- K4 L9 e* }        int permissionCheck2 = ContextCompat.checkSelfPermission(getApplicationContext(), android.Manifest.permission.READ_PHONE_STATE);
    ' m2 ^4 T* f' g# b% w; c$ X        if (Build.VERSION.SDK_INT 0 && permissionCheck2 == 0)) {
    " p& O& M: `( A+ H8 r3 G* e3 i            //This is used to start SDK services and initiate SDK.5 [1 ~5 ?; q8 ~- k- S% v
                DJISDKManager.getInstance().registerApp(getApplicationContext(), mDJISDKManagerCallback);% l: x" J5 S+ b- I
    //            ToastUtils.showToast(getApplicationContext(), "正在注册,请等待...");
    ; O) r, T# J% M) r//            Toast.makeText(getApplicationContext(), "正在注册,请等待...", Toast.LENGTH_LONG).show();7 M* m7 @9 E* Z7 `7 D- b
            } else {
    4 V$ O8 R# ?8 I/ B* @3 {//            ToastUtils.showToast(getApplicationContext(), "请检查是否授予了权限");
    0 X' f/ d% m/ M6 g, S; _, E//            Toast.makeText(getApplicationContext(), "请检查是否授予了权限。", Toast.LENGTH_LONG).show();* R; M* U- x- ?3 z3 ^' ^/ u
            }5 i$ M# S! E/ i- s: y3 l
        }! w4 ^3 X/ x  F: w6 f
        private void notifyStatusChange() {
    4 l  J9 X9 e/ d4 I. q& `        mHandler.removeCallbacks(updateRunnable);
    4 |( j% C* n* @8 C6 o( J        mHandler.postDelayed(updateRunnable, 500);
    ( l& n9 k* x& z7 J4 t    }
    , `) Y: i6 ?: k4 E    private Runnable updateRunnable = new Runnable() {
    , @  K! N  G7 F! t, U        @Override
    ! [3 ?" o6 M: ~1 H/ l4 F- r6 W        public void run() {
    ( z* z& {  y. ^            Intent intent = new Intent(FLAG_CONNECTION_CHANGE);+ w( l( o, b) I( @7 d# d7 k: h
                getApplicationContext().sendBroadcast(intent);$ T' A) i1 l5 S2 A$ e! U  t+ L% _
            }( u  {& X2 H- F- H& k' ^
        };5 K% D5 K# Y; H, o% X
    }
    , H( v. F* a; p* t7 J上面的代码是对BaseProduct、Aircraft和Camera类进行实例化,在后续使用中不用再去进行重复的实例化工作,减少内存的消耗。5 C  c$ m) l0 _9 M* Z. A+ W6 i
    @layout(R.layout.activity_registration). G" O2 d, C# B% O0 v5 q
    public class RegistrationActivity extends BaseActivity implements View.OnClickListener{
    7 n2 z) k" X2 y- S3 h+ N    private static final String TAG = RegistrationActivity.class.getName();; H1 M2 f- i0 _/ H+ |
        private AtomicBoolean isRegistrationInProgress = new AtomicBoolean(false);5 L  k  H) e- s' B9 t
        private static final String[] permissions = new String[]{& j7 e, m* K4 G8 W1 ^% w( U
                Manifest.permission.BLUETOOTH,4 ]- @3 H) h; B1 P! z& C3 F
                Manifest.permission.BLUETOOTH_ADMIN,5 {0 O* F  O# X* ~
                Manifest.permission.VIBRATE,
      I, ], E! t' J            Manifest.permission.INTERNET,
      m3 [1 P# e4 F% f            Manifest.permission.ACCESS_WIFI_STATE,9 \* q' i  s7 J1 o& K9 P
                Manifest.permission.ACCESS_COARSE_LOCATION,5 U3 o& A, z, @3 B0 X, ?
                Manifest.permission.ACCESS_NETWORK_STATE,, G4 R4 v0 w2 J
                Manifest.permission.ACCESS_FINE_LOCATION,% B" O6 f$ b% Z$ h
                Manifest.permission.CHANGE_WIFI_STATE,& }. o4 `0 J# b  Q
                Manifest.permission.RECORD_AUDIO,
    9 L: P1 C/ Q2 z; b6 c) p            Manifest.permission.WRITE_EXTERNAL_STORAGE,7 y* @, b+ o/ Z! ]
                Manifest.permission.READ_EXTERNAL_STORAGE,# ~) `* x+ ]" n* z
                Manifest.permission.READ_PHONE_STATE," U. d! |" [/ F7 k
        };
    + g" E! k1 T2 W7 k' w" N; F6 y  ?% u9 W
        @Override
    + l1 R. J8 p' P2 x, K3 I0 B2 U    public void initViews() {
    ) m( B, D8 y3 A8 ^) \        isPermission();1 B$ \8 b. }2 o( c
            IntentFilter filter = new IntentFilter();
    " J* i9 B! W5 N$ {5 R0 d        filter.addAction(ReceiverApplication.FLAG_CONNECTION_CHANGE);
    " W! ^6 g1 O" g0 a        registerReceiver(mReceiver, filter);
    7 w, T" _9 M2 A    }/ Z& F7 r2 D) g9 r3 _! P$ T: ]  H/ v
        @Override# F0 p5 J8 Z4 _3 [6 A
        public void initDatas() {4 [5 R+ T0 C2 H( U- ?. c3 _+ ~8 m
            startSDKRegistration();% u$ G: ^- ^- f  K3 c9 l
        }) ]) i, n! S- e4 c* s
        @Override
    % ?; u4 P& {8 J. K" A1 n4 \" j    protected void requestData() {
    $ g) p; f% i- a# h6 L. Y2 M+ R        
    8 i# o- D2 j, H/ M: C# U    }# r1 t% m2 V/ x' p$ e$ a5 n
    " D! m* S/ Q: T) V% ~0 a5 C3 G
        @Override
    ! y4 H) ]( u, V    protected void onResume() {
    9 Q2 U$ g" {4 P; p        super.onResume();
    " l( S, c& j( m* q    }0 g) e; J4 t6 E" t& @5 l! h% d

    1 }+ n5 h+ n) h: w    private void isPermission() {
    ) {; B* y4 Z  R2 f2 x8 r        requestRunTimePermission(permissions, new IPermission() {
    7 V* G4 D+ E$ F  [2 b9 m) z            @Override
    6 k5 F$ ]1 J% @            public void onGranted() {' e* k$ G) O1 C$ p4 F1 Q
                }" A9 a0 z- P% K7 A
                @Override
    0 `4 L' q' w3 C- X- j8 p2 v1 |            public void onDenied(List deniedPermissions) {
    $ e  \1 [& I1 f3 ^3 {% Z& d            }$ U# \. ^; C  H7 g1 L2 v7 M7 L
            });( D" y# P# b+ X/ D1 _6 V
        }* d$ x0 \0 h8 o# {7 c# Z
      
    1 r& `8 ]# v3 O& [7 }  `    //无人机首次注册
    4 z9 G, U, q+ M! G  B        private void startSDKRegistration() {
    " }, V) P" D# [3 P3 N7 B            if (isRegistrationInProgress.compareAndSet(false, true)) {
    9 h* }1 j9 ~& |                AsyncTask.execute(new Runnable() {
    : |" m3 p4 d7 F# |                    @Override! o% N7 I9 j$ L/ H7 G( z; s' k
                        public void run() {6 I( v/ G) u/ K
    //                      showToasts("注册中,请等待...");
    0 c4 X3 p7 z8 A8 @                        DJISDKManager.getInstance().registerApp(getApplicationContext(), new DJISDKManager.SDKManagerCallback() {
    5 e1 e+ M! q) u) _# C* X. t                            @Override
    $ }+ S# V1 Z9 o; y" A- y                            public void onRegister(DJIError djiError) {! D% r& y. E$ W1 n1 Y) d# O7 y+ z
                                    if (djiError == DJISDKError.REGISTRATION_SUCCESS) {+ M# F8 s, f6 @- D8 a4 M
                                        DJILog.e("App 注册", DJISDKError.REGISTRATION_SUCCESS.getDescription());& T$ ^5 }1 u, k9 {1 e. `0 n
                                        DJISDKManager.getInstance().startConnectionToProduct();8 Y6 c) o, L9 w, h! j6 T! c/ Y
        //                                showToasts("注册成功");" j, J& {) ?# \) V8 i" r
                                        loginAccount();% O0 m& q$ k% [
                                    } else {' c8 t) D& K2 i
                                        showToasts("注册sdk失败,请检查网络是否可用");& V2 b/ ^# x' ~7 X* x+ X+ ]
                                    }: f, Y+ s+ |; ?3 k; U- A% I2 B* o
                                    Log.v(TAG, djiError.getDescription());
    2 Q8 b. l7 X# `1 t! t                            }; P; M8 |7 o- G0 r
                                @Override( y4 N0 F4 d# q% x# T1 N( a8 O
                                public void onProductDisconnect() {
    ! J/ z8 q* W1 J6 O5 ]                                Log.d(TAG, "产品断开连接");
    2 I( b& y' w0 `* `8 ]/ }$ W    //                            showToasts("产品断开连接");
    - n6 E: U( C- z2 e                            }
    : ?) n: ]( f' q                            @Override
    9 I& s& Q0 T& a/ n9 W7 H2 J4 v! y! H                            public void onProductConnect(BaseProduct baseProduct) {
    7 \  W: H3 U) z                                Log.d(TAG, String.format("新产品连接:%s", baseProduct));- X+ _! j; x% y  F5 R
        //                            showToasts("产品连接");
    . f) y4 `: R& M7 n' H; a                            }9 x6 p8 E' j' V9 d; c8 j
                                @Override4 P* u+ Q/ Y8 s+ B# V0 x; m
                                public void onProductChanged(BaseProduct baseProduct) {: g5 N- x) ~1 j( U
                                }1 }2 r# u5 f0 K5 h% a
                                @Override
    0 j2 A1 ^& B3 U9 m$ T                            public void onComponentChange(BaseProduct.ComponentKey componentKey, BaseComponent oldComponent,
    ' r. D  o: _+ Z                                                          BaseComponent newComponent) {
    & L* N* [3 t7 _, s6 o+ \: ]2 |                                if (newComponent != null) {
    8 g, j5 W- e# I* V9 W( x                                    newComponent.setComponentListener(new BaseComponent.ComponentListener() {( N5 M: C$ ]1 {" k) }- G
                                            @Override
    - L" X' C- n! y9 v6 g$ I' b                                        public void onConnectivityChange(boolean isConnected) {
    % `/ c3 D0 w% f# G) l; p                                            Log.d(TAG, "组件连接已更改: " + isConnected);
    " b0 V+ |" r( y2 W/ B% v; f                                        }8 _0 B7 u7 U* X" X6 V
                                        });; ?3 M: F* c2 ~( @8 l; V* M! q7 P5 O
                                    }: j- R7 C# ]9 X
                                    Log.d(TAG, String.format("改变设备Key:%s, " + "旧设备:%s, " + "新设备:%s",
    . U, l/ P0 A9 t. _1 ~                                        componentKey, oldComponent, newComponent));
    ; w& T2 _9 w5 G                            }
    # e  j( j; N! v2 U                            @Override' G0 L- N  z, |
                                public void onInitProcess(DJISDKInitEvent djisdkInitEvent, int i) {+ i' B( P& ?6 ~1 a- ^
                                }5 M2 q( v( x. @* x! w
                                @Override0 P0 X3 `% l2 e1 F; Q1 V# Q
                                public void onDatabaseDownloadProgress(long l, long l1) {
    " Y3 h0 k' G, D: J* S. Y                            }5 u$ w$ r, B/ O. Q. U5 V# b
                            });- e( C0 U! {7 J4 c* V& ?
                        }* Z( p% D# s5 p: z
                    });+ t" ]) ?% U% X
                }" \) _! }1 {- C# R+ A+ O
            }/ s7 I$ j8 V* x
        protected BroadcastReceiver mReceiver = new BroadcastReceiver() {. a  Q) C, v5 Y0 L# F
            @Override' q9 t' N! W7 G  ~% a
            public void onReceive(Context context, Intent intent) {
    0 G: Y4 p$ x; ~( X            refreshSDKRelativeUI();
    ( R$ Y$ G" j# s6 d        }4 e, \( F. T% y) g& c. u* E- d
        };
    3 ^. q" `# }8 W! k- g  _    private void refreshSDKRelativeUI() {- S& b  X; C8 {! C% \* F3 r/ v& \/ a6 i
            BaseProduct mProduct = ReceiverApplication.getProductInstance();/ Y  o* C: H1 e( }' A
            if (null != mProduct && mProduct.isConnected()) {& u6 ^% z3 U% @7 W
                Log.v(TAG, "刷新SDK: True");3 H9 D! T1 A8 A& p+ U4 m2 ]; h; d
                mButtonFlightTask.setEnabled(true);& {# ^' _9 u$ g: P9 W' t
                mButtonSettingRoute.setEnabled(true);
    1 z+ P- o& E  V6 O& W- Q1 e            mButtonFileManagement.setEnabled(true);1 G4 ^6 E6 O8 b6 E7 ?& l
            } else {0 y# c# j/ P& |* x( `
                Log.v(TAG, "刷新SDK: False");+ m9 u& L! ?, Y( T" r- X- X7 u9 M
    //            mButtonOpen.setEnabled(false);
    ) }+ `1 L% m; B. c+ r# l//            mButtonSettingRoute.setEnabled(false);& t* i+ e2 k. F6 v+ ^
    //            mButtonFileManagement.setEnabled(false);
    2 A! l  N* W8 ~9 \& y//            startSDKRegistration();8 d7 W9 i" p1 [/ v7 Q% B# T$ |5 O
            }
    7 s& b; W& X" L    }! L! E! E  f+ f; i1 E
        protected long exitTime;   //记录第一次点击时的时间
    9 k6 r8 J0 ^4 C4 ?& u    @Override: N3 f+ l8 I* e
        public boolean onKeyDown(int keyCode, KeyEvent event) {
    # h3 G% x1 \8 {4 |0 @. f& L        if (keyCode == KeyEvent.KEYCODE_BACK  I' ~6 b' o/ g' K- U
                    && event.getAction() == KeyEvent.ACTION_DOWN) {: A" i; p$ d; @0 ]( c# N) H
                if ((System.currentTimeMillis() - exitTime) > 2000) {
    + E, @+ d0 J) w% i3 a! u3 y                showToast("再按一次退出程序");# F; P9 x) p0 {; w
                    exitTime = System.currentTimeMillis();
    2 [. \- c/ Q, x$ x8 j' X' l9 I; M. y            } else {
    5 `% f; T. `) ?' p1 E                RegistrationActivity.this.finish();
    8 H9 m/ }2 E  b6 u3 E! h                System.exit(0);8 y4 ]& b- f$ F/ ~4 P: g" j% i
                }
    7 S1 i' A, ~% ]# c% L: N' f$ C            return true;. z' U+ T6 E7 S+ U+ I5 d
            }
    * {  o8 l# U# F! D' m% f        return super.onKeyDown(keyCode, event);& S$ l- ?3 B9 x2 o" m$ e& R
        }  H4 h9 p+ H! A1 L$ p4 T

    5 F0 E4 @1 E8 z$ c2 N/ ^        private void loginAccount() {
    0 a9 X/ Q  b. \  f& B            UserAccountManager.getInstance().logIntoDJIUserAccount(this, new CommonCallbacks.CompletionCallbackWith[U]() {
    % I, k5 Z1 K9 j( J* S5 s                @Override! ~; P; Q3 M5 k7 j1 G) I6 w" p; Z
                    public void onSuccess(UserAccountState userAccountState) {
    & Z; ~$ m8 ~+ k; P  w& R- p                    runOnUiThread(new Runnable() {# q$ Q) G/ u8 T8 M* O5 k
                            @Override1 p3 Q' t5 d6 x7 U9 |" R0 W: W
                            public void run() {: _4 g3 S! n, f" W5 s/ j6 B) `
                                mButtonFlightTask.setEnabled(true);
    ; i1 Z3 L+ {9 x, T                            mButtonSettingRoute.setEnabled(true);
    ' J  o% a% c6 k                            mButtonFileManagement.setEnabled(true);
    , `1 W3 @) `7 C  H                        }
    / }+ Q! g, n- s+ ~/ f6 A; n                    });0 p/ S( W+ ^2 h& ^% h9 d' x' b
                    }( w# X/ C: k, g+ Q
                    @Override8 u. B" p3 W; |
                    public void onFailure(DJIError djiError) {9 T3 _; c% F( I/ z
                    }
    1 m2 c" k" ]" p            });$ a) U# f' i9 |* a$ p  i
            }& H7 g: M3 R% K" b5 Y
    }% l3 g* s# H# t1 D5 E& G8 Y
    上面的代码就要进行第一次注册登录了,当然你不需要自己去设计登录注册页面,大疆会调取自己的登录注册页面供你使用。
    & C( M0 J6 H# {$ p% u

    5vvpks3hoqw64023083305.png

    5vvpks3hoqw64023083305.png
    2 R9 @7 F  R& E( _
    安装提示注册登录即可。
    3 D7 R3 ]  \' X5 @' k( M上面的这些做完后,恭喜你!现在,您的移动应用程序和飞机可以在中国使用而没有任何问题。换句话说,您的应用程序现在可以看到飞机的视频流,并且飞行将不仅限于直径为100m和高度为30m的圆柱体区域。/ E1 z# \2 l3 D6 k% Q. M8 e2 F; |" U
    39 ]) Z! `  V' r$ {1 i3 N6 L' ]  M
    飞行界面使用# ?$ R+ Z' I1 W: {3 {3 c
    虽然说可以正常飞行了,但是飞行需要设计飞行界面。那么创建一下飞行界面的UI及逻辑处理文件。逻辑处理文件中包含了获取飞机的实时姿态信息,代码中有注释内容,描述的内容就不多说了。
    # ^1 ]9 x0 d) m3 T6 I" Y9 O. D% M& U" @3 h" B( D$ S9 u
    导入UX SDK依赖( I% m' @8 G1 b- W! u1 v: ^1 K+ M
    上一节有说过集成部分,其中内容有导入UxSDk 的操作,这里再顺便提一下。再build.gradle文件中加入implementation "com.dji:dji-uxsdk:4.16"依赖,等待安装即可。7 ]1 d) X& @$ J7 e

    ' d1 g' C0 J! f9 n! p6 ~设计界面UI+ Y- {7 d" `% F& t% h9 n
    创建MainActivity文件及activity_main.xml。
    5 r# b& [4 K5 X% z* _RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"0 X* a% \7 J5 [. I
        xmlns:tools="http://schemas.android.com/tools"& a# ]& [; M/ K. a7 b( z' W  h
        xmlns:custom="http://schemas.android.com/apk/res-auto"
    ( s3 N3 i) ~$ d3 v2 p0 ]% ^9 W    android:layout_width="match_parent"9 _4 s: x. C! l; P. Z+ x7 l
        android:layout_height="match_parent"
    7 A, \2 [! H! M& q  S) ~    android:background="@color/background_blue"
    * v! R0 @1 j# i5 D' o    android:id="@+id/root_view"
    4 i# v( i9 ]& f. D- z% m. x    tools:context=".ui.MainActivity">2 y! b+ j  ]5 P
        8 S# Q+ n0 L- j; v* |/ \
        RelativeLayout
    ; b' L9 |# m6 c3 T+ ^        android:id="@+id/fpv_container"2 D+ ?/ q( p( Q: P$ }4 A( {% i6 V
            android:layout_width="match_parent"
    & A4 G$ q" K2 [, O2 L        android:layout_height="match_parent">4 Y& q* B* R0 K0 v% C* N/ x+ F
            dji.ux.widget.FPVWidget
    , ~6 i( y1 q9 `* C            android:id="@+id/fpv_widget"5 v9 }+ F( `+ {# I- J7 F0 c5 O7 S
                android:layout_width="match_parent"
    0 Q% J# n) _- W- u            android:layout_height="match_parent"' n  S; s' q# g' ?( e. i
                android:layout_centerInParent="true"1 W9 O# I3 F; W0 ^  u1 ?* I
                custom:sourceCameraNameVisibility="false" />/ Z  B. v* |9 o+ E* E
        RelativeLayout>
    1 l( s. R2 p. j! L  M& J7 }    dji.ux.widget.FPVOverlayWidget
    9 \1 V- Q) \) i, g  v# \+ e9 P  a        android:id="@+id/fpv_overlay_widget"
    ' M! u4 A5 h& Y$ E% `+ s        android:layout_width="match_parent"
    2 Z& P' K" _# H5 |        android:layout_height="match_parent"/>5 {! Q2 j) g! W* Q0 h9 u; v
        RelativeLayout6 x9 u( @9 K" }' ]
            android:layout_width="match_parent"
    3 b" e% N: H8 `  Z        android:layout_height="match_parent"1 `6 Z2 b# a+ [8 R  q0 c) o( O$ z$ F
            android:layout_marginBottom="40dp"
    0 Z: B. b4 ]* O! W+ R        android:layout_toRightOf="@+id/TakeOffReturnPanel"; G2 R1 k) [# N5 O% F
            android:layout_toLeftOf="@+id/CameraCapturePanel", \0 x/ c7 S* n
            android:layout_below="@+id/camera"
    3 h5 O) A8 N* A0 ^3 M! M! a        tools:ignore="RtlHardcoded">- |0 C* m% u% j+ P- ]+ v+ B9 ]
            dji.ux.widget.RadarWidget
    0 i. L# e$ y2 l3 b/ d6 x            android:layout_width="wrap_content") g8 `" d6 S- l/ [1 i8 F6 H& ^0 B. D
                android:layout_height="wrap_content"6 ]" v: G4 T+ L4 N+ X# _
                android:layout_centerInParent="true"/>
    / D- G( |2 _# I) j5 [$ r    RelativeLayout>
    $ a3 v% U$ _; E9 f( q7 \   
    & u8 v& `0 o/ V) i2 G5 d    LinearLayout
    $ S3 V  K1 S' L* o2 `/ z" M4 E        android:id="@+id/TakeOffReturnPanel"6 G8 P1 N- J+ m9 F# G; d/ H
            android:layout_width="40dp"
    . O. f3 x( a# m2 `* n6 |3 L0 @        android:layout_height="wrap_content"
    5 k- o+ V- F! }" V% S        android:layout_marginLeft="12dp"5 E6 P7 R- G. T4 q& t$ T- @3 u
            android:layout_marginBottom="4dp"
    * t* N* S' w$ I6 Y7 r        android:layout_marginTop="50dp"7 Z" Y* l% h/ H! Z4 `
            android:orientation="vertical"
    ) ~. l7 F  k# m4 D6 D/ _, F        android:gravity="center">
    9 F! q- j- I+ K! d1 k# ?/ s0 A. V        ImageView# B7 s+ [1 e: L4 ?3 ]% \6 `  G( ?
                android:id="@+id/img_show_back"3 n. C3 I+ Z& h- C
                android:layout_width="match_parent"
    / ~5 z1 ], g8 q. H            android:layout_height="38dp", q5 {: d0 `+ f; i8 y
                android:src="@mipmap/ic_back_36dp"8 W- O* [7 v; g* z1 y9 s0 F- V
                android:layout_marginBottom="10dp">ImageView>! R4 W2 [7 G9 e0 S+ X& `+ T) N* B
            dji.ux.widget.TakeOffWidget
    2 L4 `. E. P+ `3 s. \            android:layout_width="40dp"
    " y* C6 L+ {2 J            android:layout_height="40dp"
    / p+ F5 h' w6 @            android:layout_marginBottom="5dp" />
    - j# p) L1 o% ?$ h" Y        dji.ux.widget.ReturnHomeWidget
    8 y- }+ U# F1 f  ^            android:layout_width="40dp"
    ) C( ~# ]. x0 I; a9 d9 z$ D            android:layout_height="40dp"
    * a/ U/ f; R' `( @# C            android:layout_marginTop="5dp"( N) [* r; g. W8 Z! ?
                android:layout_marginBottom="5dp"/>; H6 _; `5 v' f: `
            ImageView& E' W4 s1 f$ K3 w/ `# J/ R5 x
                android:id="@+id/img_live"
    4 @5 r$ A# t* A- @            android:layout_width="35dp"6 H9 v  q7 V8 X; M% l
                android:layout_height="35dp"
    . y! I* `" @( f4 g            android:layout_marginTop="5dp"
    1 V2 B: \8 U2 F2 L" B            android:layout_marginBottom="5dp"
    " R' j3 `+ J! g6 ^9 b            android:src="@mipmap/ic_live_write_36dp">ImageView>/ s/ F* g2 `' ?
        LinearLayout>
    - W% \' a$ E& b( M, }3 O! Z5 y& H    FrameLayout
    ' i3 M8 N+ h7 {4 `9 R, z1 g- P2 `& g& J        android:layout_width="150dp") V( N: r* L7 r9 t) f
            android:layout_height="100dp"
    ( G8 F+ X  f' n/ j% [        android:id="@+id/secondary_video_view"( L# j0 S" G5 I0 u/ x
            android:layout_marginLeft="12dp"$ ?4 z7 j- j7 Q
            android:layout_marginBottom="7dp", m  |3 L, I" L# o/ R# r2 X$ `8 l
            android:layout_marginTop="50dp", e- @9 s  ?, |2 P% ^. ^
            android:layout_alignParentLeft="true"
    . o6 {4 W, n! F0 p, b+ s+ a1 }0 f        android:layout_below="@+id/TakeOffReturnPanel"
    - ^" s7 v& X: \, \        android:background="@color/black"># K* {# w1 y1 y, \& |9 }8 s
            dji.ux.widget.FPVWidget
    # A1 a" K6 J- F- a' T            android:id="@+id/secondary_fpv_widget". v) l% D5 @& ?1 B4 ]4 P% V$ U
                android:layout_width="match_parent"
    1 Y2 Z  {9 u& |( T; o; x2 k            android:layout_height="match_parent"& y5 I1 X, Z& r5 \" L8 P, o  R
                custom:sourceCameraNameVisibility="false"
    ' `+ W$ n' I  F& j3 J            custom:videoSource="secondary"/>4 Z- B! @  M- g8 ]& G: s# y
        FrameLayout>
    ) V; P& \. K, H    dji.ux.workflow.CompassCalibratingWorkFlow
    * _) c6 w# z. m; V- D        android:layout_width="match_parent"
    . O8 R1 m8 H5 k+ ?        android:layout_height="match_parent"/>) a7 Y6 v8 y0 I! {* w0 s; g, `3 t  \% ]
        dji.ux.workflow.CameraSensorCleaningWorkFlow
    + s1 A0 i9 g0 m) A        android:layout_width="match_parent"- }, \2 s& J2 L4 r! J  |2 y0 V
            android:layout_height="match_parent"/>* E8 D% B) L2 p/ t$ y, s5 [8 L+ s# J
        dji.ux.widget.RemainingFlightTimeWidget" _8 j  j3 |! Z, f, i
            android:layout_alignParentTop="true"
    - h1 z: c+ O, @, N        android:layout_marginTop="18dp"
    " Q3 a: {: X9 q2 N4 Q) _/ [, G/ J% A        android:layout_width="match_parent"+ P# ]4 U  W, O8 _; j3 k% v
            android:id="@+id/remaining_flight_time"
    ( r5 [8 H1 \& R! u* }3 e        android:background="@color/transparent"
    $ M  z2 Y1 @& b6 _6 o% v7 G) o        android:layout_height="20dp"/>0 S: Z$ I( O- m1 Z
        LinearLayout9 d- f6 Z4 n; C# E4 E
            android:id="@+id/camera"2 V# |5 Y% ?6 P2 n" G4 g8 J) W
            android:layout_alignParentRight="true"
    ; J) ?9 x' p+ k3 ?        android:layout_width="wrap_content"
    ' i1 j# H7 k/ T6 x        android:layout_height="wrap_content"" R' W5 k+ ]) ]& g0 e# s: Y
            android:layout_below="@+id/signal"* Y" E) p$ r. [7 D: Y7 f
            android:layout_marginTop="15dp"
    ( u- P3 p6 x3 M" z1 u/ W" s        android:background="@color/dark_gray"( s9 h2 Y$ t' s
            android:orientation="horizontal">& u% y& G+ |& f9 g0 ^
            dji.ux.widget.config.CameraConfigISOAndEIWidget4 F/ s5 o" R6 ?
                android:layout_width="50dp"
    + E8 _# ]$ c- l" [* z( q0 K            android:layout_height="25dp"/>( p) ?) |9 E, Q+ L7 ^7 R; r
            dji.ux.widget.config.CameraConfigShutterWidget
    , x4 H" R' f  m& U( y8 Y            android:layout_width="50dp". ^! j8 v7 b/ D$ f/ }
                android:layout_height="25dp"/>4 K6 s/ D0 I: A" v
            dji.ux.widget.config.CameraConfigApertureWidget) y$ n% k3 j, s- a) h$ y7 v
                android:layout_width="50dp"6 v3 S: v% u5 t* @$ O  n$ O
                android:layout_height="25dp"/>
    / p; z" _7 u9 X5 |        dji.ux.widget.config.CameraConfigEVWidget7 ?( x8 d4 W; ~3 e8 k
                android:layout_width="50dp"
    7 m5 \) t* O- q* g6 s, A2 Q            android:layout_height="25dp"/>
    & k) `  u; c0 u, D) L9 z        dji.ux.widget.config.CameraConfigWBWidget/ `& [7 e  d5 T3 v
                android:layout_width="60dp"! M8 r! k8 j# S' c+ H0 H
                android:layout_height="25dp"/>/ `; m3 n2 w9 q7 S0 G6 \& T
            dji.ux.widget.config.CameraConfigStorageWidget
    / M2 m5 N% _0 F7 m            android:layout_width="108dp"6 j+ R8 z" u# a
                android:layout_height="25dp"/>
    ; K; M3 p9 l# X' @        dji.ux.widget.config.CameraConfigSSDWidget
    ) d5 z3 I/ j0 m            android:layout_width="125dp"
    2 Z$ g, f, P7 U            android:layout_height="25dp"/>: w9 W* a% C' H( `
        LinearLayout>
    & n+ E" b9 y$ `. U! X( R' H$ y! G    LinearLayout
    ' |6 U+ R2 r3 p5 x6 H1 t2 E        android:id="@+id/camera2"
    7 b- m% M, D; c9 {/ _        android:layout_width="wrap_content": ~3 Y% H. D. T4 e2 b
            android:layout_height="wrap_content"
    7 S& R/ m4 _9 s7 H        android:layout_marginTop="5dp"2 ?% ~1 |( `- O1 |1 v
            android:layout_below="@id/camera"8 ?# i: l. |1 K& V' J0 j
            android:layout_toLeftOf="@+id/CameraCapturePanel"
    6 E+ P: [! D4 l) b* Q        android:background="@color/dark_gray"6 Q, O" k5 M& W0 ?/ w$ t: m
            android:orientation="horizontal">
    ( _) G3 O4 T5 M9 R        dji.ux.widget.SpeakerWidget
      _# y; Z  h0 S/ K! }$ N, A            android:layout_width="35dp"
    % w; Z9 c( m, ]- l6 V4 r            android:layout_height="35dp"/>
    4 _6 j2 a/ L( ~7 r        dji.ux.widget.AutoExposureLockWidget% m$ x2 H: n" k0 b6 h* H
                android:layout_width="35dp"
    ! {' l5 X  @4 f- R            android:layout_height="35dp"/>
    . O; v* A( l/ q% J2 ^        dji.ux.widget.FocusModeWidget' q; w; d! q$ E. K% h( b
                android:layout_width="35dp"! W2 S2 F/ X8 ?9 o" V
                android:layout_height="35dp"/>
    ; t/ ]3 _1 h# h% n        dji.ux.widget.FocusExposureSwitchWidget
    1 [" O2 }" l( q: j. S" t            android:layout_width="35dp"* t: t5 z7 R( A0 a2 }) R
                android:layout_height="35dp"/>% F0 C7 @3 F! W
            dji.ux.widget.BeaconWidget+ J, [2 r7 K  K% P7 Z* g
                android:layout_width="35dp"
    + i2 h5 z- y9 m% U& _            android:layout_height="35dp"/>. D( B" d' n1 v- b
            dji.ux.widget.SpotlightWidget) [; r$ D4 k! s( ~! l
                android:layout_width="35dp"
    5 D  d/ A" L( C0 \) ]8 U* t. E# j. r            android:layout_height="35dp"/>
    6 X' H) V  F, b( Q3 O' l# r        dji.ux.widget.AccessLockerWidget' G, Y" B! C( k- S
                android:layout_width="35dp"
    $ q5 A2 O& h+ w            android:layout_height="35dp"/>' D9 G4 x" t0 u* }# e
        LinearLayout>
    1 y& @2 s; V( C! m2 u    dji.ux.widget.ManualFocusWidget
    8 d2 x) h* O  }        android:layout_alignTop="@+id/camera2"4 @: }! j7 R0 `. N: M
            android:layout_toLeftOf="@+id/camera2"8 U1 w& v# f) P$ w7 k- }/ _
            android:layout_width="50dp"
    & t7 ?# M, n; R        android:layout_height="210dp"3 P; [7 P4 j, y( a' v
            tools:ignore="RtlHardcoded"/>
    ( u: ?, h8 Y) a: b, ?7 e* G% v) G    dji.ux.widget.MapWidget+ d+ O2 S7 m& J6 z1 \
            android:id="@+id/map_widget"
    1 V& S) T. D5 B: m( \0 P9 b1 E( N( E        android:layout_width="150dp"4 n  z- B0 _  r# q
            android:layout_height="100dp"" f; R/ M" S+ J
            android:layout_marginRight="12dp"3 A* x5 N# R, @  Y; g, `' e
            android:layout_marginBottom="12dp"
    0 ~$ }: s5 U8 t        android:layout_alignParentRight="true"  }4 `" D5 x. W) J
            android:layout_alignParentBottom="true"/>
    9 w* D% V3 P2 [  A3 D   
    , Q; P/ S6 \) \1 F4 u    dji.ux.widget.controls.CameraControlsWidget& k7 T; e& R, a, u
            android:id="@+id/CameraCapturePanel"  q1 }. T$ c6 ?/ X1 e
            android:layout_alignParentRight="true"6 [) u$ r1 A1 o# A
            android:layout_below="@id/camera"2 D6 V$ g, F: D  G* S' _2 S- V
            android:layout_width="50dp"
    * \* ?& R. h3 k4 L9 t1 B" z7 A        android:layout_height="213dp"
    . x: `% M. t) w3 h2 L, @        android:layout_marginTop="5dp"
    . g& S5 q5 `3 E+ `9 K5 B# `        tools:ignore="RtlHardcoded"/>  ~. R; m4 @- N
        # S  V* A" x+ P* ^" Q2 L
        LinearLayout
    4 t2 z9 n7 @1 i+ O        android:id="@+id/signal"! r' C5 V! s" K, W
            android:layout_width="match_parent"! Z9 T3 Z8 o- b1 `/ }
            android:layout_height="25dp"
    4 ^  M0 K7 q% C        android:background="@color/dark_gray"; H# U- Z! }2 u: i/ G
            android:orientation="horizontal">5 F2 ?: v# l1 C1 Y: F+ J# k
            dji.ux.widget.PreFlightStatusWidget
    ; ^1 S, w5 L; f/ y/ W            android:layout_width="180dp"
    8 u5 x( ]% K# t. S) S            android:layout_height="25dp"/>7 M! \$ S: t; u1 g8 ?
            dji.ux.widget.FlightModeWidget+ H  H0 L. c( N- L5 n
                android:layout_width="103dp"
    3 E$ \9 H% W! ]. A' U1 i            android:layout_height="22dp"/>" q2 @: _* A3 c* r
            dji.ux.widget.GPSSignalWidget
    7 h- j7 p+ }/ V3 [9 V& V; R2 J2 B            android:layout_width="44dp"+ }  U8 \  }' q' V
                android:layout_height="22dp"/>
    . F: t# `9 S& L) _, Q* A- M        dji.ux.widget.VisionWidget3 \* f- F" G' Y7 O+ m) |
                android:layout_width="22dp"
    4 u! d) O* G- |. q            android:layout_height="22dp"/>0 O) b4 F% i; L, Q5 d& a/ e7 z& Y6 r
            dji.ux.widget.RemoteControlSignalWidget
    ) v+ E+ s5 S& I- `1 J/ H- j" M            android:layout_width="38dp"9 d  G) T& ^8 r: g
                android:layout_height="22dp"/>/ G# T6 a2 S. ~2 N4 x7 S: u  k# P
            dji.ux.widget.VideoSignalWidget
    7 Y) K+ }. |2 C* h6 b$ N            android:layout_width="38dp"6 w2 `# ?( w1 ~3 }" _% e
                android:layout_height="22dp"/>
    , [4 Z% g+ c7 g5 D- \4 v1 e        dji.ux.widget.WiFiSignalWidget
    ! P, `# d9 u% R) ]4 u$ E            android:layout_width="32dp"
    * \, R: A4 `" d1 I+ ^+ ?0 ?            android:layout_height="25dp"/>
    ( c9 |# d* K8 {* o2 w5 a        dji.ux.widget.BatteryWidget' E$ O* `9 u  B
                android:layout_width="96dp". A3 v  T' X# J: n8 ~
                android:layout_height="22dp"2 G+ e: |% g) ?) B/ F/ M
                custom:excludeView="singleVoltage"/>
    * M4 C. g) k3 i4 V        dji.ux.widget.ConnectionWidget
    % K6 \, b; O, z0 `/ ]# j8 _            android:layout_marginTop="3dp"6 A4 `4 K5 S3 Y- w  `! G
                android:layout_width="18dp"
    ' N0 m3 I. E- y" ]1 j3 X            android:layout_height="18dp"/>: U+ X8 Q9 E' v1 _' o+ C% ?
        LinearLayout>8 R* [1 ?  l5 O. H5 m0 \1 {
        LinearLayout  J& F% W+ m, x
            android:id="@+id/dashboard_widget"
    ! {- B8 G; ?* v$ T+ c        android:layout_width="match_parent"1 E' f# B; |' U# e# u5 U
            android:layout_height="wrap_content"& ]4 P( _6 w1 y2 c$ d# A! r
            android:layout_alignParentBottom="true"8 s9 i6 y% R- s
            android:orientation="horizontal"
    : }9 Y. J2 t8 q$ r        android:padding="12dp">: m+ P) ?8 @4 C2 V
            dji.ux.widget.dashboard.DashboardWidget
    3 S; L- P1 u; f  p            android:id="@+id/Compass"$ y' Y$ b% A! D8 h, U
                android:layout_width="405dp"6 d+ c( V1 F! B/ L+ D( s: V
                android:layout_height="91dp"
    + ^" L% ?9 m& a5 }& G            android:layout_marginRight="12dp"
    # W1 {2 A1 A" w            tools:ignore="RtlHardcoded" />& S9 ?  u" o  ?* ~/ x
        LinearLayout>1 {( s/ J' S. t. a* [& E' G

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

    rndxjmine2a64023083406.jpg

    rndxjmine2a64023083406.jpg

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

    dwx4hpo5o5k64023083506.jpg

    dwx4hpo5o5k64023083506.jpg
    2 e; X5 Z/ T5 t
    " y+ S7 }8 U9 _; `

    uiwobraut0x64023083606.png

    uiwobraut0x64023083606.png
    : e: E8 t/ l; }- W0 J- q5 @2 ~
    往期推荐LabVIEW OCR 实现车牌识别
    - a8 h5 K! Z8 f6 t) L" f9 b& `2 _( ]3 r和12岁小同志搞创客开发:有意思的激光切割技术
    / i* w7 _7 R& M) C0 OJavaScript+TensorFlow.js让你在视频中瞬间消失& N1 V6 b) ?& z8 z
    使用OpenCV测量图像中物体之间的距离/ Q" b1 ?8 o6 V4 w2 o
    全网仅此一篇:工业级压力传感器设计及实现
    7 Y; S% w% K) q7 m! b  s
    # q. a9 D' J3 ^

    qye2bh0mhdb64023083706.jpg

    qye2bh0mhdb64023083706.jpg
    $ j! n# |4 C* J% q3 c1 N! q

    cnnb1olyf5d64023083806.gif

    cnnb1olyf5d64023083806.gif
    6 U2 s1 q$ ^2 S* r6 C
    点击阅读原文,更精彩~
  • 回复

    使用道具 举报

    发表回复

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

    本版积分规则


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