电子产业一站式赋能平台

PCB联盟网

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

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

[复制链接]

752

主题

752

帖子

6398

积分

高级会员

Rank: 5Rank: 5

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

3qnnlgeqxdf64015971050.gif

3qnnlgeqxdf64015971050.gif

; w. j0 P! ^' Z6 P) [点击上方蓝色字体,关注我们
+ ~% ~) a; s8 l6 o2 l9 K
4 z. m7 l! \& f2 o+ M( w2 e" g: k8 _上一篇文章(基于Mobile SDK V4版固件开发大疆无人机手机端遥控器(1))因为时间原因介绍了一部分内容,如果已经完成上一篇内容的操作就可以进行下面功能方面的制作了。自己开发的APP功能不是很多,但是已经将大疆无人机的常用功能进行了结合,同大家一起进行学习~$ G7 c, v5 w1 V0 E  d6 Y
1- G, Y" w1 l. a% l. l  v
应用程序激活与绑定
0 J' J) G) b. K) x" E如果在中国使用DJI飞行器固件,则需要使用该用户的DJI帐户激活控制DJI飞行器的移动应用程序。这将确保大疆能根据飞行器的地理位置和用户个人资料,为飞行器配置正确的地理空间信息和飞行功能集。激活系统的主要是:
% [7 O8 _. g4 B. f9 U
  • 中国用户必须在每三个月至少登录一次DJI帐户以遍激活应用程序。
  • 激活信息将存储在应用程序中,直到用户注销为止。
  • 登录DJI帐号需要连接互联网。
  • 在中国境外,SDK会自动激活应用程序,无需用户登录。
  • 另外,中国用户必须将飞机绑定到DJI官方app中的用户帐户。这仅需要一次。如果未激活应用程序,未绑定飞机(如果需要)或使用旧版SDK(
    ; w3 s1 Y6 i4 ~. E9 `
    3 x4 l& M% Y4 C
    2
      E5 w3 f  c6 |. U! J( p为应用程序创建UI编写MApplication、ReceiverApplication和RegistrationActivity文件(此处粘贴部分代码)。
    ! p0 q$ U: {( J& Xpublic class MApplication extends MultiDexApplication {3 J+ [8 }: n% Z7 z8 k: b
        private ReceiverApplication receiverApplication;
    , o) `: a  o7 V9 f( |+ |    @Override
    " V0 Y, @, P, h* {- R# `$ Z    protected void attachBaseContext(Context paramContext) {
    3 L/ d+ a  G7 U9 v3 m  Y6 \        super.attachBaseContext(paramContext);" p$ T+ U9 u( _6 a3 `- c! G
            CrashHandler.getInstance().init(this);: ]9 M0 m7 E- v. g' |, Z  G
            Helper.install(MApplication.this);
    ( w( K' P5 e% w7 X8 l0 P. z# @        if (receiverApplication == null) {
    6 I( f1 f6 i! d* s' r            receiverApplication = new ReceiverApplication();
    ; m# h. Q, H: h$ N; a            receiverApplication.setContext(this);( ]% R, p% l5 h- S5 Z$ c2 v
            }
    2 h% R9 G* k( r( ^    }1 \0 n+ j. E* n7 _+ M# c
        @Override( H& T( ?' N3 ^0 J) C' e" f
        public void onCreate() {
    / x3 a  [* C  `' O        super.onCreate();+ Y* k% W6 A3 A) Y+ \) x8 b$ v
            receiverApplication.onCreate();
    - u0 ~4 \' M7 t  R6 W) V9 u    }, e/ d% t8 z! `, w4 ~
    }8 i5 r+ t+ E, u; l; c' X8 C
    上面的代码实现了绑定当前APP,将后续需要用到的类函数封装到ReceiverApplication 中,在ReceiverApplication 中也能够进行账户登录的操作。
    ) d1 y6 s+ ]! V* Dpublic class ReceiverApplication extends MultiDexApplication {
    # z2 a, R/ B$ P5 d    public static final String FLAG_CONNECTION_CHANGE = "activation_connection_change";/ i- _$ `  {, k+ V, \8 [3 r2 K5 u1 [
        private static BaseProduct mProduct;5 _0 H$ Y1 @4 D/ j6 f: ^) C
        public Handler mHandler;: D! j( f! Y* J- s3 x7 N  R
        private Application instance;
    ) W! A+ ^9 O! K    public void setContext(Application application) {# p  \, _8 W! @
            instance = application;3 y9 w% n- W8 h3 d
        }
    ' Q/ a/ M5 f. \( v7 h    @Override
    5 H, J% d. q) l/ y/ G    protected void attachBaseContext(Context base) {
    ; o5 }: U$ Z2 W8 U2 y        super.attachBaseContext(base);
    - _5 V3 u0 t: e- s( |        Helper.install(this);4 h$ K, w4 H6 O8 t. x
        }
    6 H6 F8 h- h" C    @Override
    $ A) D) w, z; Q9 ]* l6 @4 q, g    public Context getApplicationContext() {
    / I7 v& a/ u& F9 E        return instance;
    # V. A6 W; n/ W9 S    }. H6 k2 i5 i6 E
        public ReceiverApplication() {
    , M% R' K& `" x% Y  u    }
    1 |, l4 i9 S" g  k' v8 l  d# K    /**9 }. O5 X5 R9 @, L2 S
         * This function is used to get the instance of DJIBaseProduct.
    3 m  ^- {/ L2 v! _  \0 k4 [( Q     * If no product is connected, it returns null.5 n( D* a3 [( w3 i8 i  w  {
         */; V. b/ N9 S3 I4 V8 H$ w# G$ C
        public static synchronized BaseProduct getProductInstance() {
    - Y! u' @. f3 x" C        if (null == mProduct) {
    * ^' A  \. }) j  L6 h( e% ^            mProduct = DJISDKManager.getInstance().getProduct();& F0 K; ]+ e! Q9 \# R9 |4 r" U& d
            }
    2 S# `8 D; s( R4 |" A0 d        return mProduct;
    , a' M4 E, t3 d* m9 T. \+ e    }( |( M2 h0 J- h5 y7 s) G9 A
        public static synchronized Aircraft getAircraftInstance() {- K: g0 y6 c- _1 V$ X" A; ~' ~2 O( a
            if (!isAircraftConnected()) return null;
    , I3 ]4 R4 f* R* E/ G3 l$ \1 V        return (Aircraft) getProductInstance();
    2 m! L! |& p( O' g    }: ?3 Y; v# a  V' [9 o1 H: I
        public static synchronized Camera getCameraInstance() {
    9 D9 @+ S3 y$ l1 |2 T  ~* _        if (getProductInstance() == null) return null;
    8 L( t* o9 x7 S1 W+ l, I* G        Camera camera = null;
    $ c9 U$ x: ~/ N8 k) u: C        if (getProductInstance() instanceof Aircraft){6 o4 `; Q% x& A* d
                camera = ((Aircraft) getProductInstance()).getCamera();7 s$ d" \$ C! K+ `% j
            } else if (getProductInstance() instanceof HandHeld) {
    9 m. ]! {& x% g2 ]% m( V            camera = ((HandHeld) getProductInstance()).getCamera();; [. y1 \6 V# j
            }  K* V: }; _. C2 `  U6 ?- G- X
            return camera;. ~+ b0 I% T4 v5 [- Y% x
        }) _" o2 Q7 @4 @: L$ i4 q2 _. r9 @
        public static boolean isAircraftConnected() {( e4 Z1 o3 A1 ?: j- j. K3 l4 S
            return getProductInstance() != null && getProductInstance() instanceof Aircraft;8 K* }2 |) I( Y) S% e/ A
        }; V# ?8 k6 Y4 D4 [$ k0 h7 Q
        public static boolean isHandHeldConnected() {) G" U( R8 [1 B$ |
            return getProductInstance() != null && getProductInstance() instanceof HandHeld;
    # D& ]: Y  Y4 q0 ~! g) N/ v    }
      o" g$ ]( z' v) k    public static boolean isProductModuleAvailable() {
    & Z+ Q. h+ L( T* `        return (null != ReceiverApplication.getProductInstance());
    3 q! L4 d1 L% j' x' s( {    }
    6 {' }/ j0 E; F# [  E: r    public static boolean isCameraModuleAvailable() {
    / j3 a* D' b/ f$ d) Q        return isProductModuleAvailable() &&
    2 [) {1 q% D& b7 j0 ?' f$ @                (null != ReceiverApplication.getProductInstance().getCamera());4 w$ Y: J3 b( o  D1 ~" n
        }
    # ?( x, d( C7 m; F" X3 H    public static boolean isPlaybackAvailable() {
    6 A0 z1 M2 U; y: g3 M; X        return isCameraModuleAvailable() &&
    * H( T  D, g0 A6 ?, V* o                (null != ReceiverApplication.getProductInstance().getCamera().getPlaybackManager());
    8 v" Y# w2 y& @+ P    }
    " d. N# ^* P9 G5 W    @Override
    . a) j/ {  G. [6 o( J. L    public void onCreate() {
    : Y2 }) Q2 L+ b" O  A        super.onCreate();+ K5 e1 q. L4 r! h
            mHandler = new Handler(Looper.getMainLooper());4 D" `5 B2 n9 ~; g3 ~4 T
            /**& l4 r' |0 d0 s3 |: {' n7 Y
             * When starting SDK services, an instance of interface DJISDKManager.DJISDKManagerCallback will be used to listen to
    5 t+ g$ w. A8 e8 q0 b5 @! D1 F         * the SDK Registration result and the product changing./ ~. p; v5 |# z
             */
    + @- z7 |$ ?+ s3 J/ D5 O        //Listens to the SDK registration result
    5 i. R5 U" Z3 }$ u: z        DJISDKManager.SDKManagerCallback mDJISDKManagerCallback = new DJISDKManager.SDKManagerCallback() {! `' Q4 n4 @/ l% v) \
                //Listens to the SDK registration result
    ; f! X) W" k  _- O2 \5 O. C( d! K! v            @Override9 f/ Q& z& I1 g8 o( r6 f& q+ R/ U
                public void onRegister(DJIError error) {- ^- X9 W. {4 T7 ^! h. a
                    if (error == DJISDKError.REGISTRATION_SUCCESS) {5 Q$ j6 J/ ]: L# _
                        Handler handler = new Handler(Looper.getMainLooper());
    $ ?! ~& M" I7 f- ?, _, T                    handler.post(new Runnable() {
    1 s2 d  k; R0 ~1 O                        @Override
    , B$ K) D4 f  n9 U% {' K! y' X                        public void run() {
    + P; Z& {" b: s//                            ToastUtils.showToast(getApplicationContext(), "注册成功");
    $ a1 p- F! W! u$ }//                            Toast.makeText(getApplicationContext(), "注册成功", Toast.LENGTH_LONG).show();
      c' a" X% [3 ]; `2 @//                            loginAccount();2 O6 ^( v# a: \2 a2 L0 ]% y
                            }1 k1 j& h  v. I2 }
                        });4 I; b' p9 Y6 ?0 @7 o; i+ p
                        DJISDKManager.getInstance().startConnectionToProduct();
    0 l) f8 D/ U0 L; ^8 l' [  i                } else {. b' v& b2 \) L( U. z
                        Handler handler = new Handler(Looper.getMainLooper());1 L) U) @, E, ?% i0 _+ I/ `1 T4 w
                        handler.post(new Runnable() {
    ' F$ J+ ~4 C' |. ?% C. b                        @Override8 _5 }% @% b* p$ J' t1 H6 {- p
                            public void run() {
      J& a2 Q" q' Q  V//                            ToastUtils.showToast(getApplicationContext(), "注册sdk失败,请检查网络是否可用");' x9 D4 p2 M) Y8 {& `% Z
    //                            Toast.makeText(getApplicationContext(), "注册sdk失败,请检查网络是否可用", Toast.LENGTH_LONG).show();
    ; {9 w' X- L+ r& b4 W                        }& d3 v. p3 L: S
                        });
    ! s! `$ m! }  m; p# d6 l4 [                }# T* m  w, F6 G$ t
                    Log.e("TAG", error.toString());
    + n4 Q. J( X) o0 c. M            }) r, U; M* Z" G4 o
                @Override4 P$ z) ~; X: N) U0 J4 N1 h) M
                public void onProductDisconnect() {
    % u8 l. p, m% |& g                Log.d("TAG", "设备连接");  Z7 n. |) U5 R$ |: v" O5 Y
                    notifyStatusChange();
    / N& m/ j) @# I* R# z& x            }
      Y9 g  I* o3 y9 P* [            @Override+ A' c+ p6 q! O$ _
                public void onProductConnect(BaseProduct baseProduct) {  Y( n- ?) S; }& j9 L
                    Log.d("TAG", String.format("新设备连接:%s", baseProduct));
    & T0 d# G8 d$ V8 v                notifyStatusChange();
    ' Y7 x* n) ?: q$ N) \            }
    # ^8 ?# \7 G6 ~# M( Z6 p            @Override
    1 \1 c) v2 D4 s& d$ w* P            public void onProductChanged(BaseProduct baseProduct) {
    / P1 i) I" c5 W/ L            }7 a9 ?/ E. i" T& T. |$ f5 c; t: R# U+ }
                @Override
    ) b. P8 v" R$ u3 |+ L            public void onComponentChange(BaseProduct.ComponentKey componentKey, BaseComponent oldComponent," n5 x$ z1 m! E% ~( K' W
                                              BaseComponent newComponent) {
    6 z2 M6 b& i2 `! z                if (newComponent != null) {4 u/ b+ O' F4 c5 `- ?" Z7 @! w
                        newComponent.setComponentListener(new BaseComponent.ComponentListener() {: ^/ N2 G: m9 N" Q% ^% K9 _4 m
                            @Override) z) m4 P- t) a9 N7 [: f3 ]5 C
                            public void onConnectivityChange(boolean isConnected) {; V% b) t- r1 e( k
                                Log.d("TAG", "设备连接已更改: " + isConnected);' h" o$ a- ?7 U) R3 Q
                                notifyStatusChange();8 U& o! {, p0 p5 t; H3 I5 \8 \
                            }
    - Y! |; e% K. ]( J/ l                    });" x4 L, E" w2 x& _
                    }
    ' o4 N" A* A& |% o; d$ x; @                Log.d("TAG",
    9 \/ \4 ^) r, l6 ^7 v                        String.format("设备改变 key:%s, 旧设备:%s, 新设备:%s",
    % k- ~/ \; P( j" h                                componentKey,1 w7 G: a9 D: p8 D: o6 `& s; @. v
                                    oldComponent,
    ) R) D" h; ^" _1 t                                newComponent));
    " `, b) Z9 c# N5 @9 T' g3 X) H7 `            }
      I9 ^- z3 F- o' j            @Override
    2 u6 M' o! ^0 ^2 x            public void onInitProcess(DJISDKInitEvent djisdkInitEvent, int i) {
    ! g2 k( _: k' {/ V( x2 y            }
    3 s) s" c/ k: A* O( ?            @Override- k7 T4 D0 B2 G; x- o9 W
                public void onDatabaseDownloadProgress(long l, long l1) {
    ' X8 q! p, m7 Q) ?            }
      w9 ]1 B& t* T1 T( |        };
    # d4 y9 H: Y9 w# k. E        //Check the permissions before registering the application for android system 6.0 above.7 w- V" ~/ {4 f
            int permissionCheck = ContextCompat.checkSelfPermission(getApplicationContext(), android.Manifest.permission.WRITE_EXTERNAL_STORAGE);
    & r9 N! e6 f% {  C: l        int permissionCheck2 = ContextCompat.checkSelfPermission(getApplicationContext(), android.Manifest.permission.READ_PHONE_STATE);/ F2 I6 l0 B3 ^
            if (Build.VERSION.SDK_INT 0 && permissionCheck2 == 0)) {
    1 B) G6 _& ^" w0 B& f; }& D' i            //This is used to start SDK services and initiate SDK.; Z" V: i& n( U" v/ Y5 U# o6 {% K2 _
                DJISDKManager.getInstance().registerApp(getApplicationContext(), mDJISDKManagerCallback);4 [8 K3 m; G0 u/ R. r& `3 N
    //            ToastUtils.showToast(getApplicationContext(), "正在注册,请等待...");3 G8 G- Y' O# O0 S$ Y5 y
    //            Toast.makeText(getApplicationContext(), "正在注册,请等待...", Toast.LENGTH_LONG).show();
    % k0 X9 D" c8 v        } else {
    % D  H/ M& ~3 C//            ToastUtils.showToast(getApplicationContext(), "请检查是否授予了权限");" S9 i5 F' H3 y/ `3 S; R
    //            Toast.makeText(getApplicationContext(), "请检查是否授予了权限。", Toast.LENGTH_LONG).show();
    7 F' y, J  j5 ]5 X        }
    - K4 o$ Y4 M5 k: c; _( n) L1 L    }+ ~& e. M6 `- m6 L' |" u$ f
        private void notifyStatusChange() {2 l& ~& d/ s: ~( F
            mHandler.removeCallbacks(updateRunnable);
    " E0 A& \" ~( f  k1 f$ z0 y        mHandler.postDelayed(updateRunnable, 500);" C# x" g7 i7 A0 o2 u
        }# `  S% k. J% H2 u
        private Runnable updateRunnable = new Runnable() {
    " |# U6 R. L! f* S( h        @Override, k2 Y# T! w) \( D" N0 x
            public void run() {
    ! Z3 I8 G, c  e  g/ c0 z            Intent intent = new Intent(FLAG_CONNECTION_CHANGE);
    + Q1 ]0 l$ O9 ^$ [; E( w/ r9 d+ b6 {            getApplicationContext().sendBroadcast(intent);7 H; C, A  C1 u7 G( x
            }
    - t( U0 G) j6 W- {' T    };' K" N* g8 w3 X
    }
    ! f3 T% e% ]7 j$ c. {. Q5 s/ o上面的代码是对BaseProduct、Aircraft和Camera类进行实例化,在后续使用中不用再去进行重复的实例化工作,减少内存的消耗。
    / n) p8 [' k. x@layout(R.layout.activity_registration)
    8 W4 D3 F0 ~! z4 Spublic class RegistrationActivity extends BaseActivity implements View.OnClickListener{
      K& G& s+ A& y9 V+ u8 o1 x  M    private static final String TAG = RegistrationActivity.class.getName();
    0 W7 r) U5 `) M" W# A5 e# Z    private AtomicBoolean isRegistrationInProgress = new AtomicBoolean(false);1 q4 g9 n. m- X
        private static final String[] permissions = new String[]{( U/ g* ?9 N) U3 x1 L
                Manifest.permission.BLUETOOTH,2 U$ Y3 J6 b0 m$ D9 h) f  t8 n
                Manifest.permission.BLUETOOTH_ADMIN,1 R% T; K" o5 H
                Manifest.permission.VIBRATE,2 g' ?" Y" D' \3 h  S8 R
                Manifest.permission.INTERNET,
    3 b* ^* P7 P: E7 a            Manifest.permission.ACCESS_WIFI_STATE,+ d9 `& g6 y5 Y. W  h& R
                Manifest.permission.ACCESS_COARSE_LOCATION,
    . V* M; L) D/ R" B: c            Manifest.permission.ACCESS_NETWORK_STATE,
    * W1 Q. M5 l* Y( g3 w            Manifest.permission.ACCESS_FINE_LOCATION,3 N# v7 ?  [- m6 `; V: U, [
                Manifest.permission.CHANGE_WIFI_STATE,
    6 |/ ~9 h% E) R4 m4 a            Manifest.permission.RECORD_AUDIO,4 L6 |! q& p) ^% c: o
                Manifest.permission.WRITE_EXTERNAL_STORAGE,
    $ Q) k; n$ a; i- S            Manifest.permission.READ_EXTERNAL_STORAGE,
    : q8 Y5 O2 }6 I8 a* m" r            Manifest.permission.READ_PHONE_STATE,  u* k' J' M! t8 p
        };
    , T; w$ W4 ?+ t, z! b$ V8 i5 `+ |* s' s; F; w$ Y6 O* Q$ v
        @Override( c4 a7 W- O" i% N
        public void initViews() {+ @# g5 i" k3 ^
            isPermission();+ M. c: @% C+ c; o
            IntentFilter filter = new IntentFilter();
    . p  C, D# A1 _6 E# u. y# S1 ~        filter.addAction(ReceiverApplication.FLAG_CONNECTION_CHANGE);2 i- Z/ N( J7 {  P- O
            registerReceiver(mReceiver, filter);
    7 G: @. ~) l8 R( U- E    }$ w7 R5 v# m9 P, B% `! N9 \- u) E/ _
        @Override
    $ a4 V4 N1 p5 Q! Q' Y7 ?' }% k    public void initDatas() {9 T' d5 l% p9 {$ s) i# E
            startSDKRegistration();
    ; _- a. z8 A& X4 [3 J: D5 |0 g    }
    ( v: F) t2 K) G, g    @Override
    0 F" m7 ^. U# D! R6 S    protected void requestData() {  d2 Z  E5 r  Z! b: s# l& x
            
    : S9 d7 \8 y' }) x+ j9 }    }: b# K3 |& y; _$ j2 {+ U# w  S% t
    # F( V+ d. h- J( `$ S0 ?2 P# x
        @Override
    ) W% f0 X' l1 c' f    protected void onResume() {' Q: u" R! [7 ]) M0 Y+ b, F% d; i; e
            super.onResume();
    . ]) a9 q0 t2 p5 `* o$ E! X# K    }
    3 s) {2 c/ O, a% g/ C9 w5 @+ o, w5 M6 i
        private void isPermission() {
    8 Z; E$ p; H) G# i2 R2 S! v        requestRunTimePermission(permissions, new IPermission() {( `$ w- ?/ s+ W! w+ e6 s
                @Override
    5 d% a- h7 A( O, Z0 s: \* Y            public void onGranted() {! ^& C: ^% i( p. B; T
                }) u) N5 `+ D! r0 Q
                @Override. l$ I) S& |- a' z
                public void onDenied(List deniedPermissions) {
    ! a+ u9 b( {9 x! N: R9 T            }
    2 E7 x+ c; Y0 D$ g0 Q0 f        });
    , G( c$ j. b- h4 m& S- X2 E    }+ m. G  I+ m9 w8 h$ C! g. S
      5 L# ]  e7 N0 b9 t! F
        //无人机首次注册
    ; q5 i" Z2 z, F        private void startSDKRegistration() {
    # d+ D& F+ S4 ]9 g; X            if (isRegistrationInProgress.compareAndSet(false, true)) {, @( l$ N* p5 i. ]% ?& r
                    AsyncTask.execute(new Runnable() {
    . d, d+ c/ R* B$ i1 Z                    @Override
    5 v; X2 R$ y2 c0 D$ j1 I                    public void run() {
    ( S* z9 M" ^' G3 r//                      showToasts("注册中,请等待...");
    ( Y  T: ]0 _: r6 d' K' F8 B9 f                        DJISDKManager.getInstance().registerApp(getApplicationContext(), new DJISDKManager.SDKManagerCallback() {
    7 x3 p3 u+ H0 m5 ?8 C                            @Override$ {' K6 }. \( T* j8 `
                                public void onRegister(DJIError djiError) {
    ' p1 u  k4 m% K5 P# p                                if (djiError == DJISDKError.REGISTRATION_SUCCESS) {/ b4 @) A9 @5 V; n9 G
                                        DJILog.e("App 注册", DJISDKError.REGISTRATION_SUCCESS.getDescription());9 A4 l! V; {; O- [# x5 X% s' d
                                        DJISDKManager.getInstance().startConnectionToProduct();/ i, N) r3 Y' h; a6 f
        //                                showToasts("注册成功");( {: h4 Q- f9 g6 X- \  n
                                        loginAccount();8 y) x: A  m; A& n* R
                                    } else {( p! ?. r; K; \4 f
                                        showToasts("注册sdk失败,请检查网络是否可用");
    6 [9 M+ H3 U1 n5 v                                }
    5 W" _- e  v9 [% w                                Log.v(TAG, djiError.getDescription());
    ' S' H7 R3 _/ @5 Z0 C                            }
    8 G& S1 S: z1 e: ~3 ^7 @                            @Override1 c8 U! V6 ^! V& M+ @; \6 R5 b
                                public void onProductDisconnect() {
    ' b3 [, g7 B2 C                                Log.d(TAG, "产品断开连接");
    - a; _( H# x- s  U0 T: c1 e    //                            showToasts("产品断开连接");
    & N3 A" ]+ X- D" o                            }
    7 b# }1 B# J4 y' t, ^                            @Override
    0 `6 _( W2 V+ q; O4 Q                            public void onProductConnect(BaseProduct baseProduct) {
    # L! o" O" e' V/ c% w                                Log.d(TAG, String.format("新产品连接:%s", baseProduct));3 }4 v: y4 F, B2 O8 I$ a  P4 P$ l
        //                            showToasts("产品连接");
    $ B" s! Y" m: N4 n                            }
    ) P) V: A2 ~, @. C. L7 o                            @Override5 @) s) S0 V7 Z1 i% M% q
                                public void onProductChanged(BaseProduct baseProduct) {
    ! i3 D  ^9 d! `& G% ?1 a* @- \                            }
    % n; y  A9 J" Q/ y( v6 W) S6 t                            @Override
    ) n2 a3 r8 ]' |8 R( B                            public void onComponentChange(BaseProduct.ComponentKey componentKey, BaseComponent oldComponent,2 g% ]& W# O+ _+ o3 s) w
                                                              BaseComponent newComponent) {
    4 T8 a( n( Z$ v$ Y1 E! u( x. s                                if (newComponent != null) {' I% g4 I1 H" Y! g$ S; v% M% z
                                        newComponent.setComponentListener(new BaseComponent.ComponentListener() {% s8 [" u+ t/ ~7 z; p+ l
                                            @Override
    5 }% m) l; O. g7 Q                                        public void onConnectivityChange(boolean isConnected) {
    2 _# |4 L7 \2 _" S; L                                            Log.d(TAG, "组件连接已更改: " + isConnected);
    2 L4 b& G% z/ D  q) D# y                                        }) A) q* T  d# E7 d2 W
                                        });
    - a2 u8 c0 S1 g0 I' Y1 c1 C                                }
    ( L! v# \6 `& r$ F0 K                                Log.d(TAG, String.format("改变设备Key:%s, " + "旧设备:%s, " + "新设备:%s",
    & ~- e7 D+ W2 J+ T. k' b5 }                                        componentKey, oldComponent, newComponent));
    ; U! H0 U2 T" D' ]                            }5 f; f, R) S6 ^5 X2 w1 G
                                @Override
    & c$ c1 P' s0 N3 c1 A$ |  [                            public void onInitProcess(DJISDKInitEvent djisdkInitEvent, int i) {/ P, c; J6 O# w& h4 D6 N* Z
                                }
    * r8 h# R7 q* o                            @Override0 j# n2 G& r2 d) B. {7 i
                                public void onDatabaseDownloadProgress(long l, long l1) {% T" |; M- Y/ V; K
                                }
    * s0 `! {0 ^: D: ]; l& b                        });# P3 U5 s5 U, l6 H" q
                        }
    . u- A/ X& v+ M. P                });8 _5 g, W- C" i% q% a3 l
                }
    ( T+ V: E( E- K  g2 ~        }
    5 e3 Y% L/ K( T- b    protected BroadcastReceiver mReceiver = new BroadcastReceiver() {. n6 h! u, [3 e7 Q/ l* z6 d( _9 {
            @Override- L4 ?: ^6 N/ [" G: F
            public void onReceive(Context context, Intent intent) {0 H2 `9 V. e1 X$ O  e+ {
                refreshSDKRelativeUI();
    * l( Y: W& [5 u) C) |$ m6 t5 K        }3 [1 N6 M4 N5 t$ }- A
        };
    $ u  i1 s4 @0 R3 M    private void refreshSDKRelativeUI() {9 Y% H! Q- Y( n2 i
            BaseProduct mProduct = ReceiverApplication.getProductInstance();' F8 a  Y, y" B$ F
            if (null != mProduct && mProduct.isConnected()) {
    1 C, w/ r  i4 w. f- |2 u            Log.v(TAG, "刷新SDK: True");7 D, t- \* k( d, X- k: e
                mButtonFlightTask.setEnabled(true);6 @, n8 h, C3 ^2 @
                mButtonSettingRoute.setEnabled(true);
    & b# N; v5 @) B6 r            mButtonFileManagement.setEnabled(true);
    ) L+ p8 D. u- u5 l, h  k& F        } else {# v. \& O/ L; t4 W# ~2 W9 U9 ~
                Log.v(TAG, "刷新SDK: False");! x9 ~6 L' ~! W2 B  B$ d1 u, v
    //            mButtonOpen.setEnabled(false);5 d; {4 b& J+ ]) ~0 t
    //            mButtonSettingRoute.setEnabled(false);; r; J. P3 O; F: Z( c5 k# M" k! f( |
    //            mButtonFileManagement.setEnabled(false);
    ' W+ a) B* r# F$ y# E0 u# y0 N//            startSDKRegistration();
    / g2 f, @. }& ?6 k4 m. j; ]        }# W( N% p' ^7 I5 n" `; q( ~
        }
    5 ^( a4 ]5 W# d! t    protected long exitTime;   //记录第一次点击时的时间
    4 F- u4 L' H, g2 G- s    @Override
    0 D  E: I$ f# r    public boolean onKeyDown(int keyCode, KeyEvent event) {" l- |( C" ^8 z: X& y
            if (keyCode == KeyEvent.KEYCODE_BACK" I) B9 P7 L( J1 N  j* x2 ]3 |4 s! t2 g
                    && event.getAction() == KeyEvent.ACTION_DOWN) {, Q3 {6 v% U: c2 ^/ c5 t4 [
                if ((System.currentTimeMillis() - exitTime) > 2000) {( H% H  ?4 q' @7 \* L
                    showToast("再按一次退出程序");2 S$ W; K7 E) U5 G/ ~8 l" D' Y+ C3 \
                    exitTime = System.currentTimeMillis();
    4 b, x! ?: H+ \; S8 m            } else {
    5 _' J2 V7 J- G0 e9 v8 G, L) {4 ]                RegistrationActivity.this.finish();' g$ {& I; @# G
                    System.exit(0);
    ; m# r, s6 u1 x* V+ r& K% B            }
    ) N+ z- E" o4 l, v, E5 M4 @            return true;
    1 y. e  n1 l  @% b        }
    * u5 ~; D! e) `: ?8 k( j        return super.onKeyDown(keyCode, event);+ Q0 d* q9 k7 r. U
        }6 y1 M" Z- E, ], n1 c& J% K, Y

    3 h* K1 P8 C/ w        private void loginAccount() {
    # `& Z* ]. b% j( G            UserAccountManager.getInstance().logIntoDJIUserAccount(this, new CommonCallbacks.CompletionCallbackWith[U]() {" ^8 k7 ^* J. @9 t/ W  G$ p
                    @Override6 U9 k4 S) x/ G
                    public void onSuccess(UserAccountState userAccountState) {
    2 U5 C% H$ A* z  F4 m6 X: P                    runOnUiThread(new Runnable() {
    , H( g0 P4 C. U1 V8 ?                        @Override8 c( f9 e) K( m/ S. V% X2 f$ y# H
                            public void run() {: W% s% h4 j- s2 H
                                mButtonFlightTask.setEnabled(true);" {/ N2 d7 \( T/ k
                                mButtonSettingRoute.setEnabled(true);: g( P( j0 B6 J! i, u8 Q9 r4 J
                                mButtonFileManagement.setEnabled(true);
    ; w  [1 J7 u" V. `$ a* J6 J2 ^" l# A                        }
    $ o2 s5 k% `& \) u1 m" `9 _                    });
    0 _' O& ]' E: b: \                }% L" h+ T" M; s8 R: M2 C' F
                    @Override
    / J) S) K( Y% N' J: ~& C                public void onFailure(DJIError djiError) {
    ; {2 J4 ]6 T' v: Q* s! v" v                }! p  o2 t( ?" d# ?; G
                });
    # E0 \4 S* ^9 Q        }
    2 w& j. {- A+ L  R. H}3 v) _" T$ O7 S/ T
    上面的代码就要进行第一次注册登录了,当然你不需要自己去设计登录注册页面,大疆会调取自己的登录注册页面供你使用。
    $ N6 U. H0 G' }+ Y' V6 ?! ~

    hq4gpuho40364015971150.png

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

    noljwkfd5j364015971250.jpg

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

    hrljml3xg3e64015971351.jpg

    hrljml3xg3e64015971351.jpg

    4 [: t5 Y* i6 @! ]9 \8 o/ X& Q" C( |8 f

    uemfnayen3564015971451.png

    uemfnayen3564015971451.png

    % M% }1 j9 K5 O( }: O往期推荐LabVIEW OCR 实现车牌识别
    ; d6 ^0 B7 L6 T和12岁小同志搞创客开发:有意思的激光切割技术" b6 p1 n& [4 L! a# j/ T
    JavaScript+TensorFlow.js让你在视频中瞬间消失& l0 l% W: |1 r; I; F
    使用OpenCV测量图像中物体之间的距离' F! l! g' T4 h# X- ^+ x9 f. A7 W
    全网仅此一篇:工业级压力传感器设计及实现! r+ \5 I! H) `8 q$ }  @0 G

    . q  F0 }) c3 r, L8 @

    5jbojgjpvyd64015971551.jpg

    5jbojgjpvyd64015971551.jpg
    . O. U9 Y, H9 T7 H+ V; b

    kmbq44rlnd564015971651.gif

    kmbq44rlnd564015971651.gif

    : M  M5 Y# B( g1 a7 }点击阅读原文,更精彩~
  • 回复

    使用道具 举报

    发表回复

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

    本版积分规则


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