电子产业一站式赋能平台

PCB联盟网

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

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

[复制链接]

1001

主题

1001

帖子

8803

积分

高级会员

Rank: 5Rank: 5

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

omqaxwaojye64015955823.gif

omqaxwaojye64015955823.gif
/ ^6 a5 F5 [0 [  a5 o3 Y. O
点击上方蓝色字体,关注我们
) h4 z" `9 y" i; y+ b& u/ A" a" Y2 d- {
上一篇文章(基于Mobile SDK V4版固件开发大疆无人机手机端遥控器(1))因为时间原因介绍了一部分内容,如果已经完成上一篇内容的操作就可以进行下面功能方面的制作了。自己开发的APP功能不是很多,但是已经将大疆无人机的常用功能进行了结合,同大家一起进行学习~
/ O2 H3 B1 v1 |0 b" X1
  S8 Z" C) o& U应用程序激活与绑定+ R+ s, }+ I  a; H6 U
如果在中国使用DJI飞行器固件,则需要使用该用户的DJI帐户激活控制DJI飞行器的移动应用程序。这将确保大疆能根据飞行器的地理位置和用户个人资料,为飞行器配置正确的地理空间信息和飞行功能集。激活系统的主要是:
" K# \" [, U8 x- I3 p9 D
  • 中国用户必须在每三个月至少登录一次DJI帐户以遍激活应用程序。
  • 激活信息将存储在应用程序中,直到用户注销为止。
  • 登录DJI帐号需要连接互联网。
  • 在中国境外,SDK会自动激活应用程序,无需用户登录。
  • 另外,中国用户必须将飞机绑定到DJI官方app中的用户帐户。这仅需要一次。如果未激活应用程序,未绑定飞机(如果需要)或使用旧版SDK(( m% T5 L! B) W) P/ T+ A! s. E+ u+ r

    ; f& Q" R( y& |. Y2
    / R2 b. j9 v' X+ |为应用程序创建UI编写MApplication、ReceiverApplication和RegistrationActivity文件(此处粘贴部分代码)。1 Z. S  g& b+ u& e( W
    public class MApplication extends MultiDexApplication {
    * U  D5 }6 _" H1 c. }* f, |2 [, K    private ReceiverApplication receiverApplication;
    + q5 I. b6 d# c: s* g* R    @Override" L+ I4 z( w0 E1 F
        protected void attachBaseContext(Context paramContext) {5 H- h# O, s$ I
            super.attachBaseContext(paramContext);
    . w# P( @/ B3 C8 A        CrashHandler.getInstance().init(this);
    0 @# ^. Z2 J8 ^9 M) i4 P        Helper.install(MApplication.this);# ]* t- j) q* [& e# d, V3 J
            if (receiverApplication == null) {
    ! S: T$ \, `* ?# t; j' z            receiverApplication = new ReceiverApplication();
    + [9 `# g. y$ _* K' l% c            receiverApplication.setContext(this);- t) N6 `6 p; b+ L7 {# s
            }
    9 l5 ~! ^$ R8 A% b    }! V% }# A+ }; v8 f. e6 Q; i5 t
        @Override
    " x% I% X4 h$ j. P    public void onCreate() {
    8 G0 y4 J8 u6 A8 @1 r        super.onCreate();
    4 @8 \; \' f. A0 |* {7 P, M' c        receiverApplication.onCreate();" D' `. e, j: t# Q6 b) Z
        }
    8 w/ o. r: X! O}
    9 N+ A+ W, U7 h3 V2 n7 n+ e3 h上面的代码实现了绑定当前APP,将后续需要用到的类函数封装到ReceiverApplication 中,在ReceiverApplication 中也能够进行账户登录的操作。
    % X3 O0 a* e  {/ u" N( U; `/ Jpublic class ReceiverApplication extends MultiDexApplication {
    . g0 @1 K# A8 S1 o$ [) u    public static final String FLAG_CONNECTION_CHANGE = "activation_connection_change";
    , g8 X. }) I0 `7 e  X, y$ f& Z4 Z    private static BaseProduct mProduct;
    7 V& ~: ~. j: ?( R, i& E    public Handler mHandler;! z& T# Q" D# L
        private Application instance;$ K* s4 T" X& ~; S6 Z2 m& n
        public void setContext(Application application) {
    . Y7 B/ u* x9 l  ^- r        instance = application;
    + ]5 l/ i+ Q! f* m' o, ]: J% d    }
    " X# Z% H/ o# C. }0 d* b! }" {1 X    @Override9 D. |' V6 k$ e. @7 R
        protected void attachBaseContext(Context base) {/ `( C. d3 ^! L" j# C7 L
            super.attachBaseContext(base);5 ]2 G+ T" ^! o) s8 @+ g4 X) j& f
            Helper.install(this);
    8 ~' K5 M( A6 O, G. G    }
    ) {1 ~1 ?) D, p& |2 I2 }    @Override
    ; h1 v3 Z; ~0 D+ v5 y    public Context getApplicationContext() {, y- B0 v9 \1 Q' j( x: K  y
            return instance;  z0 A! y: h* L; B; j  e6 B
        }
    7 x/ I4 a& L. \4 H6 @    public ReceiverApplication() {% i! U2 f6 \+ R4 w2 F1 u* v) \
        }3 m1 U3 u) y7 ~3 ]9 k1 p' [8 `
        /**; `- X) i  \3 ^
         * This function is used to get the instance of DJIBaseProduct.! g5 p0 u% h" C
         * If no product is connected, it returns null.
    / i' o& B4 B1 l$ z$ q. S! K     */1 P, _' l" l& ^5 ?  i8 x
        public static synchronized BaseProduct getProductInstance() {; c$ f4 J  a8 ]. p2 G' n
            if (null == mProduct) {
    2 o+ u# G. I% q- S9 C; b            mProduct = DJISDKManager.getInstance().getProduct();
    & A3 J0 P& H# F2 J        }
    8 w' t& a* p/ l7 U& j        return mProduct;
    ' ~" J+ N# ?( s$ Z! ^2 L: R    }
    " {; b6 z; J8 K2 f( j: C    public static synchronized Aircraft getAircraftInstance() {; M4 Q+ c' r1 q- k6 n
            if (!isAircraftConnected()) return null;
    . b. R$ T3 _- B# r8 k        return (Aircraft) getProductInstance();6 l/ i& ~. \( @
        }8 p/ c4 J( a$ U7 e: T
        public static synchronized Camera getCameraInstance() {' [9 w. R8 U" z3 Y% y* d- l
            if (getProductInstance() == null) return null;8 k4 [9 V. h6 |
            Camera camera = null;8 j) K  q% q+ u- R. B
            if (getProductInstance() instanceof Aircraft){
    5 P, J* \( G0 y3 l2 A+ N/ d            camera = ((Aircraft) getProductInstance()).getCamera();9 P6 F5 F% a! {3 ^
            } else if (getProductInstance() instanceof HandHeld) {
    " M$ c2 C$ x4 A5 x; G$ b6 i            camera = ((HandHeld) getProductInstance()).getCamera();
    + `( c, }/ A& |6 I' D5 I        }7 \7 U/ {1 p/ n
            return camera;
    + q4 _9 }3 k5 C; T1 ^: d. y    }. q$ T! i5 o$ J8 h) V. L+ x
        public static boolean isAircraftConnected() {3 n6 H" z! S1 ?8 v
            return getProductInstance() != null && getProductInstance() instanceof Aircraft;; Z6 U( d  P6 w+ P% d4 K8 u% F0 x
        }7 U# t0 d; f: E0 H" g3 f+ @" \* z
        public static boolean isHandHeldConnected() {
    / _; r5 g! L" g4 Q6 H$ P( V        return getProductInstance() != null && getProductInstance() instanceof HandHeld;9 q' Y' |+ N0 E
        }7 L4 m: ]3 A) i& d0 v
        public static boolean isProductModuleAvailable() {
    6 E8 ]$ g! H2 @1 z5 I8 V* F        return (null != ReceiverApplication.getProductInstance());" Z# {/ O5 T; K, G
        }+ a; X. p6 D; u6 u' {7 a
        public static boolean isCameraModuleAvailable() {3 ]. t9 \" g7 c6 Y) x
            return isProductModuleAvailable() &&
    % o' G' H  b% x# \                (null != ReceiverApplication.getProductInstance().getCamera());
    2 V  K6 j4 G" ?; N( \4 k    }
    4 l1 a" M3 ~' ?( R    public static boolean isPlaybackAvailable() {
    2 a& v$ b) ]2 W( V        return isCameraModuleAvailable() &&
    , I# J$ A+ V4 z: N, _" N                (null != ReceiverApplication.getProductInstance().getCamera().getPlaybackManager());+ }6 Q2 V' F7 k* B! r0 F: f
        }
    6 i& {& i0 ]  H) \    @Override
    8 O9 p  k( u* `. ?2 m% @8 h    public void onCreate() {
      p- O/ J7 n0 o" u; \        super.onCreate();
    ' a. y4 L- r8 m9 @" z        mHandler = new Handler(Looper.getMainLooper());$ L$ N: E$ D4 f( j, V
            /**
    , c  v* R2 [  w         * When starting SDK services, an instance of interface DJISDKManager.DJISDKManagerCallback will be used to listen to( W( i- _0 j6 k
             * the SDK Registration result and the product changing.
      f# R0 C$ k" r( L3 ~         */4 R; x" p* o$ K( t1 j1 Y
            //Listens to the SDK registration result
    / V5 g/ B/ `* P# R, w        DJISDKManager.SDKManagerCallback mDJISDKManagerCallback = new DJISDKManager.SDKManagerCallback() {3 B) V. W: a7 @& B9 k) U4 z) i
                //Listens to the SDK registration result2 m0 T: r# G8 w; D" u( |
                @Override( y: r; m; {0 U* Q
                public void onRegister(DJIError error) {8 I! F( J, ^# k) e; p; j
                    if (error == DJISDKError.REGISTRATION_SUCCESS) {
    " V3 s4 u* v% D$ J5 I. T- Q                    Handler handler = new Handler(Looper.getMainLooper());# e1 i) x! ^8 A9 Z* H7 y
                        handler.post(new Runnable() {# z$ s4 F! ?! L
                            @Override
    : e2 H  ?+ X2 W* j( D7 n! I% t& ?                        public void run() {) D% t2 C6 f- v( d+ V
    //                            ToastUtils.showToast(getApplicationContext(), "注册成功");
    8 F8 g" t% M5 E2 r  }//                            Toast.makeText(getApplicationContext(), "注册成功", Toast.LENGTH_LONG).show();: x/ g( Y$ h, R
    //                            loginAccount();/ ], }9 \: X. M% O( ]2 F
                            }4 k& M; F# \2 o6 Q
                        });! r( c$ Z% V' s; b( a' R2 J
                        DJISDKManager.getInstance().startConnectionToProduct();
    0 Y' L: @  q* s# s: p; w                } else {
    3 f1 {  s$ D- _; X- O                    Handler handler = new Handler(Looper.getMainLooper());
    ' `  M% J% B+ x1 z                    handler.post(new Runnable() {
    ; O* ^! E3 V6 Z  n& q                        @Override
    ' e& |. |) t* Y7 I  o                        public void run() {
    9 U6 y7 A# `( N; g- b# O//                            ToastUtils.showToast(getApplicationContext(), "注册sdk失败,请检查网络是否可用");
    0 X6 b" ~$ M4 `//                            Toast.makeText(getApplicationContext(), "注册sdk失败,请检查网络是否可用", Toast.LENGTH_LONG).show();
    " m) |" _5 A5 F( z5 K' h8 ^                        }3 J7 d) \4 S8 |, B4 F( W
                        });7 @# s: s/ B1 ?/ u6 F
                    }; Y8 Y0 [! V+ a! M
                    Log.e("TAG", error.toString());. R) x+ P. R4 n
                }" Y1 b0 @9 b0 A6 r5 b
                @Override
    ' t: x( X, ^7 b/ ^# u            public void onProductDisconnect() {  t' ?. ~7 T, C
                    Log.d("TAG", "设备连接");9 j7 U. i& x% v+ I5 C3 q3 |9 P
                    notifyStatusChange();" t/ x* h8 f5 {4 _1 ~" C
                }
    0 g# {+ S% }! K9 F' U- ~" R            @Override
    1 A& p4 Q  y# d( {! t            public void onProductConnect(BaseProduct baseProduct) {
    , D" m0 H. m& r( Y6 O7 u                Log.d("TAG", String.format("新设备连接:%s", baseProduct));
    5 {3 a* }, X0 A/ w3 h                notifyStatusChange();
    ; P6 K" o9 U8 @            }
    ! g- Q6 Z$ s  b+ f6 }6 J            @Override/ N$ a6 t) S: l; m; n
                public void onProductChanged(BaseProduct baseProduct) {' U" P0 j& f7 D+ V
                }* }9 ^  e1 ?* E+ k  m9 d- l' m
                @Override
    * g1 V& g8 Y5 o( a8 e            public void onComponentChange(BaseProduct.ComponentKey componentKey, BaseComponent oldComponent,
    ; E8 h, `4 t1 L+ I                                          BaseComponent newComponent) {3 E: P1 V8 a; Y& o5 {
                    if (newComponent != null) {
    ! L" N8 }" D' U$ R+ t  A; Y                    newComponent.setComponentListener(new BaseComponent.ComponentListener() {
    7 Z* R- X* u" h6 [4 q                        @Override
    * V( p: R7 ^; C5 j) l                        public void onConnectivityChange(boolean isConnected) {
    - [0 [* \( J* n+ {  x) d                            Log.d("TAG", "设备连接已更改: " + isConnected);- U* r% G' u/ i* h8 d) v4 d" A
                                notifyStatusChange();3 v5 O1 b0 t/ f8 s, X  C& X  j# T
                            }
    6 Z; b  N+ B* }' e& e9 G                    });
    - L) x& k6 r& Y6 m                }" M) u! y: i0 w/ g3 N
                    Log.d("TAG",
    # I6 E: H- R* K9 b                        String.format("设备改变 key:%s, 旧设备:%s, 新设备:%s",# w* a6 D6 e; e  S7 n0 C' U% v
                                    componentKey,
    3 S7 h" P4 {% ^" z/ Q3 t7 Y                                oldComponent,4 G0 q9 x0 K4 s) {8 k* {
                                    newComponent));
    $ h( r: c; _% Z' o/ U- u            }
    2 D8 A. ^9 b+ [. Q, v            @Override6 c$ Q( s, m7 q" g, E4 f$ V
                public void onInitProcess(DJISDKInitEvent djisdkInitEvent, int i) {
    - M9 R1 s% F: n3 r            }
    & t7 A( z7 v2 A' k  h" m" l            @Override
    ) j8 v+ [3 Y% {% J" O            public void onDatabaseDownloadProgress(long l, long l1) {
    8 ~+ V& ^6 v, D' j7 E            }
    2 F1 \5 {1 a! ?+ d- w, R9 W( |        };7 N+ g2 ?/ F) d3 n0 j0 [+ @: J
            //Check the permissions before registering the application for android system 6.0 above.
    8 m$ f% @& a: W' ?# [        int permissionCheck = ContextCompat.checkSelfPermission(getApplicationContext(), android.Manifest.permission.WRITE_EXTERNAL_STORAGE);) K8 h+ z2 k5 \% @9 c7 Y
            int permissionCheck2 = ContextCompat.checkSelfPermission(getApplicationContext(), android.Manifest.permission.READ_PHONE_STATE);7 u, L4 O  v' K, |2 O! G: A2 R
            if (Build.VERSION.SDK_INT 0 && permissionCheck2 == 0)) {
    6 ]: x- J! d, w( X1 l9 @! z            //This is used to start SDK services and initiate SDK.& K' Q0 x2 z$ c7 O! t
                DJISDKManager.getInstance().registerApp(getApplicationContext(), mDJISDKManagerCallback);' J8 Y5 Y- |6 h( M
    //            ToastUtils.showToast(getApplicationContext(), "正在注册,请等待...");/ e' Y3 l( ^, f
    //            Toast.makeText(getApplicationContext(), "正在注册,请等待...", Toast.LENGTH_LONG).show();
    # p( f3 {+ P0 }/ I        } else {( z! P, [0 D4 l- v' N. m
    //            ToastUtils.showToast(getApplicationContext(), "请检查是否授予了权限");
    $ L- S5 [* _) d4 r! j//            Toast.makeText(getApplicationContext(), "请检查是否授予了权限。", Toast.LENGTH_LONG).show();, F+ M; S! F5 s2 e
            }6 ~4 T% r& Q# n+ Z' }5 }
        }
    & \2 X) i. A+ s3 G! y3 z0 X! n    private void notifyStatusChange() {
    ! n( ?, U4 |" U: O& Q        mHandler.removeCallbacks(updateRunnable);" J& V( b7 v7 G* W# }7 o' x
            mHandler.postDelayed(updateRunnable, 500);1 n' Z* p- o1 i: E0 r! J
        }
    0 M8 o( L8 k6 w& f    private Runnable updateRunnable = new Runnable() {! D- {$ O; O8 L! _- ?4 P
            @Override% n, k9 L5 m- A' t7 q9 a6 l, b
            public void run() {
    7 F- V8 K5 U9 O$ u& ~! E1 X$ ~0 g5 g            Intent intent = new Intent(FLAG_CONNECTION_CHANGE);
    8 K2 \& p2 N( u; N7 M/ q7 v            getApplicationContext().sendBroadcast(intent);
    . Z) L$ V* Y  w6 R        }
    : Q! g. F5 G! O. {9 l+ R/ a    };1 S& y$ g1 Z8 w2 H( y% v  ?
    }% m- L* A2 c. @  y* }# H
    上面的代码是对BaseProduct、Aircraft和Camera类进行实例化,在后续使用中不用再去进行重复的实例化工作,减少内存的消耗。* J( r( F! n1 J' ?: h6 A* F
    @layout(R.layout.activity_registration)# m, M: |0 B" M
    public class RegistrationActivity extends BaseActivity implements View.OnClickListener{; `/ u: o2 b4 Q
        private static final String TAG = RegistrationActivity.class.getName();
    6 t0 f# @$ k  p1 M    private AtomicBoolean isRegistrationInProgress = new AtomicBoolean(false);
    7 k) g0 \2 h" g0 E/ s    private static final String[] permissions = new String[]{
    * F& ?" z: K& ^5 b            Manifest.permission.BLUETOOTH,) T& {* K) Y$ L% Z( y3 Z
                Manifest.permission.BLUETOOTH_ADMIN,
    / \1 L/ o1 U+ D; `% x2 f3 |            Manifest.permission.VIBRATE,8 g2 D; ^0 a" t: C9 ?3 z
                Manifest.permission.INTERNET,
    ' g# K$ q' N4 n            Manifest.permission.ACCESS_WIFI_STATE,
    , O8 a$ k, G$ ?" G            Manifest.permission.ACCESS_COARSE_LOCATION,( q" y4 |' z5 [, y" Y
                Manifest.permission.ACCESS_NETWORK_STATE,3 S" [1 @9 ]  p5 p. b
                Manifest.permission.ACCESS_FINE_LOCATION,
    8 _, `) ?9 V" b            Manifest.permission.CHANGE_WIFI_STATE,
    % S: E  o6 c9 S- }5 A8 t" v            Manifest.permission.RECORD_AUDIO,. t' o1 M$ U7 K! O; t
                Manifest.permission.WRITE_EXTERNAL_STORAGE,% {: ?, I6 m( `/ {7 n1 V
                Manifest.permission.READ_EXTERNAL_STORAGE,. ^/ i' a& Q/ {! y  ~9 _
                Manifest.permission.READ_PHONE_STATE,7 s8 H- ]: G7 e, v2 K
        };
    ! Z% M: V8 R. s* U! J
    $ Q* \( \8 J2 \6 E5 v    @Override
    : R9 X* [8 W5 H# d7 ^5 X/ E' h    public void initViews() {
    ! T5 S1 O; R1 u$ Q) ]        isPermission();
    . V6 Y* m9 e6 S: h        IntentFilter filter = new IntentFilter();% Z( ~- q, f  o; ]  J/ |" Z1 g* o, G
            filter.addAction(ReceiverApplication.FLAG_CONNECTION_CHANGE);0 g% D' t# R. k* u  A7 b
            registerReceiver(mReceiver, filter);  M' c# m- p  i, k( Q
        }9 S' Z) B6 K& o8 `! W. G
        @Override4 X% d: F5 ~7 h6 V2 d
        public void initDatas() {  y. }2 w; b9 X4 c+ t) s/ j
            startSDKRegistration();
    ) N, N3 m5 {* _  O    }
    . V. O$ l; J7 `2 I7 v    @Override7 }7 n' ~# B! ]) c
        protected void requestData() {. o5 d3 x: {# B
            3 A" @& H2 H0 U8 f. C
        }8 t& p( L8 l& \! O9 }5 g
    5 u! u& H5 p1 o* _' p/ J8 p
        @Override6 O4 P& ~4 @" @+ E, e
        protected void onResume() {/ c8 G9 v0 O' c- I. J1 k9 B6 k- L! [
            super.onResume();
    . w+ C7 j* P* u    }
    / H* O. A+ G0 g& P7 p4 q: D
    1 S0 g- f9 ^: m; u. @9 b* E    private void isPermission() {
    , N" U; v$ @) M- I' E        requestRunTimePermission(permissions, new IPermission() {
    7 i$ F5 y. d* t8 i% f1 A. E            @Override
    , K! C' r- _! k& j' H& Z            public void onGranted() {
    8 g: ~3 a, P; H# w. A            }# T6 W3 }/ T1 H; M
                @Override
    6 R$ D/ ]2 v1 s% }            public void onDenied(List deniedPermissions) {
    + |3 e/ m; y# D. G3 e0 l) p/ o; ~            }
    # v  _. }! X- s: R" E, `        });* {; \& }7 x- }' x; _
        }
    ; E$ Z# p: ?3 j& t0 f- g  
    4 m0 n5 F3 W3 R+ v+ e. A    //无人机首次注册' b" t: }% {1 o2 g$ r
            private void startSDKRegistration() {
    ! C3 a" P8 x2 P* A' R3 p+ G6 |            if (isRegistrationInProgress.compareAndSet(false, true)) {9 O6 r. V* W# s2 X$ }2 w4 K
                    AsyncTask.execute(new Runnable() {
    * Q. l/ Y- Y4 f                    @Override( ]; v3 _! C0 x& @% ^3 p% Z% F
                        public void run() {
    8 i$ F9 z4 L$ K1 v& I1 {//                      showToasts("注册中,请等待...");
    & d0 I1 J* {6 Z7 R3 x; B2 V- J. H                        DJISDKManager.getInstance().registerApp(getApplicationContext(), new DJISDKManager.SDKManagerCallback() {- w, `; v7 E" J
                                @Override% \! q8 V4 [9 b# R9 W
                                public void onRegister(DJIError djiError) {! D' D( ]7 U6 h# S7 d' K/ y& B& i
                                    if (djiError == DJISDKError.REGISTRATION_SUCCESS) {, ]: k- {$ V- `* g4 B1 w, O1 a
                                        DJILog.e("App 注册", DJISDKError.REGISTRATION_SUCCESS.getDescription());
    9 a, d( W- V/ @$ C* o* a8 w                                    DJISDKManager.getInstance().startConnectionToProduct();( [6 m  Y- k" U6 y# V1 B
        //                                showToasts("注册成功");# s. {3 [" A3 `" k
                                        loginAccount();
    ! s1 _7 t* y  Z# P" S7 x! e                                } else {
    3 p& j. W9 l& V6 d6 ^- r  R0 u                                    showToasts("注册sdk失败,请检查网络是否可用");- Z. }% h' w, \3 D& U& P
                                    }2 c2 U" M  d3 y7 O( Q# R( \, G
                                    Log.v(TAG, djiError.getDescription());
    / n- l0 G9 M$ [! u0 K6 o  S% o                            }
    6 y5 t$ g5 l6 ]                            @Override* K) s8 [$ s! H9 D* V2 |
                                public void onProductDisconnect() {
    ; w2 L+ N' L: r2 H1 {) L) n/ W                                Log.d(TAG, "产品断开连接");8 u" o# e  E- z4 b* g- D, z
        //                            showToasts("产品断开连接");
    8 e! {* Q7 `/ @) }  |& y/ d                            }" n6 P+ t; }; D
                                @Override3 a( |! n; a/ ~# R
                                public void onProductConnect(BaseProduct baseProduct) {
    % |( O' }  N6 ]) w8 Y                                Log.d(TAG, String.format("新产品连接:%s", baseProduct));
      `0 O- g4 C# i; ^; b/ t8 P" U    //                            showToasts("产品连接");
    7 y6 A3 s  m5 i( h! G, m                            }( X1 L. K, w5 k3 K; n; i7 U" P
                                @Override' j. V; x1 i; J  i" c. f6 T: @( y/ k
                                public void onProductChanged(BaseProduct baseProduct) {
    4 Q9 O  b; M) g) `& y9 p+ p                            }1 k1 Y! N6 u+ q  B/ f
                                @Override. u2 S, |' H5 A+ q+ P& c/ |+ A" s3 q
                                public void onComponentChange(BaseProduct.ComponentKey componentKey, BaseComponent oldComponent,, P6 v5 `% R4 B" E  m! W
                                                              BaseComponent newComponent) {
    & [% I' \0 p  P6 w; `/ l                                if (newComponent != null) {! \2 Q1 `% i1 ?9 p
                                        newComponent.setComponentListener(new BaseComponent.ComponentListener() {
    8 V/ {5 j$ F0 I2 t                                        @Override
    ' c# O0 H0 l" B6 d% `) X- ~                                        public void onConnectivityChange(boolean isConnected) {: A" p( w- \3 @
                                                Log.d(TAG, "组件连接已更改: " + isConnected);1 J7 V! B1 c2 e) n9 H" N
                                            }
    ! q* G' {1 h% v7 {& g: V$ U+ X$ o                                    });- R2 q9 |* Z+ u: o0 A5 s
                                    }
    7 G; H7 N3 ~' O6 Q                                Log.d(TAG, String.format("改变设备Key:%s, " + "旧设备:%s, " + "新设备:%s",
    1 y% Y* ]& E: l0 I1 P* z8 r$ j                                        componentKey, oldComponent, newComponent));
    ( B' O3 T( f! a2 j                            }* R- u3 Y  b+ X/ }, w+ W
                                @Override$ d5 K) k5 h+ |+ J- i; T6 V
                                public void onInitProcess(DJISDKInitEvent djisdkInitEvent, int i) {
    ; ?9 t( v' N: @+ |- C# d2 F2 h9 i! z                            }, a+ H4 ?- f# ?, \
                                @Override  m4 t  S0 [' m3 h* C8 s
                                public void onDatabaseDownloadProgress(long l, long l1) {* s* o! v' v' G) s
                                }
    % l2 |. |! n/ j  W                        });
    ' ^& L% n) \4 |" q7 Y$ f                    }
    / h! @6 J  q6 z3 U                });% p. i9 ?3 A* a: L
                }& U9 I$ O* C, e/ w- J; g% I+ u7 f9 T
            }
    * e& P% x  m2 i    protected BroadcastReceiver mReceiver = new BroadcastReceiver() {- ?. |) R% I% O* Y& {: R4 l
            @Override
    . Z6 ?, T( M6 ~' O7 q8 R- H- N        public void onReceive(Context context, Intent intent) {5 a  l: z3 ?9 I! K
                refreshSDKRelativeUI();/ h8 |# V" b' D- h, E8 S$ a9 }; I! D
            }
    + k1 W+ f% @9 W: H1 D    };' ?, l" ~. G( P0 _! N0 H& h0 w
        private void refreshSDKRelativeUI() {+ }6 P% t' Q8 P2 C
            BaseProduct mProduct = ReceiverApplication.getProductInstance();
    ) C" O+ \; M2 L& Y+ m        if (null != mProduct && mProduct.isConnected()) {" i2 B! j. D1 B9 X( _% G, L
                Log.v(TAG, "刷新SDK: True");! H' ]0 k- G) r6 H
                mButtonFlightTask.setEnabled(true);& ^6 }3 N" n9 A2 P. f/ |
                mButtonSettingRoute.setEnabled(true);
    ( X+ z! c0 C5 G; H/ P5 W            mButtonFileManagement.setEnabled(true);; I: a2 v8 w5 F- X
            } else {
    6 P' M/ C" L/ T2 ~& d            Log.v(TAG, "刷新SDK: False");
      R% J  H$ u0 Z% u$ D8 Q//            mButtonOpen.setEnabled(false);; w% F! \7 a3 p& q' g
    //            mButtonSettingRoute.setEnabled(false);6 D0 I8 e5 ^: J0 h# t  a* J
    //            mButtonFileManagement.setEnabled(false);
    6 c4 g4 ^# F; y, Y7 a% f//            startSDKRegistration();
    7 g7 w1 f3 s1 n8 k! ]3 I        }1 X0 m/ W' ]6 V
        }7 D$ c; L5 f1 [6 T7 w' |5 d
        protected long exitTime;   //记录第一次点击时的时间
    ' _. ?* b+ h+ K% t    @Override
    9 Y) ]' j) h6 z4 x    public boolean onKeyDown(int keyCode, KeyEvent event) {' W2 \! M" g+ \7 E0 Q
            if (keyCode == KeyEvent.KEYCODE_BACK/ c$ J5 f+ h* S2 R& K& i+ W
                    && event.getAction() == KeyEvent.ACTION_DOWN) {
    1 R+ Z# A, {& D( _4 ]; r            if ((System.currentTimeMillis() - exitTime) > 2000) {& W4 j3 _2 x: O- P) B
                    showToast("再按一次退出程序");5 R& b: u5 a% y# R6 f7 G
                    exitTime = System.currentTimeMillis();
    + R! w/ ?8 L, `# L            } else {$ G+ l: P) Q/ s: S
                    RegistrationActivity.this.finish();
    4 g0 y0 w4 E" P, p9 x! M! g                System.exit(0);, n5 T0 ?) s1 J, _# Z0 o8 T* n
                }2 Y4 M/ d+ m  q$ s  X7 d
                return true;; J; w( w) {/ B0 V, I' x- d; M3 [( r
            }
    - T0 @5 c# E5 B+ Y# `        return super.onKeyDown(keyCode, event);& c0 v4 a* Y( Q1 I
        }
    : g9 x# L; C5 z+ l7 [% F- O% S
    " J, i- S! K4 e) W$ @        private void loginAccount() {
    1 O2 x2 V: `! B' X            UserAccountManager.getInstance().logIntoDJIUserAccount(this, new CommonCallbacks.CompletionCallbackWith[U]() {
    5 L9 O& h. T8 l7 O' b                @Override
    0 ?# R" V6 @9 F' R0 t                public void onSuccess(UserAccountState userAccountState) {* B; A: J8 Z, n+ J% I
                        runOnUiThread(new Runnable() {! l0 V6 b/ a1 C0 a1 \1 }
                            @Override
    5 Z- ^- w  a& K$ R                        public void run() {
    " B7 G/ w- y0 g" V7 m                            mButtonFlightTask.setEnabled(true);
    ) c+ v1 q) {/ N1 E                            mButtonSettingRoute.setEnabled(true);; b  d/ [* y+ {, H& M' Y
                                mButtonFileManagement.setEnabled(true);
    $ B6 ~8 v: q$ Y7 E$ }% ~                        }
    7 Z' s! B" {9 K0 T, `) G2 {                    });
    6 b  I; J7 O/ l3 d                }
    7 y. k4 C0 [9 x$ W/ J9 D6 [3 p$ @                @Override9 I! ~9 n7 k$ |/ v, q, y+ O/ v
                    public void onFailure(DJIError djiError) {
    ' e$ D. @# v  X                }
    7 I, ]( q2 H8 r1 S/ [% C: ^) I            });
    1 F2 B0 H9 ]/ w/ P        }
    ; y8 ?6 H0 \& {}
    / z; h8 m- P! Q2 m6 p4 b" S上面的代码就要进行第一次注册登录了,当然你不需要自己去设计登录注册页面,大疆会调取自己的登录注册页面供你使用。
    2 T: g) {8 C9 u( ?( t  u

    mk1fg5zkzzj64015955923.png

    mk1fg5zkzzj64015955923.png

    7 B& F' N, W% g安装提示注册登录即可。
    " k: w' S# `6 I  F; ~上面的这些做完后,恭喜你!现在,您的移动应用程序和飞机可以在中国使用而没有任何问题。换句话说,您的应用程序现在可以看到飞机的视频流,并且飞行将不仅限于直径为100m和高度为30m的圆柱体区域。6 l, a0 D+ S8 \, j
    37 u! _1 I; u. Z2 ^
    飞行界面使用
    ( x- j- w; |0 M$ G虽然说可以正常飞行了,但是飞行需要设计飞行界面。那么创建一下飞行界面的UI及逻辑处理文件。逻辑处理文件中包含了获取飞机的实时姿态信息,代码中有注释内容,描述的内容就不多说了。1 ~' T7 |3 E" x7 {
    6 \( f/ ]+ R( q- D; Y- q
    导入UX SDK依赖9 W7 m7 Y; R  q+ n
    上一节有说过集成部分,其中内容有导入UxSDk 的操作,这里再顺便提一下。再build.gradle文件中加入implementation "com.dji:dji-uxsdk:4.16"依赖,等待安装即可。  O5 r; C4 f: @6 l5 f% p

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

    6 s/ x3 S: D4 r. m0 x9 i    //获取飞机信息、云台信息
    4 I# I) {9 J) p  Q3 e0 ]! D$ D    protected BroadcastReceiver mReceiver = new BroadcastReceiver() {% L0 p5 g9 \0 K' ^% V- Y6 ~! {
            @Override
    , ^' r6 K6 X& a' l2 g5 V: o        public void onReceive(Context context, Intent intent) {
    . _  Y# X/ R$ K: V% P3 F  D0 K; [            BaseProduct mProduct = ReceiverApplication.getProductInstance();/ Q9 I& H' G" X7 H9 h: I
                if (null != mProduct && mProduct.isConnected()) {
    5 T: N$ ?) K/ b                flyInformation(mProduct);  [0 V2 `$ C. X- L7 X+ ?
                    batteryInformation(mProduct);4 [; P0 `$ _0 A$ d9 O- P2 A
                    cameraInformation(mProduct);
    ' w% W0 h* `0 E* g                camera(mProduct);
    3 Y- I2 C5 i% j! U# c4 Q) T//                MobileRemote(mProduct);
    5 y& w# v/ c6 P+ X& g  B) N9 W            }
    ' s$ l2 B5 f7 L$ ?) G        }
    : ~6 X% A/ D. }( h5 h    };
    . Y2 C  V6 z2 M- H' z" W//    private void MobileRemote(BaseProduct mProduct) {
    + f! R  W3 a& Z) M" Y3 c! O8 {; m//        if (null != mProduct && mProduct.isConnected()) {
    , j: m  R% S3 G. t$ h7 {4 M  ]( v//            mobileController = ((Aircraft) mProduct).getMobileRemoteController();) w9 O& ]  m$ z2 b
    //        }
    5 J* s7 e; C3 U) I: J' p& L5 ^//    }
    , q, V2 T0 ~( U$ }* h- d/ G6 V    //获取飞机信息& P5 v- W$ M0 i5 S4 {; F4 n2 Z2 [- V
        private void flyInformation(BaseProduct mProduct) {
    1 \6 \/ l- g! ?; u1 B1 {- x        if (null != mProduct && mProduct.isConnected()) {7 l! a! o0 o- r+ ^9 R1 t7 z# |
                controller = ((Aircraft) mProduct).getFlightController();
    9 ]! w. h$ R3 x' }* V        }: G0 y% }- c1 \' U: s. b
            if (controller != null) {; p) C" v/ H1 a1 d; D% K2 h8 _( U5 U
                controller.setStateCallback(new FlightControllerState.Callback() {
    7 q% i6 W2 i2 G, _0 i  |                @RequiresApi(api = Build.VERSION_CODES.O)
    ' `5 J# I1 k2 u. c: A8 u                @Override
    * U, Y" D, ?; S2 G2 F0 P2 M                public void onUpdate(@NonNull FlightControllerState flightControllerState) {
    2 n0 d: k0 \. {7 I! j" J) ~                    //纬度、经度、高度、俯仰角、滚转、偏航值、速度5 I2 B. E, e  a, o7 S; ~+ I% x
                        lat = flightControllerState.getAircraftLocation().getLatitude();
    8 W! M1 i" M4 W5 m8 @+ I* v                    lon = flightControllerState.getAircraftLocation().getLongitude();
    # U2 Y# P% d, f5 M5 E2 M                    high = flightControllerState.getAircraftLocation().getAltitude();( G4 I. \/ x9 I/ w
                        attitude = flightControllerState.getAttitude();9 S5 L0 \/ m5 l7 r7 w- z
                        pitch = attitude.pitch;9 f/ \. U  J( v% _3 Y& r
                        roll = attitude.roll;
    * t7 S, z* a& s  H8 \                    yaw = attitude.yaw;
    ; _3 ~! C% [  t5 S7 ?$ p9 ]* Q                    velocity_X = flightControllerState.getVelocityX();
    * L, i9 C4 X% m4 V                    velocity_Y = flightControllerState.getVelocityY();
    & U5 B# h2 k& Z7 c7 x                    velocity_Z = flightControllerState.getVelocityZ();$ i; n1 }0 s1 b6 K! J5 h
                        isFlying = flightControllerState.isFlying();
    & o3 T0 [8 ~3 {; ~* o$ K6 M                    //                    MyLog.d("经度:" + lat + ",纬度:" + lon + ",高度:" + high + ",角度:" + pitch + ",速度:" + velocity_X + "," + velocity_Y + "," + velocity_Z);
    9 I5 Y- a, P  x                }$ ~: ]0 q3 Y6 x6 i2 u
                });. y; x% \7 u: j! Y) y: Y  a
                controller.setVirtualStickAdvancedModeEnabled(true);* c) [9 ~2 k8 X6 M) f( w1 G" m( u
                controller.setRollPitchCoordinateSystem(FlightCoordinateSystem.BODY);- @, }9 I+ T* Q7 r  q& l# b! ?
                controller.setVerticalControlMode(VerticalControlMode.VELOCITY);  y2 `  z( d4 E5 \2 g4 N
                controller.setRollPitchControlMode(RollPitchControlMode.VELOCITY);
    , t1 G4 a# ~: g5 w& h8 H: l$ P            controller.setYawControlMode(YawControlMode.ANGULAR_VELOCITY);! O% R. u& h6 W1 U- r( K# ~5 G) [
    //            controller.setTerrainFollowModeEnabled(false, new CommonCallbacks.CompletionCallback() {% z8 z1 g2 |3 H9 x
    //                @Override
    8 U1 A: k1 z& j& n# h& r//                public void onResult(DJIError djiError) {& ?+ |  ]4 @9 i4 `* D) e- ]
    //                    MyLog.d(djiError.getDescription());) l0 J  A  c; J3 O
    //                }- r  g4 C6 u1 C$ l  w4 u
    //            });* o7 x. C3 r, I9 q2 y1 I
    //            controller.setTripodModeEnabled(false, new CommonCallbacks.CompletionCallback() {
    # Q4 G5 {# A0 X9 j* D//                @Override
    ' ~' i% s7 s7 W8 |4 H$ {//                public void onResult(DJIError djiError) {4 V8 W* p) O" l0 m
    //                    MyLog.d(djiError.getDescription());
    ' |* F& r" y# N+ `5 Q//                }
    2 O: C; i2 u6 H; {) _8 I//            });
    1 ]1 `- X+ }/ B% m2 b- S//            controller.setFlightOrientationMode(FlightOrientationMode.AIRCRAFT_HEADING, new CommonCallbacks.CompletionCallback() {5 h; x9 W* O% ]% B
    //                @Override
    ' g; k9 a1 x; ^/ e//                public void onResult(DJIError djiError) {4 k. J$ |, K4 Z/ q9 R$ B
    //                    MyLog.d(djiError.getDescription());
    - V. n$ L* _/ z# ]; Q, \7 c//                    if (djiError==null){
    - ^: d' W. M6 V5 F/ p7 g8 n//                        if (controller.isVirtualStickControlModeAvailable()){
    5 W, e; J5 m7 _: g" ~1 F, U, o3 }//
    * Q, S, Z3 u6 S0 M1 Z//                        }else {" f  n! H6 Z6 ^0 s& l0 y) y: n
    //                            MyLog.d("虚拟摇杆模式不可用");7 @3 S8 Y% C; Y0 C; a& {* s
    //                        }
    / b; ]4 k( W" i) u//                    }6 O! P4 X: u4 V+ o8 y$ |
    //                }
    7 j& E1 H3 o- }$ s1 {//            });
    : `- T( M$ [1 n" A        }
    ( V) y" a  [# A8 e/ L- C* ?& W' p% b    }
    # k- y- P) O2 g! T    //电池信息6 t+ I1 _# D0 t6 K- g. a
        private void batteryInformation(BaseProduct mProduct) {
    , Q2 e- [& J- m3 L5 _        if (null != mProduct && mProduct.isConnected()) {
    8 O; S) ~9 E% Q+ o1 V8 u% \            battery = ((Aircraft) mProduct).getBattery();" P/ u/ |. L: f
            }
    5 A% N% b& f/ i. s" O/ E        if (battery != null) {& u: W' [( W& ^. w) Q' ^9 S) ?
                battery.setStateCallback(new BatteryState.Callback() {
    ' M7 T# \  _) t3 t+ G9 |                @Override
    8 B9 s9 m" o' j0 z* y                public void onUpdate(BatteryState batteryState) {
    . v% w4 o+ g8 D, [. Y0 Z                    //电池电量3 @% v6 J* `7 Y6 p6 I
                        power = batteryState.getChargeRemainingInPercent();5 Y& H: `% J+ S' y6 Z3 |) t
                        //电池温度
    ! l! t9 ?' |$ _! z) h8 z9 l. U  b* ^6 {                    temperature = batteryState.getTemperature();
    5 U' M4 I6 a; e1 }* ?                }
    " X. Z- h9 ~9 Q9 M            });
    & a6 J& U( \+ K        }) g/ J: p% _4 z  b
        }& O3 t% ]$ H- t; M) W" X: q. K% L
        //云台信息4 s# D5 [* {; r5 b3 v: c$ Y: k
        private void cameraInformation(BaseProduct mProduct) {
    5 F+ ~: L$ ^* {8 z5 c        if (null != mProduct && mProduct.isConnected()) {* @1 P7 n6 `, i
                gimbal = ((Aircraft) mProduct).getGimbal();
    0 _  k' U4 x( t4 J9 v        }- {* G4 d5 A" W/ }# V
            if (gimbal != null) {
    ) Z* t5 D) T+ G9 L8 {* N: q. B7 s" |            gimbal.setMode(GimbalMode.YAW_FOLLOW, null);
    * ^' o# M* B$ f( p) }            gimbal.setStateCallback(new GimbalState.Callback() {
    0 F1 O# w/ C+ t+ P3 c0 l* {1 g! v- `                @Override
    . i+ \  y- I+ S3 i- A                public void onUpdate(@NonNull GimbalState gimbalState) {- `" L5 q+ g" [: Y8 J, {! E9 |4 `
                        //俯仰角、滚转、偏航值( ^  ]2 x$ q6 Q" A
                        g_attitude = gimbalState.getAttitudeInDegrees();8 n( o8 h  M+ R$ ]- |; @
                        g_pitch = g_attitude.getPitch();/ e, I5 }/ a+ f. A) f% u& v
                        g_roll = g_attitude.getRoll();5 \. Y: {1 m' E
                        g_yaw = g_attitude.getYaw();9 U) B$ h6 j, N, r7 r! L8 ]( b
                    }$ X7 i+ q; q% m4 E$ i* c& K
                });
    : j: {  P9 I& e+ o/ u" J# _        }
    " S0 R8 Q5 _. G9 v) w  w" @$ l    }$ A& |5 v9 f, u+ {- n9 Q+ |
        private void camera(BaseProduct mProduct) {; R2 s+ ]$ g8 [) @  S; \
            if (null != mProduct && mProduct.isConnected()) {9 e8 m. V$ d# {0 W9 w, [
                camera = ((Aircraft) mProduct).getCamera();
    ! t9 z! l/ ]: a5 z0 h3 @        }
    $ ~; a) P4 v: E. e- w6 h0 o+ H6 G, a" B1 K        if (camera != null) {
    6 W3 r- `- X' ^2 X" D            //            camera.setVideoCaptionEnabled(true, new CommonCallbacks.CompletionCallback() {
    . D2 l7 G. j( J            //                @Override2 g7 Y3 |% \$ Y9 s& R; F$ M6 V
                //                public void onResult(DJIError djiError) {
    7 K: p, m9 u1 e' t# s5 b8 f            //                    MyLog.d("VideoCaptionEnabled"+djiError.toString());, Y0 X/ }6 u) |6 d0 R( m8 ^
                //                }  u0 q( B+ E: N/ F# i3 j9 q' p
                //            });$ Z% S: N4 |9 o& R1 A% g* e& X' h
                //            camera.setMediaFileCustomInformation(projectId +","+trajectoryId, new CommonCallbacks.CompletionCallback() {+ y8 H: }! f1 C- c) v4 Y- I2 a
                //                @Override
    : K  M; [% O) X- Q; g% q            //                public void onResult(DJIError djiError) {" X0 |3 @( e4 u3 S$ X/ J
                //                    MyLog.d("自定义信息:"+djiError.toString());
    ' ?2 ~, o. y7 T* X6 p7 o7 [, Z            //                }! C- ^! K+ Y' `. D
                //            });
    # W$ }# ]4 m; Z: C            camera.setSystemStateCallback(new SystemState.Callback() {) {6 N* c. d$ R3 ~5 S/ j
                    @RequiresApi(api = Build.VERSION_CODES.O)
    ' T9 x) N9 S1 r5 a8 \7 Y' O+ |                @Override$ a" F5 p* ]' e& k0 t
                    public void onUpdate(@NonNull SystemState systemState) {
    2 ]7 a( L9 ^0 R! L                    if (systemState.getMode().equals(SettingsDefinitions.CameraMode.SHOOT_PHOTO)) {
    8 Y2 u+ }* |! S( I/ y, y                        if (systemState.isStoringPhoto()) {
    $ l% x/ P; A& D" J& Q. N2 S- U3 H                            dateStr = Long.toString(System.currentTimeMillis());- O. @$ Y2 B) x/ a8 X- v0 a; N
                                list.add(new DeviceInfo(dateStr, lat, lon, high, pitch, roll, yaw, velocity_X, velocity_Y, velocity_Z, g_yaw, g_roll, g_pitch));0 t3 _: F$ ?, ^( t
                                CsvWriter.getInstance(",", "UTF-8").writeDataToFile(list, FileUtil.checkDirPath(FLY_FILE_PATH + "/照片数据") + "/" + DateUtils.getCurrentDates() + ".csv");/ x8 L0 U: ^7 g+ t: s) k5 U
                                list.clear();" P0 t3 \9 q1 a: Q6 {1 _* y
                                return;# w4 R1 X! K4 v1 W$ L* D
                            }: h% e* v9 d" D; ?
                        } else if (systemState.getMode().equals(SettingsDefinitions.CameraMode.RECORD_VIDEO)) {$ {6 o9 |5 y" u- V# y6 w' v- r
                            if (systemState.isRecording()) {5 q0 r. I, O) w1 |
                                try {
    $ B: {7 B3 Z, ~; Z                                dateStr = Long.toString(System.currentTimeMillis());4 [' J* E$ A; V) y2 s
                                    list.add(new DeviceInfo(dateStr, lat, lon, high, pitch, roll, yaw, velocity_X, velocity_Y, velocity_Z, g_yaw, g_roll, g_pitch));
    9 \. N* t& A4 O- k* C2 ~8 Y                                getList.add(dateStr);) t) M9 H6 T& R; l  j
                                    Thread.sleep(100);  B6 _' o( ?. u
                                } catch (InterruptedException e) {
    : ], @* G3 F' m  y% t- o                                e.printStackTrace();
    , d& B$ z# R# ~' d4 T                            }% ]  p/ {, Q7 L
                            } else {
    , o5 I$ \; p3 M. p8 E1 f! q7 s                            if (list.size() > 1) {2 C$ ^* i0 F- k) S" f
                                    posName = DateUtils.getCurrentDates() + ".csv";* c' l# [  A9 D  Q' \
                                    CsvWriter.getInstance(",", "UTF-8").writeDataToFile(list, FileUtil.checkDirPath(FLY_FILE_PATH + "/视频数据") + "/" + posName);
    & \4 M7 D& B6 L                                list.clear();
      _0 g; O; X5 V4 o                                runOnUiThread(new Runnable() {
    + g9 C9 M+ p/ o+ ~                                    @Override
    5 i+ ?9 r# |8 z: I                                    public void run() {
      W3 m6 q" c# I' a                                        getFileList("end");, P/ _6 X4 h6 I- X
                                        }
    ; x! h/ X9 c, i- r% f* C                                });5 T8 U7 |7 u7 X6 b% _. @9 a
                                }
    2 `- Y) \- K0 c! i, B% J                        }
    4 D" y$ s9 T. {5 a& j) F& K% o                    }5 n7 S; `$ c! t+ j
                    }, j/ ^/ s: z9 P" R0 u3 N
                });! [  K" r/ u/ f" U: \
            }8 x- t+ a1 C: `5 [6 ]- T/ \) K
        }: p. p  U/ R) `: [/ ~; Q5 H) w! V
        //遥控器信息
    * N- ^6 U8 a% Y$ t    private void handheldInforamation(BaseProduct mProduct) {
    - o! x7 P# u( U        if (null != mProduct && mProduct.isConnected()) {, u: e% }- e4 r' V
                handheldController = ((HandHeld) mProduct).getHandHeldController();
    & W/ ]- h3 \3 s( b( v6 x        }, K1 f& x3 m) e: a
            if (handheldController != null) {
    0 L1 N0 U, h; d% K' S; n            handheldController.setPowerModeCallback(new PowerMode.Callback() {+ t, ?! T! e2 j- z! r+ G" H* T
                    @Override
    / I. X! U( D6 A9 L( A& q                public void onUpdate(PowerMode powerMode) {
    , A  J) R5 Y4 f1 G) Z$ Y( B3 `                    switch (powerMode) {* `' S) L2 g# X! r" a( L2 ^
                            case ON:+ w# R8 P- [% _( I0 b
                                Battery battery = ((HandHeld) mProduct).getBattery();
    9 ^- s4 z* p. t. h  I7 ?                            battery.setStateCallback(new BatteryState.Callback() {! J6 @3 R/ U7 m4 c
                                    @Override2 }. o: y( R! d" F& G; ~) a! R; f! x
                                    public void onUpdate(BatteryState batteryState) {
    / r4 c- S8 C2 k+ F# N2 A" B                                    h_power = batteryState.getChargeRemainingInPercent();4 x! g+ l' U- O$ ]6 ^% N
                                    }! T8 w" Z: x: \$ j, d1 j! i% l- M
                                });) d5 X/ M8 A' d9 @
                                break;
    / g1 R* [  M$ C                    }* w' t# |! g: i
                    }
    ( m( Z; l: D* t" u) \& X            });2 X% P6 ^% W) H0 O8 r. `
            }
    ; X. N: ~( @! a0 J$ x    }
    ( a1 P, [9 G( m8 J1 p4 Q8 l' H   
    & w- j* t0 i  N5 g% K  R' l0 C8 y7 g% [    @Override
    ' n3 `$ j  a: e7 A. a+ o2 F    public boolean onKeyDown(int keyCode, KeyEvent event) {
    6 b  B) G$ ?! o3 N( s        if (keyCode == KeyEvent.KEYCODE_BACK
    9 U6 y* G6 E$ x8 I3 d4 o( n                && event.getAction() == KeyEvent.ACTION_DOWN) {9 B! I+ S, t; Y! x4 e- M
    //                        closeConnect();  ~0 K, K( c; W0 n+ t
                MainActivity.this.finish();3 y# S: l' t( g% q! P& x
            }3 K- k% |* q7 q3 W( L; m
            return super.onKeyDown(keyCode, event);, m1 J  {% R# D4 Y9 h
        }- A- V, d- _5 T9 b! r
    }
    " ^% m0 o. g4 D% X完成后界面如下所示:1 o5 C  [2 Z  U' e' T- V6 T+ F

    sz1bbeuylep64015956024.jpg

    sz1bbeuylep64015956024.jpg

    8 f% V: y7 _6 b+ Y9 S8 h  Z0 c上面的工作完成后就可以在无人且宽阔的地方进行无人机飞行了。8 o7 q4 {7 E! }6 V' {
    4. @3 ?$ j/ Y( L( l
    多媒体资源的操作
    . e9 K$ ]. X  C" Q' P: a多媒体文件操作,主要为多媒体文件的获取、查看、删除、下载的操作
    . v) j7 d" N( u/ m同样创建多媒体功能文件FileManagementActivity及activity_file_management.xml9 k3 n# A$ r+ W& c
    activity_file_management.xml
    : b- ?+ L4 X2 u5 T% \- ULinearLayout xmlns:android="http://schemas.android.com/apk/res/android"$ |! J. n; v' @0 A
        xmlns:tools="http://schemas.android.com/tools"# k& ?1 J; w! q! X7 j0 C
        android:layout_width="match_parent"; q' \! c* @0 |
        android:layout_height="match_parent"$ ~% T. _& e8 z
        xmlns:custom="http://schemas.android.com/apk/res-auto"
      b! b9 ^2 O. ?) ]    tools:context=".ui.FileManagementActivity"$ d; W' b$ k# M  @
        android:orientation="vertical"
    $ ^+ V  U2 ]9 D4 x, G+ i9 V    android:background="@drawable/shape_corner_eight">
    3 c7 i5 J6 V6 d2 }5 O  E6 H! K% z    include layout="@layout/activity_toolbar"
    ' b3 u0 d9 s' e        android:id="@+id/layout_file">include>, {: n; C# ^# d( S; f/ u- l
        LinearLayout% D9 Y' k6 o$ a% o! }, ]5 C
            android:layout_width="match_parent"0 X0 z) f' C8 v4 o: E/ A
            android:layout_height="match_parent"
      V5 P: {+ u) Q) S        android:orientation="horizontal">$ T, D  I7 N1 u( V4 z  {7 n0 F
            LinearLayout
    / c8 q1 e+ O$ J/ O) i            android:layout_width="250dp"1 O6 G* M& e9 w3 F" j: `! f& a
                android:layout_height="match_parent"
    $ {( n* z. f+ O* E            android:orientation="vertical"
    2 P5 x  X3 @# q) ?# V' O2 h            android:layout_marginLeft="15dp"' h6 N. j( A/ ]; }& U( T! R3 e. U
                android:layout_marginRight="15dp">7 l: Q9 ?4 t$ N* U3 P  H$ q  I
                RadioGroup" B' ~8 Y7 _: o" K! N
                    android:id="@+id/rg_file_management"
    , T' ^, e- o, n* F6 r8 {                android:layout_width="match_parent"  D0 Y! `+ }. Z, {* o
                    android:layout_height="40dp"
    / f) ?4 \( g+ O* l                android:orientation="horizontal"2 |3 x1 r/ Z0 u
                    android:background="#2B3141"
    ; P  E$ Z' X* p" b! [                android:gravity="center">
    + I( f1 O. w' j* y# \. D' E                RadioButton5 w" ~  Z/ Y) p, v! ^/ |# }# `3 L, U
                        android:id="@+id/rb_file_all"
    6 C3 c1 a3 d  {& i                    android:layout_width="0dp") R& S& A4 r  M0 b
                        android:layout_height="match_parent"5 c6 j0 t* H/ [# Y4 H6 J
                        android:layout_weight="1"
    - ^5 S5 X1 Q9 q' M                    android:button="@null"
    0 I' b( y+ b+ r. ?% {  ]+ f8 G8 B                    android:checked="true"
    ' ?! j# p2 w# _( |# k- X/ D                    android:gravity="center"& B7 I, f4 _1 v: F
                        android:text="全部"
      Y' Q1 R; s* O2 u" b5 B, q                    android:textColor="@drawable/nav_item_color_selector"% n0 D0 ?2 v7 w! r: k9 x
                        android:textSize="18sp"
    0 g  n% U: x8 ]$ u7 w                    tools:ignore="TouchTargetSizeCheck">RadioButton>
    1 Z$ M5 a- M- o- u3 Y/ g1 Q3 @# f                RadioButton6 P- o/ H7 K# j( i5 M* I
                        android:id="@+id/rb_file_photo"! ^' G) [& {. S9 J# J3 T. _  f
                        android:layout_width="0dp"
    ' y( B: R7 F7 o, e5 R                    android:layout_height="match_parent"
    6 d2 L; L  ?# P9 v: R8 O                    android:layout_weight="1"! m- p, Z6 V. q! k' J7 [* A0 `+ J
                        android:button="@null") B5 m( n6 [. X0 a; u; B4 e! y
                        android:gravity="center"
    - q& Y/ v! |. z6 p* P) [                    android:text="照片"
    / I/ C% c) z# `                    android:textColor="@drawable/nav_item_color_selector"
    4 x5 m  v, v; a& A: _% j                    android:textSize="18sp"
    7 v7 p/ ~7 d, P7 @5 x                    tools:ignore="TouchTargetSizeCheck">RadioButton>" v6 {# _/ a6 g6 U: i8 p. Q
                    RadioButton; Y8 p( v! D9 c( V7 c  n; ]
                        android:id="@+id/rb_file_video"0 f. Y/ V% V: ]* E% E: h
                        android:layout_width="0dp"
    ' b! O* G9 \: Z2 l                    android:layout_height="match_parent"
    4 V) g! @# o8 A2 ]8 V                    android:layout_weight="1"
    ) D9 y; n# t+ l" t3 k: d. E* i4 O                    android:button="@null"
    ) b( f/ j0 {  G                    android:gravity="center"
    $ V* Y( d4 E1 ~& K% V5 F                    android:text="视频"! S& l% g, E0 ]: G* V3 y* y0 Z
                        android:textColor="@drawable/nav_item_color_selector"
    8 n: m! `# I6 R$ ^8 J                    android:textSize="18sp"
    - X5 r$ r8 L* R                    tools:ignore="TouchTargetSizeCheck">RadioButton>
    . G% H8 m+ k  P4 Y/ T            RadioGroup>9 Z6 O: R8 U' d  v- {2 g
                androidx.recyclerview.widget.RecyclerView
    % i8 M- j8 r, o3 a6 M) q                android:id="@+id/rv_file_management"
    ; B. T/ _( v5 q* W/ b                android:layout_width="match_parent"3 T4 c* B0 T1 q: j# d$ m0 |. B3 H2 x
                    android:layout_height="0dp"- d+ j  A8 t% z, W6 H
                    android:layout_weight="1"
    ) l" n8 }" ^( d6 s$ Q; t                android:layout_marginTop="10dp">androidx.recyclerview.widget.RecyclerView>" D% t+ t% ]0 d6 u: \
            LinearLayout>
    7 [0 ]* ]; L% t" `& O2 C" v        RelativeLayout
    # g) @4 z* t" _1 I            android:layout_width="0dp"
    9 J7 [6 e7 N( |7 F            android:layout_weight="2"
    0 X$ M7 b( j) O& G3 f/ o/ H$ l            android:layout_height="match_parent">
    7 e. t% N. l* d7 J. p            RelativeLayout
    ) ?2 X( l% Z1 ^0 D  H! ^                android:layout_width="match_parent"
    4 _3 V5 t1 p7 H7 @0 o! \* r9 U0 Q                android:layout_height="match_parent">
    2 L* J, I, s; y                dji.ux.widget.FPVWidget
      b  ?4 {- g7 p" E( n5 g                    android:id="@+id/FPVWidget"8 L8 C* |/ m' l
                        android:layout_width="match_parent"8 w* {0 [9 v; x% L/ h
                        android:layout_height="match_parent"5 k8 F  g9 O% k! n: X: G: |
                        android:layout_centerInParent="true"
    & y7 f! E! d! J& F+ H0 Q( U+ x4 N                    custom:sourceCameraNameVisibility="false" />
    - e/ }/ D6 y! @1 h# |            RelativeLayout>
    , f2 b+ @+ S( ^( d: e6 D            ImageView
    % B: P9 [8 Q  R9 v3 j( O& V& I                android:id="@+id/img_show"! r$ n+ Y. ]6 f- s; H9 g4 g/ g! i
                    android:layout_width="match_parent"
    # \  L: D3 [/ v                android:layout_height="match_parent"
    4 c5 J; P3 a7 Z' B) f, `                android:scaleType="fitXY"4 y- V; c, D8 T2 ]
                    android:visibility="invisible">ImageView>& s4 E5 v. P9 z1 c: U4 C5 H" p
                LinearLayout4 P& O% ~" L6 q( x& n  i$ n  P
                    android:id="@+id/ll_video_btn"% R6 M2 k) e5 N% g; S
                    android:layout_width="match_parent"
    1 x8 h. k: R! [- M& j8 S8 H                android:layout_height="50dp"4 l& n; v0 G' y; ?
                    android:orientation="horizontal"; |! o1 _7 m5 ^! b
                    android:gravity="center"4 Z9 K+ w8 B) U2 o. ^! y
                    android:layout_marginBottom="15dp"
    ' }2 ^# n. a% m8 @8 N                android:layout_alignParentBottom="true"
    4 \7 B) X& U6 o) h/ w' M+ e9 M                android:visibility="gone">$ M: b' s& R/ V* }& p1 \
                    ImageView) s# R6 _) m. K6 @& N
                        android:id="@+id/img_video_pause"3 E8 f$ L% a, u$ _
                        android:layout_width="35dp"
    $ \9 P9 h; Q. G/ x0 ^. W3 p                    android:layout_height="35dp"; [/ u- ?9 M% n2 I
                        android:src="@drawable/background_stop_selector">ImageView>; L/ B! ~6 I, m, |. r! f8 |7 `
                    ImageView
    2 e. G* [7 M) v/ i$ S6 _                    android:id="@+id/img_video_play"
    ) L( _: A1 ?5 O4 r; ^: |                    android:layout_width="45dp"
    7 b, A8 X+ i' D$ v7 [  s/ y/ T                    android:layout_height="45dp"
    ) Z' {, R1 J, Y, V+ \( G4 D                    android:layout_marginLeft="20dp"
    + Y: H  ?( b; d& d. _3 h  ]                    android:src="@drawable/background_palyer_selector">ImageView>
    / q  a  ]' \0 Q( S3 c. n                ImageView+ N, y0 y* Z" y) e
                        android:id="@+id/img_video_stop"& p2 ^+ l6 }# j7 g3 G6 {% x
                        android:layout_width="35dp"# N+ m: l% O+ F+ a# a5 N7 J( |
                        android:layout_height="35dp"
    " L- t% o# M8 F/ ?0 C1 M2 M% q                    android:layout_marginLeft="20dp"
    7 c# V' I! l' L6 C- d# e1 N                    android:src="@mipmap/ic_reset_36dp">ImageView>
    3 C0 y# _+ z0 o! S            LinearLayout>
    " Q  p) A5 x) m+ F5 D1 a" q. \2 L' R- G        RelativeLayout>
    0 {" ^* W) G( k# U8 q    LinearLayout>
    " D3 ~7 c+ a% ?' u  e+ D7 WLinearLayout>. d% T% z1 V6 k6 [1 M9 m
    FileManagementActivity- o' F( Y+ d5 _6 a1 l/ z
    @Layout(R.layout.activity_file_management)
    - i  ]2 g1 P% n0 Y9 l1 Z, l8 h' Cpublic class FileManagementActivity extends BaseActivity implements View.OnClickListener {. c& Z9 Z5 c- f. g$ ?  }1 q
        private static final String TAG = FileManagementActivity.class.getName();
    9 b# R8 a5 d$ Y& {5 v* _9 P    @BindView(R.id.layout_file)9 O9 |# \" Y+ {$ a$ S, n4 s$ _
        View mViewLayoutToolbar;
    , e" r9 w4 I2 Q. J5 I" x    @BindView(R.id.tv_toolbar_title)
    8 a, B7 d' o+ F3 q9 m7 h# Q8 t: f    TextView mTextViewToolbarTitle;; U* A5 M8 A7 y: x" E/ V  O0 _4 A
        @BindView(R.id.ll_file)% b( f8 g+ n3 L# T# W+ Q
        LinearLayout mLinearLayout;, M; ], {) E5 S& M8 f5 t
        @BindView(R.id.rg_file_management)3 i" Q' Z6 [4 F* }+ m
        RadioGroup mRadioGroup;1 a7 f4 M8 a- z) Y2 `
        @BindView(R.id.rv_file_management)$ @+ _9 f* r# J$ W" o% [1 l! E$ f
        RecyclerView mRecyclerView;
    3 D# H8 W! I4 u  K* o    @BindView(R.id.img_show)
    * e' C& g9 `9 t    ImageView mImageView;! w. I  ^, B/ _% U. y; i9 K4 S' b
        @BindView(R.id.ll_video_btn)
      T# Z' S9 ^+ X. B. p    LinearLayout mLinearLayoutVideo;
    & s& ^$ E+ j) ~9 w3 b4 F    @BindView(R.id.img_video_play)! i, Z+ ^. X" b7 _
        ImageView mImageViewVideoPlay;
    % E8 d! Q* |3 M* W3 D1 \6 r* N  I    @BindView(R.id.img_video_pause)
    % A  b, V/ L, |0 n" b. X3 o3 m    ImageView mImageViewVideoPause;
    2 J( s; y$ P* u5 J) F! M    private FileListAdapter mListAdapter;
    $ Q. d4 L1 e; L    private List List = new ArrayList();
    0 \3 O9 W9 r# K! j/ d$ N    private List mediaFileList = new ArrayList();
    # o, [2 j2 t9 J3 F) m( z    private MediaManager mMediaManager;- ]' Y+ i9 V( m& g4 i
        private MediaManager.FileListState currentFileListState = MediaManager.FileListState.UNKNOWN;
    ( Q/ o& \6 s1 e2 E0 |    private MediaManager.VideoPlaybackState state;+ J4 d6 S* n3 }, p0 g8 |9 ]
        private ProgressDialog mLoadingDialog;8 f9 K: ?8 @6 L# `" I& O
        private ProgressDialog mDownloadDialog;
    $ h2 T' i: j% \& Z    private FetchMediaTaskScheduler scheduler;
    / B% v. C1 w; j; Q- O) b! \    private int lastClickViewIndex = -1;) e5 E- U; N; T, Q: w$ P& e9 [
        private int currentProgress = -1;( E4 t  b" |* T3 r4 V! M( l
        private String SavePath = "";' N" u: k  Q' s0 \+ `. V
        private View lastClickView;
    ' z( h2 v: C1 ~' w    private boolean isResume = false;
    : [8 N# c: v( ]4 p    private SFTPUtils sftp;( B2 f2 l# G& ]! O8 K2 A9 ^
        private SettingsDefinitions.StorageLocation storageLocation;
    & s8 |* z  {6 \  W    @Override& ^5 o, I+ |# R; E
        public void initViews() {
    3 u0 b& x- J  K' Z3 h9 W        mLinearLayout.setVisibility(View.VISIBLE);
    - J  Y3 i' ]& |4 i) O+ i        mTextViewToolbarTitle.setText("文件管理");$ j" m6 l7 A: A1 }
            mImageViewVideoPlay.setEnabled(true);
    6 Y' R* ?* N4 [& f" m# X& X4 w        mImageViewVideoPause.setEnabled(false);
    , A6 X7 P  ?; B/ H2 ]# d# L        mRadioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
    - `, e4 c8 K$ i) W; T: \. I/ O            @Override, I# R: T$ ^% @7 s; y
                public void onCheckedChanged(RadioGroup group, int checkedId) {
    ; }3 `7 L0 [9 L7 J) z% w                List.clear();" o* U( @* k1 T4 F
                    mediaFileList.clear();: ]3 _3 v" K/ \7 g
                    switch (checkedId) {9 i* Y0 y* H7 T7 l
                        case R.id.rb_file_all:, ^% N' D$ r% n& F1 }. P5 b
                            getFileList(0);
    6 `; ]- U, V& T                        mListAdapter.notifyDataSetChanged();
      x8 G& h) A' B9 L8 t                        break;" w3 U) B9 z/ O" t
                        case R.id.rb_file_photo:( F5 Q, [- A6 H- J+ ?6 S
                            getFileList(1);: ?& P3 I- ]; s7 O3 Y) t
                            mListAdapter.notifyDataSetChanged();- ?! O$ s; K9 x! O* @  I
                            break;
    ; y- U" _( c% b8 `/ X0 m+ N                    case R.id.rb_file_video:2 \, W* s3 i1 U+ W
                            getFileList(2);
    ! @( i& D* |4 x6 h) [$ @/ X                        mListAdapter.notifyDataSetChanged();
    / {! p+ I0 S- u3 A9 [                        break;
    1 ^- k$ f& {, `9 r' o                }
    ( Q6 O* P' Y, _8 ~6 H1 g1 _            }
    % y  ?4 u4 F' p) `9 o        });; a0 H7 c5 Q: W6 X$ E! D, K4 D
            LinearLayoutManager layoutManager = new LinearLayoutManager(FileManagementActivity.this, RecyclerView.VERTICAL, false);
    0 |0 M9 i1 P" f8 }; J        mRecyclerView.setLayoutManager(layoutManager);
    ) y+ V3 M' R. e/ s5 Z        //Init FileListAdapter
    , @3 d1 O1 w) E% E* I5 t        mListAdapter = new FileListAdapter();6 b4 y/ c" I1 H& I5 k8 E
            mRecyclerView.setAdapter(mListAdapter);
    7 o" A$ `1 Q$ h! k/ a$ @3 \8 Y        //Init Loading Dialog2 v8 L8 r1 s& m' F' r
            mLoadingDialog = new ProgressDialog(FileManagementActivity.this);/ V& L6 P- f1 l, {' l: M* ]
            mLoadingDialog.setMessage("请等待...");
    . q& w( `" Y$ s& \        mLoadingDialog.setCanceledOnTouchOutside(false);
    * v# e7 J/ P  J  k4 T  J) r+ K        mLoadingDialog.setCancelable(false);7 s. [! @! y+ Q  P& e5 f& \
            //Init Download Dialog+ f1 d8 d: J: H  P: X2 S, q8 h
            mDownloadDialog = new ProgressDialog(FileManagementActivity.this);
    $ V# Q" s# l) Q7 q: y' t1 I        mDownloadDialog.setTitle("下载中...");9 i) O9 R+ X- p. c8 ?8 {8 W. m! p
            mDownloadDialog.setIcon(android.R.drawable.ic_dialog_info);
    8 ~+ Q' q* G2 ^2 J( p        mDownloadDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
    ' o. ?3 K+ d) [* Y( ]8 y8 r% v2 g        mDownloadDialog.setCanceledOnTouchOutside(false);
    8 j7 H2 A3 s2 V: y( A* z0 O+ x7 @        mDownloadDialog.setCancelable(true);4 b* K6 w0 g! L" f2 i
            mDownloadDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
    " p% Z! J5 T8 \( y% O            @Override2 h0 B/ J7 s6 y) n$ K) `
                public void onCancel(DialogInterface dialog) {  C2 b4 d) u$ P6 I/ C' {* V. R$ U
                    if (mMediaManager != null) {; }2 B4 ~, i( r2 h$ f1 u
                        mMediaManager.exitMediaDownloading();
    - t4 W+ u1 _+ j                }
    / ?  B, f: p+ j* t+ t, X            }
    ! _# t: H1 J& a        });
    ) R- S" x4 }5 ^* I% C4 {3 u9 F        sftp = new SFTPUtils("49.4.79.249","uav","uavHHch@YREC.cn");. c# P! p" F9 P3 m7 k* R
            ReceiverApplication.getAircraftInstance().getCamera().setStorageStateCallBack(new StorageState.Callback() {0 L0 Y6 U9 l( [/ ]5 c
                @Override
    6 N6 r: ?' ?- u            public void onUpdate(@NonNull @NotNull StorageState storageState) {
    ( ?* b" z. B3 D! {5 q                if(storageState.isInserted()) {  i6 y* c6 X/ |7 w$ t4 R
                        storageLocation = SettingsDefinitions.StorageLocation.SDCARD;
    ) H5 g  ?3 y! x; d$ y, N* ?* N                    ReceiverApplication.getAircraftInstance().getCamera().setStorageLocation(SettingsDefinitions.StorageLocation.SDCARD, new CommonCallbacks.CompletionCallback() {
    / _/ m2 ]3 L7 n. n: R                        @Override# z0 Q* W, M7 \. }9 d5 v# `! B
                            public void onResult(DJIError djiError) {
    5 `/ d0 g' H5 V  n  r& C; ~% _                        }
    / K1 m+ L& r% X1 P                    });
    ' t" u3 W0 U* O% b9 d. b  u3 M                } else {( E8 F+ K! N  |5 x4 t2 A& e3 y
                        storageLocation = SettingsDefinitions.StorageLocation.INTERNAL_STORAGE;+ O/ j! F/ D9 j4 k4 `
                        ReceiverApplication.getAircraftInstance().getCamera().setStorageLocation(SettingsDefinitions.StorageLocation.INTERNAL_STORAGE, new CommonCallbacks.CompletionCallback() {
    . a+ W9 `- L' A                        @Override5 L5 Z3 Y$ ]; y# n0 i
                            public void onResult(DJIError djiError) {
    + F& q2 ?  Z. W- W: q- m                        }1 ~1 M' |* h7 S& d
                        });
    $ X1 x# Q& i) \0 C7 ~! `( E1 m                }
    & I% o, `$ A( {. ?7 A            }1 U: G" w' O1 Y! y; @
            });
    " K" t2 s" E' G" K; B9 S& u. }2 o" R    }
    7 I& _! ?0 N3 \6 c    @Override
    , R" s3 S; ~/ t4 L1 }4 @    public void initDatas() {
    ' B8 E: `) e3 `$ a( z! M0 u6 [2 k' l! V    }! b6 |: \9 m9 V. O: I6 V: x* H
        @Override
    6 v5 ]& U: H3 E; A; R    protected void requestData() {8 ^0 J6 e% y. m5 P5 V
        }6 q: J3 u, O1 E+ k) l+ `
        @Override- |3 W7 m' n1 Y0 k
        public void onComplete(String url, String jsonStr) {
    , `! d- b) e6 }* w* g; V" N        super.onComplete(url, jsonStr);2 ]  r7 c: F" e$ e" `
            switch (url){3 m9 I2 j! o6 h' x8 [( n
                case POST_VIDEO_INFO:% b- q; U( s+ j' v0 V6 _! e
                    break;
    8 e& G2 n5 i* a8 v0 w! \4 D            default:' H) `/ u% ~4 ]+ [
                    getVideoJson(jsonStr);( l* ]# H. B2 v
                    break;
    " X% D5 z( l4 {  \) K        }7 g4 ~  ^) q5 Z" X# ]7 e$ g( p
        }
    6 |$ d: W0 ]$ @2 L    private void getVideoJson(String jsonStr) {
    / c8 J: y" L! v/ Q" ?        VideoModule module = GsonUtil.GsonToBean(jsonStr,VideoModule.class);7 c0 }7 P5 \4 r& e
            if (module.getCode() == 200 && module.getRows().size() == 1){
    2 ]* w4 Q% P1 ~# K. C# ?            runOnUiThread(new Runnable() {
    3 X2 m4 l* q2 j% b                @Override& B  P4 K: T+ Y; |1 D9 K( T
                    public void run() {9 i* z! J9 u% S
                        UpdateFileModule fileModule = new UpdateFileModule(module.getRows().get(0).getId(),"/mnt/uavFtpFolder/"+module.getRows().get(0).getFileName());5 }5 R- M  B4 h) _% a9 p
                        http.getHttp(POST_VIDEO_INFO,"PUT",GsonUtil.GsonString(fileModule));
    ' \4 i" F1 ?! `1 a                }
    & D. o! z' w- \            });* E% }9 \0 d6 {- e/ Y8 r1 j5 t
            }
    # q# R" v+ P7 W, e8 Z. [9 G    }
    ; {5 v- J1 G! K" g- V( \# X& t    @Override! w8 ~% b3 d, n1 X- V. @
        protected void onResume() {- I: x/ O9 n: d' v
            super.onResume();
    5 e. Y) V5 z0 x% V        initMediaManager();' W( B+ j: V" ~, x
        }3 O) v( t6 ]# W% c
        @Override; A2 h5 N  o) v
        protected void onPause() {; @  z# D6 K0 x3 a4 T+ B
            super.onPause();
    8 |. n# |9 J4 B* c    }
    * d5 z- h6 `8 f0 y    @Override( b" Y$ M; c3 ]$ W6 ]
        protected void onStop() {
    . \  c0 n1 N6 \4 j: u& f' M: {        super.onStop();
    $ `/ T9 P" J2 r: p# [; D    }+ Q& ~9 h" N) O+ I4 I8 |0 _: x% Q$ u

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

    splrzdloa3i64015956124.jpg

    splrzdloa3i64015956124.jpg

    9 w4 H; Z) r& ^; n6 w" W8 x9 @( D* F6 t  c! C+ {7 a! Q

    szmxbq0ilqc64015956224.png

    szmxbq0ilqc64015956224.png
    1 Y2 Y; ^) m, h8 ]7 [# u1 d4 X/ n
    往期推荐LabVIEW OCR 实现车牌识别
    9 i* u% ~1 [; @  \* |和12岁小同志搞创客开发:有意思的激光切割技术) o' k, V- Y. d# A
    JavaScript+TensorFlow.js让你在视频中瞬间消失) |& {9 u+ T6 n" R9 r. ]1 M
    使用OpenCV测量图像中物体之间的距离% e! S: s0 {' j, X, R8 k1 c& v
    全网仅此一篇:工业级压力传感器设计及实现# p% W0 W8 L  s  H
    1 @9 e3 r& y1 B: ]8 ^" x- n/ k/ L: A

    libqpzwnv4k64015956324.jpg

    libqpzwnv4k64015956324.jpg

    ' J) y9 F% R! @: }' p% g( e: t

    eaw5giox2vj64015956424.gif

    eaw5giox2vj64015956424.gif
    3 H( s' e3 b7 ]* a
    点击阅读原文,更精彩~
  • 回复

    使用道具 举报

    发表回复

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

    本版积分规则


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