电子产业一站式赋能平台

PCB联盟网

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

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

[复制链接]

1001

主题

1001

帖子

8803

积分

高级会员

Rank: 5Rank: 5

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

tuvqh5dfafc6406117254.gif

tuvqh5dfafc6406117254.gif

4 P8 M! m5 k2 A9 l点击上方蓝色字体,关注我们" Q5 h# `3 U1 Z: Y: g$ P
6 e/ |) ]. Y$ z! O# J
上一篇文章(基于Mobile SDK V4版固件开发大疆无人机手机端遥控器(1))因为时间原因介绍了一部分内容,如果已经完成上一篇内容的操作就可以进行下面功能方面的制作了。自己开发的APP功能不是很多,但是已经将大疆无人机的常用功能进行了结合,同大家一起进行学习~3 a4 A! ^) h' g5 f5 H( [
1& M4 [6 n: S, e4 k, O& ~
应用程序激活与绑定
( s$ M+ [; Q/ U5 @7 B% a如果在中国使用DJI飞行器固件,则需要使用该用户的DJI帐户激活控制DJI飞行器的移动应用程序。这将确保大疆能根据飞行器的地理位置和用户个人资料,为飞行器配置正确的地理空间信息和飞行功能集。激活系统的主要是:
( M0 c; s5 _6 h5 f+ J
  • 中国用户必须在每三个月至少登录一次DJI帐户以遍激活应用程序。
  • 激活信息将存储在应用程序中,直到用户注销为止。
  • 登录DJI帐号需要连接互联网。
  • 在中国境外,SDK会自动激活应用程序,无需用户登录。
  • 另外,中国用户必须将飞机绑定到DJI官方app中的用户帐户。这仅需要一次。如果未激活应用程序,未绑定飞机(如果需要)或使用旧版SDK(
    % D; p9 d; S7 @0 D3 t5 Z! k% a
    / m' I* A. `2 F
    2
    ; d. n3 H8 i3 e& x' D& D# O- n/ |为应用程序创建UI编写MApplication、ReceiverApplication和RegistrationActivity文件(此处粘贴部分代码)。
    " }; X% k  U& |2 m, z- @public class MApplication extends MultiDexApplication {5 [6 Z7 `+ {) b5 O+ i) d1 O- g: V6 N) i4 w
        private ReceiverApplication receiverApplication;
    : ]( s" ~1 s' [3 k6 d8 M# M    @Override" r/ [0 g- e" @6 Q7 P5 S
        protected void attachBaseContext(Context paramContext) {; r+ q* n% V- a6 g* T3 y. v9 G
            super.attachBaseContext(paramContext);0 g  r# P% q4 v7 |: t$ Z& k1 D8 q) q: Y6 e
            CrashHandler.getInstance().init(this);! Z2 y* G6 z$ r& S* j
            Helper.install(MApplication.this);
    ( \' q3 X9 n0 G' O        if (receiverApplication == null) {
    1 G0 x0 q, u6 g1 y  y# |            receiverApplication = new ReceiverApplication();# g+ K8 N; z3 l+ a& n
                receiverApplication.setContext(this);
    # c# k$ _1 Q6 z( J* R0 Q5 {        }
    2 a! m3 y( f' I: }& f; A+ ^    }6 Z1 @0 m$ p6 K( B- u) ~
        @Override
    5 e3 x0 s9 k, t. X  x    public void onCreate() {
    : ?& o( Y* [' K        super.onCreate();
    - j3 e4 S: E4 e& U6 G        receiverApplication.onCreate();
    ; H1 `- T) s! L- h+ D7 z9 H4 u! x7 E    }
    - U% r& G& u$ `}; c4 P: Q) s, j# W& X6 c
    上面的代码实现了绑定当前APP,将后续需要用到的类函数封装到ReceiverApplication 中,在ReceiverApplication 中也能够进行账户登录的操作。
    ' ?  r$ E5 X- V: g- F3 wpublic class ReceiverApplication extends MultiDexApplication {  I4 w, Q2 |( Z9 T2 J
        public static final String FLAG_CONNECTION_CHANGE = "activation_connection_change";+ C$ A& H3 m: F. @
        private static BaseProduct mProduct;5 T) M' O  G: X9 Q9 x# r
        public Handler mHandler;
    & U9 e8 L" {, G    private Application instance;
    " n  A2 F5 n1 ]: i; P7 E( G    public void setContext(Application application) {1 ]1 L1 B4 @- C8 s( z6 F
            instance = application;7 o" y, @+ n2 ~7 ~
        }  z( N! t9 A; T4 H( O
        @Override
    + c1 A7 {0 P0 x" f7 a    protected void attachBaseContext(Context base) {
    8 w, s1 |& l6 v5 v% i        super.attachBaseContext(base);
    # |& V7 h( z5 s6 z/ f        Helper.install(this);
    6 b" C. j: w0 Z  u" D    }+ W" l: [- o& h- I1 d1 t( n
        @Override
    ! Z7 n6 r  \/ D6 D0 R    public Context getApplicationContext() {
    3 W5 u7 b- F5 [# _9 S        return instance;& {0 a5 G& Q+ l& r+ M4 j. ~
        }
    8 ?; x6 t3 H; Y  ~! u. N7 A    public ReceiverApplication() {
    - n2 o6 F: P; a$ q) s    }, d$ l1 b! W& a8 ^
        /**# g1 B9 w  p: v
         * This function is used to get the instance of DJIBaseProduct.. D8 C$ U7 A" w$ P
         * If no product is connected, it returns null.7 V, {6 o6 Y- O) J1 [; \( g, r5 W
         */
    * X- y8 @3 o5 c  G* c; G    public static synchronized BaseProduct getProductInstance() {
    ' S2 ?, _8 q) l7 d% Z6 k, B# `& p1 j        if (null == mProduct) {
    # Y* z/ {' p. c# U            mProduct = DJISDKManager.getInstance().getProduct();
    ! c$ @& s, \! t! q  [! w        }
    ! ~3 Y& c2 Z  r* P) x5 }. h* w        return mProduct;
    - i/ z3 z" z5 [4 {  b8 N    }
    1 o# [* k" U* X; R& C! e8 f    public static synchronized Aircraft getAircraftInstance() {
    , i0 e5 C8 I) H* f- L9 R        if (!isAircraftConnected()) return null;
    4 J, b4 O6 r3 V4 R5 Q        return (Aircraft) getProductInstance();
    3 ?' p! G7 t/ ?* d* f1 D( {    }4 R8 C" T. L6 Q6 t1 O  S
        public static synchronized Camera getCameraInstance() {
    ( c6 M. W+ r; C4 l# Q" I  ?        if (getProductInstance() == null) return null;
    + M, K  ]; x( G" q* P$ n% R        Camera camera = null;9 L6 b( d! R& D* h9 b
            if (getProductInstance() instanceof Aircraft){
    , I* S' m8 C- i8 h+ j( }: T            camera = ((Aircraft) getProductInstance()).getCamera();
    " w1 q3 G; Z, ^) R        } else if (getProductInstance() instanceof HandHeld) {
    / B! n+ S9 ?7 c% ]3 a            camera = ((HandHeld) getProductInstance()).getCamera();
    6 [' N  C  |# S4 Q        }
    % N4 i% F) K: n" G        return camera;# v( B! X: r+ D( v% T) {
        }
    : R* h  d' B$ w: ^9 u    public static boolean isAircraftConnected() {. Q1 v2 H1 f" n& P& |# Q- W! \* C
            return getProductInstance() != null && getProductInstance() instanceof Aircraft;) l" j5 j# E- a# Q1 {
        }
    6 W: A8 S, S/ E9 ^- X. _7 R$ k$ C4 ?    public static boolean isHandHeldConnected() {, x# a* u3 _: w) i9 }
            return getProductInstance() != null && getProductInstance() instanceof HandHeld;
    3 ]" u% g/ g& s5 T& n7 J8 d" k    }/ v% M- [! s: X0 e$ x
        public static boolean isProductModuleAvailable() {- N7 P3 G- f  @5 |& E: d* E
            return (null != ReceiverApplication.getProductInstance());3 _) t' _' G: H# T
        }0 Q8 p' Z+ C4 t
        public static boolean isCameraModuleAvailable() {, U7 e. s' w! s/ U5 p" a" E
            return isProductModuleAvailable() &&
    ' i6 n- U& _1 T8 I1 f& c                (null != ReceiverApplication.getProductInstance().getCamera());
    3 w. {# U8 G+ j* z" @    }8 Z; O3 f6 G+ [- a, \4 [8 I
        public static boolean isPlaybackAvailable() {: H1 U. ?4 q" y1 O! q6 z' }
            return isCameraModuleAvailable() &&5 ?! q& j9 j3 g4 J% E
                    (null != ReceiverApplication.getProductInstance().getCamera().getPlaybackManager());
    ; J- J% ?' l8 _( j) z, e9 [    }
    1 _: c3 u" w- e4 S    @Override4 o' @7 }  X/ x" @- N; X1 w. t
        public void onCreate() {
    , j0 h; g' b+ Z& B( g        super.onCreate();6 q# @* K( s) |7 V
            mHandler = new Handler(Looper.getMainLooper());
      U2 d% @- D; R" N3 Y, T( n        /**
    : M9 s  N, r' \  K: c7 ?         * When starting SDK services, an instance of interface DJISDKManager.DJISDKManagerCallback will be used to listen to
    ( V5 j, n6 B. }) K5 V         * the SDK Registration result and the product changing.
    . x+ K/ I9 e% P         */
    9 _( `+ P9 [8 G, L+ t) ]        //Listens to the SDK registration result
    ; c4 V5 S0 E) ^- }& Z) V' S3 @        DJISDKManager.SDKManagerCallback mDJISDKManagerCallback = new DJISDKManager.SDKManagerCallback() {9 h% H# b- g* ?. e/ Z$ N/ K
                //Listens to the SDK registration result2 n7 J: z% M0 K' D. E0 V
                @Override
    * ~8 X9 t/ C' l$ i            public void onRegister(DJIError error) {$ n! ~( |, ]0 p3 N
                    if (error == DJISDKError.REGISTRATION_SUCCESS) {, {$ Q2 Q1 s2 ^
                        Handler handler = new Handler(Looper.getMainLooper());
    & u. T2 F' n- E7 p4 H                    handler.post(new Runnable() {
    & D# u& \# L  c% F% ?7 ^                        @Override
    7 J& v: y' `* z3 K" C9 \                        public void run() {
    ( I% r0 n# |& n) V//                            ToastUtils.showToast(getApplicationContext(), "注册成功");  e+ O0 l2 H( a3 }4 v& M
    //                            Toast.makeText(getApplicationContext(), "注册成功", Toast.LENGTH_LONG).show();
    ' s! v; C. u/ d# ~) v9 M  t//                            loginAccount();  B, p$ _. e5 B6 I& {
                            }
    + T$ A# @0 F) m* Y* y) I                    });
    4 [+ d, O# }1 C; E2 b; i, l                    DJISDKManager.getInstance().startConnectionToProduct();+ f2 A6 N) s- J
                    } else {3 H/ m( f5 V5 X; @+ i
                        Handler handler = new Handler(Looper.getMainLooper());" q* F/ {1 k2 I2 H- Z. d9 K
                        handler.post(new Runnable() {) h2 a' x" J# g
                            @Override
    * }9 d9 ^$ ~1 o. s7 c( K* Z                        public void run() {
    ' ]3 C9 j" {- _- h//                            ToastUtils.showToast(getApplicationContext(), "注册sdk失败,请检查网络是否可用");0 u! O0 [- l6 b
    //                            Toast.makeText(getApplicationContext(), "注册sdk失败,请检查网络是否可用", Toast.LENGTH_LONG).show();& P& J) }7 I- _
                            }' n5 `) G% C6 y" r
                        });
    1 o: C+ l5 f1 L  m: q$ v9 X* R$ M                }; S5 Z, P2 z4 B* V/ G2 N+ H
                    Log.e("TAG", error.toString());
    - A4 [1 q1 W) Q  @% [            }" |9 S9 O& H2 ^3 X
                @Override( m$ B7 |+ [4 p, @
                public void onProductDisconnect() {
    $ {( ~7 ^. T+ U/ z                Log.d("TAG", "设备连接");' u+ L: j. I' {
                    notifyStatusChange();! O2 X4 Y. C# Y- S
                }
    ( C/ [8 V6 e: X            @Override7 i, U( c: b/ m, W) {$ E. q( A
                public void onProductConnect(BaseProduct baseProduct) {+ ?. u4 @  ?! g
                    Log.d("TAG", String.format("新设备连接:%s", baseProduct));4 S2 {& b3 ~& G4 w6 `, k
                    notifyStatusChange();# m1 Y. E! _( S/ a7 t
                }
      l5 V( a  X# k# Z2 D& I  O# E# K            @Override5 D1 X+ B6 }4 j$ w
                public void onProductChanged(BaseProduct baseProduct) {% `1 `5 t% W, \0 |) |+ k  e; x: d4 E- i
                }  P' U0 A9 X5 G5 K
                @Override
    # i' i/ o, G6 W            public void onComponentChange(BaseProduct.ComponentKey componentKey, BaseComponent oldComponent,0 ?. o; `2 S! r: w
                                              BaseComponent newComponent) {
    2 ?) q) R; q! G! A' j2 ^% c# G- O5 H                if (newComponent != null) {
    : b% m1 a% j4 R; n8 s+ O                    newComponent.setComponentListener(new BaseComponent.ComponentListener() {
    ( Z) O$ ?8 k, Z# r                        @Override
    3 p: V) ^" `+ q2 z& C                        public void onConnectivityChange(boolean isConnected) {  Y: @8 t4 N3 }
                                Log.d("TAG", "设备连接已更改: " + isConnected);
    # ~0 v% M7 v, ?1 c                            notifyStatusChange();+ {2 P. R# g+ o, [) \2 c$ V
                            }: b. l2 l2 z& H; f# a
                        });! s7 A( f- `# E
                    }  P; K" o+ [$ ^" s# s
                    Log.d("TAG",3 l: P# y* ~! w' v0 U, \8 ?2 Q" W
                            String.format("设备改变 key:%s, 旧设备:%s, 新设备:%s",+ o, Z4 g. k# q: }
                                    componentKey,0 ~, D( Q/ l+ }1 c1 A& i
                                    oldComponent,
    # u2 e2 S! P  J2 f$ B6 ?: z                                newComponent));
    4 @1 I7 l7 a3 n3 B  o& P* w            }5 _- ]3 A1 g* W9 q  o
                @Override
    , B, d8 Z# k4 O1 C. j+ Q* Y- `            public void onInitProcess(DJISDKInitEvent djisdkInitEvent, int i) {
    % Q) H. v1 d3 ?: v            }
    - w+ ]% x, r; H* G            @Override
    . S  T1 Z' {, ~3 w            public void onDatabaseDownloadProgress(long l, long l1) {
    6 s" Y6 S( b. t  X            }
    . d2 l" I; c' v& p/ U        };& l. E# ^* o* O3 ?: W8 q
            //Check the permissions before registering the application for android system 6.0 above.
    : V) {( b/ ]" K/ a4 [3 j, L$ P        int permissionCheck = ContextCompat.checkSelfPermission(getApplicationContext(), android.Manifest.permission.WRITE_EXTERNAL_STORAGE);
    " O( Y2 |2 {! M! p5 l! t$ J        int permissionCheck2 = ContextCompat.checkSelfPermission(getApplicationContext(), android.Manifest.permission.READ_PHONE_STATE);
      v* }& P3 f6 h" N  o2 g6 P        if (Build.VERSION.SDK_INT 0 && permissionCheck2 == 0)) {
    ' o3 v# Y) N* Y4 {8 p$ g5 D            //This is used to start SDK services and initiate SDK.8 U/ B' L' d( c: V$ r
                DJISDKManager.getInstance().registerApp(getApplicationContext(), mDJISDKManagerCallback);& j4 ], U# Z# R- L' l& O+ _
    //            ToastUtils.showToast(getApplicationContext(), "正在注册,请等待...");) W, x, n# b5 Y) d6 [% s2 V+ t
    //            Toast.makeText(getApplicationContext(), "正在注册,请等待...", Toast.LENGTH_LONG).show();
    4 t+ }1 W( Q8 e        } else {3 |* ^* s& @9 V6 I* @( ~
    //            ToastUtils.showToast(getApplicationContext(), "请检查是否授予了权限");
    5 ~6 p6 R. V+ p1 y//            Toast.makeText(getApplicationContext(), "请检查是否授予了权限。", Toast.LENGTH_LONG).show();
    ) U# [8 k3 E& ^5 D5 i$ r$ k( N        }" \" }/ P( I- D0 b$ [+ R& {
        }4 `; L0 H  w' M1 [
        private void notifyStatusChange() {+ J8 q0 m% [8 @; ~
            mHandler.removeCallbacks(updateRunnable);
    ; K6 h  z8 K2 a- p) U        mHandler.postDelayed(updateRunnable, 500);
    ' U8 `! o! z. H; }0 f0 d6 u    }# S0 B/ f8 f5 Q3 V1 g3 X
        private Runnable updateRunnable = new Runnable() {
    ) S. O4 j# T* a' `        @Override3 H5 u) j4 _( o/ }5 b( r6 p( e- R" s
            public void run() {! K& s$ C# _$ {0 H9 s1 F  x
                Intent intent = new Intent(FLAG_CONNECTION_CHANGE);# X! o/ g5 ?* y+ t( t4 R
                getApplicationContext().sendBroadcast(intent);
    & Z. W" I  a/ e7 q8 q        }
    ( J* l$ @; Z+ |+ n    };
    ' O) j, C, j; F}. @6 [$ R) W" f3 W* u) I0 F
    上面的代码是对BaseProduct、Aircraft和Camera类进行实例化,在后续使用中不用再去进行重复的实例化工作,减少内存的消耗。
    - o- m# r7 w1 u! m  [9 L6 k@layout(R.layout.activity_registration)
    9 u. u* }  X! _/ G" x: Spublic class RegistrationActivity extends BaseActivity implements View.OnClickListener{
    4 n) Q& Z- ^: R9 X    private static final String TAG = RegistrationActivity.class.getName();! [' J8 a) _2 P
        private AtomicBoolean isRegistrationInProgress = new AtomicBoolean(false);
    2 p( v$ b5 a! ]8 g! D1 v& u9 h    private static final String[] permissions = new String[]{
    " U3 [% m) ~5 [7 `- ]- V. e7 S            Manifest.permission.BLUETOOTH,& C% x) E4 h; M1 M+ h; e
                Manifest.permission.BLUETOOTH_ADMIN,
    9 I/ u' N! \6 ]& a1 o            Manifest.permission.VIBRATE,4 o3 k4 O9 {* A$ ?- a
                Manifest.permission.INTERNET,4 [2 T3 w) c4 L0 h# J
                Manifest.permission.ACCESS_WIFI_STATE,
    ( M( J- R8 u$ x8 k6 i            Manifest.permission.ACCESS_COARSE_LOCATION,
    8 }; Y' b9 s* n. F; y4 i+ H            Manifest.permission.ACCESS_NETWORK_STATE,
    ! T9 E8 I7 |; P% W* I            Manifest.permission.ACCESS_FINE_LOCATION,
    & U) A2 G6 B, ~            Manifest.permission.CHANGE_WIFI_STATE,
    # Y. ?& a( e, a            Manifest.permission.RECORD_AUDIO,
    ! a! P% `/ R) o( r1 E( E# T( D            Manifest.permission.WRITE_EXTERNAL_STORAGE,
    2 }3 C; ?! h! Z2 C+ w. ]            Manifest.permission.READ_EXTERNAL_STORAGE,
    : q. t; R+ U* C! b; Q$ u            Manifest.permission.READ_PHONE_STATE,8 X& P/ F, K3 C$ F6 k
        };6 Q8 ~2 o4 U5 q) }# \/ }( f4 m: l

    # O& X( b8 J  b- N    @Override0 G  `( @9 \6 u3 ]
        public void initViews() {
    ; P# |! c4 n7 |. Z# W0 o4 t5 f        isPermission();
    ! f2 Q0 A5 _0 Q; d! j        IntentFilter filter = new IntentFilter();4 [% V$ s; p2 _# D( [
            filter.addAction(ReceiverApplication.FLAG_CONNECTION_CHANGE);6 ^* p7 t9 p- \5 m- S
            registerReceiver(mReceiver, filter);2 B& h' B* i5 s; D; t3 K
        }
    * \' H3 p0 x- s3 x+ r    @Override% I- d5 w% r8 A0 q+ m
        public void initDatas() {1 T, J% L* C% R  W
            startSDKRegistration();. l, }2 N; e# C% E# ]' ]
        }. y# }, [$ z# H# ~6 X7 W% E
        @Override
      n7 M& N& \# N5 p! v4 e! k7 D* w3 U    protected void requestData() {% O0 C/ }& N7 [5 N
            
    2 s5 L- P5 @, \2 d2 q* [: Z4 s    }
    5 J3 E! \- L- w8 p7 F4 t. Q
    * q/ L* |$ v$ ~( n' z/ W    @Override
    3 U) q* w/ q! a    protected void onResume() {2 m$ K) p" d; h* @
            super.onResume();
    & l' L7 }; L. H    }
    & N# G2 M: \1 z: m3 k
    " j/ v2 V" G6 e: o    private void isPermission() {& P! S6 w( x. J7 V6 F
            requestRunTimePermission(permissions, new IPermission() {2 q+ g7 P- R' c$ P3 V1 |
                @Override) ^5 D- ?: p% L4 P# m2 V- a6 P* }
                public void onGranted() {
    . a2 Q6 C( i2 y' ~! }6 _1 y: n            }, d9 `! K. s1 G9 e7 n* U' K" Z2 @
                @Override
    ) y/ n5 d- t3 [            public void onDenied(List deniedPermissions) {
    5 x0 {$ i; }' ~3 W. D5 T            }
    ( ?+ Z3 u! @) ]7 i        });6 Z' j0 C+ @: N5 X0 y1 D$ q
        }
    5 \0 c3 _( ?( F2 T0 A7 v1 u  
    % J0 f- r0 c9 h* G( r. _$ Q    //无人机首次注册
    . u, `6 y- k% I4 w6 }! I1 B$ c# z5 `        private void startSDKRegistration() {6 N# Q! w# M6 X- N& u
                if (isRegistrationInProgress.compareAndSet(false, true)) {4 K  H( L9 @# V. i" \
                    AsyncTask.execute(new Runnable() {( Z+ w" w- K. i7 \8 E+ r
                        @Override
    ( E& S! f& m9 q% }) {4 B                    public void run() {
    + K6 E  S0 f, ?6 v. u//                      showToasts("注册中,请等待...");% b0 e0 o, v7 a+ g! ~9 ?" f1 d
                            DJISDKManager.getInstance().registerApp(getApplicationContext(), new DJISDKManager.SDKManagerCallback() {( }! ?' }! L& L2 q+ a7 \
                                @Override  F, \9 d& R. z' k
                                public void onRegister(DJIError djiError) {0 s1 N, v7 `* L
                                    if (djiError == DJISDKError.REGISTRATION_SUCCESS) {8 k) X- E5 ^' l( r! P
                                        DJILog.e("App 注册", DJISDKError.REGISTRATION_SUCCESS.getDescription());
    % A0 p& Q0 Z  q, J6 w4 Z7 t                                    DJISDKManager.getInstance().startConnectionToProduct();5 W- u! j) J; K5 H: n$ ^) R( F
        //                                showToasts("注册成功");
    ( {, J0 ]/ h$ F' X                                    loginAccount();) J% E7 B/ H1 B
                                    } else {" J2 Y- Q" e3 _9 X7 _
                                        showToasts("注册sdk失败,请检查网络是否可用");
    9 {) q* p* e  O( r! T6 O5 O  d                                }/ I! j" z+ q9 K* C& G% `+ C
                                    Log.v(TAG, djiError.getDescription());! k* a& u6 Y1 Q: D( q3 ^4 ?( B1 t# n
                                }/ }( a3 S3 w# p9 g9 Q' Y
                                @Override* Q, z. x3 e9 j" C
                                public void onProductDisconnect() {/ `9 W6 x% o9 ~3 J* }5 i
                                    Log.d(TAG, "产品断开连接");% z/ i. A. Z% t# ]; ~* d
        //                            showToasts("产品断开连接");! N' P6 c8 R$ ?* w
                                }! I8 ~1 Y' i) m+ Y7 D7 B
                                @Override$ f3 b& ]. w$ I1 y
                                public void onProductConnect(BaseProduct baseProduct) {3 k, `, v- |6 U- j* D# X
                                    Log.d(TAG, String.format("新产品连接:%s", baseProduct));* z- F& s+ |- w1 N; d8 V
        //                            showToasts("产品连接");
    3 h* O% M5 L( n2 T: {                            }
    3 g* n. l# `3 F                            @Override
    / u, L! `3 U8 _* W6 k! x# y                            public void onProductChanged(BaseProduct baseProduct) {
    " O- Q- T9 E: b                            }- X9 B# C8 m0 `) r
                                @Override
    ; U& V0 v2 Q8 F                            public void onComponentChange(BaseProduct.ComponentKey componentKey, BaseComponent oldComponent,& U# Y3 @6 F8 A. P+ L; g# m
                                                              BaseComponent newComponent) {/ v' g6 h# U  d/ k4 g6 @
                                    if (newComponent != null) {
    ' X% r6 A1 |% V4 m: n" a                                    newComponent.setComponentListener(new BaseComponent.ComponentListener() {. Q- G! ]% V1 l' J+ o
                                            @Override! {$ ^7 k' w4 f/ s/ m! Q
                                            public void onConnectivityChange(boolean isConnected) {
    + j5 {- a: c- J9 r6 Y$ R: }                                            Log.d(TAG, "组件连接已更改: " + isConnected);# D2 K. N- Z; s6 A
                                            }
    5 ~* n' `" B( M- _9 c  m6 a                                    });
    6 U2 ^9 X$ v" t5 N; D                                }. _" D4 {0 k. x( L
                                    Log.d(TAG, String.format("改变设备Key:%s, " + "旧设备:%s, " + "新设备:%s",1 ~8 \% U( E' \  E5 J
                                            componentKey, oldComponent, newComponent));( s0 t8 V- x4 b7 s
                                }8 V: ?( |& X7 z  ^
                                @Override
    5 f# O$ j/ K. h/ _                            public void onInitProcess(DJISDKInitEvent djisdkInitEvent, int i) {
    ; v+ H' Y3 `* T! }                            }
    ! z6 A9 F# i/ T. O4 G0 i                            @Override
    , A0 ~' I% i1 a* `                            public void onDatabaseDownloadProgress(long l, long l1) {. o( D! ~' b# d6 h( z/ M' @
                                }
    ' k) d) K! F  Q' T* Z' p                        });
    * L0 J. K% [7 \; R& [( C% d                    }
    ( c: ]3 ?! p6 e) r) ^+ @' Y                });
    # ~) \- v' v/ O9 M3 g- P% z            }3 k9 g4 k9 `& |1 l; Z
            }3 c' z8 I, g( l: v9 H' I
        protected BroadcastReceiver mReceiver = new BroadcastReceiver() {
    + D& G- C* [! V        @Override8 H# S: ]: Z! `! R# y" i" D1 a
            public void onReceive(Context context, Intent intent) {2 X3 m0 N2 G% J" ~5 \6 U% s
                refreshSDKRelativeUI();3 M* v! p+ Z8 f$ S
            }5 }# B( u6 \8 J. H
        };
    0 s8 n, G5 ]) ], t    private void refreshSDKRelativeUI() {6 D; a" g$ c& F8 p2 d( c
            BaseProduct mProduct = ReceiverApplication.getProductInstance();: L2 R  c. b8 x1 z$ w
            if (null != mProduct && mProduct.isConnected()) {
    ) s4 ^6 L5 N% }( I6 o            Log.v(TAG, "刷新SDK: True");8 x% g. X3 K6 C( p( ]. v. V
                mButtonFlightTask.setEnabled(true);  M" _: w( n1 L2 v7 X
                mButtonSettingRoute.setEnabled(true);
    , c! v- O. s2 _: r$ E" E  r4 T            mButtonFileManagement.setEnabled(true);' n/ p; J2 [, x& q5 U3 Z
            } else {
    1 H* ?% K3 c( q' S# S6 `9 p- S" S            Log.v(TAG, "刷新SDK: False");: u4 h+ `5 E1 ?5 u
    //            mButtonOpen.setEnabled(false);
    $ c% S. S  ~% _* t* a: g. j//            mButtonSettingRoute.setEnabled(false);- W+ h! N' V. S- L* B- r
    //            mButtonFileManagement.setEnabled(false);
    ; h( |& D, L" ^" T5 C7 G0 \//            startSDKRegistration();
    . e& @! x; F' F3 p% E& ^( Y        }
    ( B3 M- @; n( L1 @$ Q  J% t    }
    * i  F) f  o3 @1 G2 B6 b5 \    protected long exitTime;   //记录第一次点击时的时间
    ' j: U6 t6 [# E% G. B    @Override4 P$ a, T; v7 o+ H+ a, S, {6 N
        public boolean onKeyDown(int keyCode, KeyEvent event) {
    " d$ |5 R: ]' {" r: Y9 A& E        if (keyCode == KeyEvent.KEYCODE_BACK
    4 ^  {0 a% k% {" V/ P7 G" b& N                && event.getAction() == KeyEvent.ACTION_DOWN) {( b8 q9 @4 z- t; a0 `
                if ((System.currentTimeMillis() - exitTime) > 2000) {* y4 T7 t9 |/ E8 u
                    showToast("再按一次退出程序");
    " m% K0 A  D6 T: Y) g/ I                exitTime = System.currentTimeMillis();6 a9 x& r" y) B
                } else {
    ! b! X6 R& Z9 J; c                RegistrationActivity.this.finish();- y8 a) x/ D. m- _; p$ L
                    System.exit(0);8 m3 m3 ?% m6 o0 i, G5 A( L
                }) A. M* Q% J# f7 L
                return true;
    . d  Q& f3 U! [# y& b        }
    : }  X9 n. _* Z  j4 @        return super.onKeyDown(keyCode, event);
    ! |* B0 A# L. h$ B: q    }9 n& L) C3 Y3 z
    & N$ z( j. D2 j$ o0 c$ L
            private void loginAccount() {3 j  Y* x4 L: f
                UserAccountManager.getInstance().logIntoDJIUserAccount(this, new CommonCallbacks.CompletionCallbackWith[U]() {, C: ^4 C1 m4 Z8 G" _3 n0 F
                    @Override3 ~. B- |- T; m) _3 R! w6 w
                    public void onSuccess(UserAccountState userAccountState) {2 X  j) x' V- f4 q# b. p8 T/ |
                        runOnUiThread(new Runnable() {+ G' p4 _) K  G7 q+ f7 }/ T" H9 k
                            @Override
    3 [# B6 t5 i9 C5 s, U3 {4 o                        public void run() {
    0 c3 r# A: G( }2 Y  `                            mButtonFlightTask.setEnabled(true);
    ; ^& j+ F4 O# w! Z5 F8 R0 @                            mButtonSettingRoute.setEnabled(true);
    , I; m- J4 Z: `; k                            mButtonFileManagement.setEnabled(true);
    8 Q- [, e' t% Y% q  e4 M8 }                        }; [2 a. I+ I$ F
                        });
    0 h7 @3 R7 Z! ?  }( |                }* Q  c6 N- D" C8 ?" x
                    @Override, o* L/ B4 Y3 a2 R/ `' |9 B# i, t
                    public void onFailure(DJIError djiError) {# N. [* ?1 O* d, V# u& N9 o
                    }  |( O! [; x& F/ F
                });
    ! `0 @' G. P! Q& B. P/ e1 ]& p1 c        }: H! ?4 c, n, X: m8 [
    }
    3 W% W2 N. G3 ~0 k( o6 Q上面的代码就要进行第一次注册登录了,当然你不需要自己去设计登录注册页面,大疆会调取自己的登录注册页面供你使用。
    , z, I3 Q( e' q( N0 ^3 o8 I1 Y

    b0cuun3oznz6406117354.png

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

    ' v1 ?6 o3 n$ g* S    //直播流推送. ^1 t; ~! k4 ^$ m( R, l
        @RequiresApi(api = Build.VERSION_CODES.O)
    4 T- L7 B2 c- w6 ^% G    @OnClick({R.id.img_live, R.id.img_show_back})
    . i# W: s2 _* v! G9 V5 T* @5 A    @Override% `" k. R8 _6 l' x' z$ N1 x  i) j
        public void onClick(View v) {
    9 i" S. ?3 }# u% o: }8 u' c- W        switch (v.getId()) {7 h. q4 M% M* i7 P, o4 F; n
                case R.id.img_live:
    + ~7 v4 X) b% M5 x; {  m! D                params.clear();1 [" G: i; j5 v0 B: W
                    mapData.clear();& y1 ?8 M  S7 `8 d9 x
                    if (!isStartLive) {! J0 p* A" |+ L: r' J9 i4 f
                        if (!TextUtils.isEmpty(mSharedPreUtils.getStringSharePre("rtmp_url"))) {* m/ {6 d1 ~4 K
                            liveShowUrl = mSharedPreUtils.getStringSharePre("rtmp_url") + trajectoryId;
    $ |) N2 M1 U5 B4 R% J//                        LiveModule module = new LiveModule("liveStreamStateChanged","plane",planeId,true,trajectoryId+"");
    / l% _) e9 D% g8 M# x. M                        MyLog.d("地址:"+liveShowUrl);& z0 Q9 o6 t& j
                            startLiveShow();% n( s% E/ O. E( B, p) R1 G" I
                            isStartLive = true;0 P7 R3 X& K0 e
                            showToast("开始推流");" ^3 t$ d: l) g6 G: [
                        } else {
    # c6 x: H( L1 o( Y7 D                        showToast("请先进行系统设置(RTMP)。");% b# i- a3 H+ k/ b
                        }) b8 d  ?6 B; b$ o3 J" ]
                    } else {% b' m8 S8 {+ S* Y/ X; J6 X
                        stopLiveShow();
    4 \9 Z0 x6 c/ ?  w5 g/ E                    isStartLive = false;( I" Z) B+ y' T/ [3 J
                    }
    8 y- z* `2 x! C6 c0 M                break;" `% g- l/ L" p
                case R.id.img_show_back:
    7 ]7 J7 I# X6 B; X/ g, W' p, p//                controller = null;" i. `( K# C$ J7 B; t
                    closeConnect();6 D1 R' }- y5 ?) V$ H
                    MainActivity.this.finish();
    ; u7 E' t' z% {1 F$ i2 u                break;8 I( E4 }6 w$ {/ N! j3 K
            }$ o* R& N1 P3 C6 ^
        }
    ' `( v  ?) w7 u6 @$ L    private boolean isLiveStreamManagerOn() {
    6 h# M& m' F3 e; O. v5 C) E" V        if (DJISDKManager.getInstance().getLiveStreamManager() == null) {
    * Q2 |! N! @* l" q            return false;
    " g% J9 D4 ^& R7 p, }. H( r  X, A+ e. h        }- ^5 d; l( G6 U# R4 N. K! }6 p
            return true;' j7 p% r# ~* N- V; C7 Z
        }5 L. g$ t, q( e- w: m( [
        private void startLiveShow() {# u+ U5 F( @' h, c' s$ P
            if (!isLiveStreamManagerOn()) {& y" p. C4 y' X% ^  H; r
                return;* r7 f2 \, P3 l7 B9 l. l' G
            }
    3 b# c6 U- M# d3 s& S1 K        if (DJISDKManager.getInstance().getLiveStreamManager().isStreaming()) {
    # K3 [. [7 @" k& F            return;
    + H; _& [. l% e3 `        }
    0 k8 u" L- \$ k; M9 U2 ?4 v        new Thread() {
    9 f! t  }2 T* T* [  [            @Override5 t2 |( ~& r/ m7 ~  h1 _
                public void run() {! j" V; n9 f: `  [
                    DJISDKManager.getInstance().getLiveStreamManager().setLiveUrl(liveShowUrl);
    $ W  ?9 f% |8 T  q! R, Q2 G2 x9 a                DJISDKManager.getInstance().getLiveStreamManager().setAudioStreamingEnabled(true);; X8 L7 ~% O% P4 a! [9 j
                    int result = DJISDKManager.getInstance().getLiveStreamManager().startStream();
    , e8 J4 ^6 y/ ^1 r8 o' m0 ^                DJISDKManager.getInstance().getLiveStreamManager().setStartTime();
    / W. i8 j) U( D% X            }
    4 B  I: S; w3 U) P- ?- }        }.start();, H$ _/ f9 p9 K! n/ P; Z1 |
        }
    * k0 W& s' ^" d% W: i    private void stopLiveShow() {
    , r- h9 u: U- k* _! h! n  k/ t5 b        AlertDialog.Builder Builder = new AlertDialog.Builder(MainActivity.this);
    4 U0 f* p  l7 k/ |( T, {        Builder.setTitle("提示");
    / X5 O3 [' r: R2 y        Builder.setMessage("是否结束推流?");4 ^5 f  h7 H- K. R! ?. ?( p+ s
            Builder.setIcon(android.R.drawable.ic_dialog_alert);
    ) M" ]' d! O5 }3 G+ m* R$ C        Builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {
    5 d2 S. \! P  ~: _4 |            @Override2 L9 D0 H, L  s  U; P+ o
                public void onClick(DialogInterface dialog, int which) {
    0 o1 W- e+ S: m6 ^, C( o                if (!isLiveStreamManagerOn()) {
    " U& W( e4 ~# v; r/ G7 p- m. v; X                    return;
    2 F4 V: Y2 s. I9 e3 D: _. q8 u" `                }  n1 e- S5 p, r  g
                    DJISDKManager.getInstance().getLiveStreamManager().stopStream();& u2 S% Q; _* [7 k- Y; p6 h+ t) c
                    showToast("结束推流");
    5 K' l3 q1 L0 Y# }) V9 r            }
    - m2 i; d9 p# w2 [        });
    ; m& E# r0 L: M5 M8 T        Builder.setNegativeButton("取消", null);3 |3 t4 i/ d7 l
            Builder.show();' r! y" H, K' }1 s3 g8 T
        }
    " r9 C- J9 I: B. J9 ~0 w! {$ z6 J3 I, P1 z5 V1 g2 Y
        //获取飞机信息、云台信息4 P% Z' @( F4 `
        protected BroadcastReceiver mReceiver = new BroadcastReceiver() {1 _7 p" n, f& H. Q. ]/ U
            @Override- h! c, }$ K8 b
            public void onReceive(Context context, Intent intent) {
    9 j" j* F  K" n4 L4 v( n            BaseProduct mProduct = ReceiverApplication.getProductInstance();
    ! @5 T! f/ G- Y" B& S; {  z            if (null != mProduct && mProduct.isConnected()) {4 t+ R. _/ I0 `1 d/ ~  _
                    flyInformation(mProduct);8 G6 d1 m8 [# ?1 {  L' @
                    batteryInformation(mProduct);
    . I8 P- c0 }" [8 L4 P                cameraInformation(mProduct);6 H8 f( B2 G. v
                    camera(mProduct);0 Z( ^, @% X2 ], `9 E
    //                MobileRemote(mProduct);
    & G$ I- q( N7 F5 T            }
    ) q! S) ]2 \: M        }
      Q. B; U# G" [    };$ C: `) F# }  T0 N5 _( y
    //    private void MobileRemote(BaseProduct mProduct) {
    , N& k( n6 x2 |3 `) ?//        if (null != mProduct && mProduct.isConnected()) {6 F& @3 H% c) C" v; R
    //            mobileController = ((Aircraft) mProduct).getMobileRemoteController();
    0 R+ s# Z# y1 R. o//        }% K' [, g5 s. ~6 i, a& [& Q. z: s) _
    //    }
    4 J3 D; r5 `5 n- Q  \    //获取飞机信息
    $ p" o- p0 r2 o5 p6 g5 U    private void flyInformation(BaseProduct mProduct) {
    - O; j4 [6 e9 a8 g$ Z  c8 X        if (null != mProduct && mProduct.isConnected()) {' z' L! _2 L! |  N! `
                controller = ((Aircraft) mProduct).getFlightController();
    2 N+ n* `" o7 ?7 G( Q/ _) E6 m        }
    8 W1 [, J+ Q+ [" l; _! J, r* j# e        if (controller != null) {
    7 I0 A. c$ g8 n7 _$ A: `            controller.setStateCallback(new FlightControllerState.Callback() {2 w" M5 K7 [& @2 v" _9 ^% b
                    @RequiresApi(api = Build.VERSION_CODES.O)- h2 y8 x9 N% Y
                    @Override  [1 H' c( ~( C  n# x4 L
                    public void onUpdate(@NonNull FlightControllerState flightControllerState) {
    / X9 y9 a. w/ L7 C/ y0 R: h* g7 Y6 Z                    //纬度、经度、高度、俯仰角、滚转、偏航值、速度
    ; k* Z8 E: O3 b, I- J7 Z2 M- G+ c                    lat = flightControllerState.getAircraftLocation().getLatitude();3 P* n# D+ e( F% Z, o/ C; z4 j4 j
                        lon = flightControllerState.getAircraftLocation().getLongitude();
    * I0 z" @# p2 ?/ P4 G                    high = flightControllerState.getAircraftLocation().getAltitude();0 F5 R2 |) L; _' D$ u5 u
                        attitude = flightControllerState.getAttitude();
    4 c& w6 y0 X' B( Q" @- W% h                    pitch = attitude.pitch;& g4 c, s- E+ J
                        roll = attitude.roll;' @  U! R+ B) J/ t- i( r
                        yaw = attitude.yaw;# ^! N6 {5 V* }3 z; x9 H0 R' i
                        velocity_X = flightControllerState.getVelocityX();7 @4 T, V: E( P: ]/ i9 B6 m
                        velocity_Y = flightControllerState.getVelocityY();% X  s1 o7 m, @
                        velocity_Z = flightControllerState.getVelocityZ();
    * y  ]1 v3 N9 @2 f" x2 n/ a$ Z9 m- H5 `                    isFlying = flightControllerState.isFlying();1 e: C/ k* F* M3 U: T% r( l
                        //                    MyLog.d("经度:" + lat + ",纬度:" + lon + ",高度:" + high + ",角度:" + pitch + ",速度:" + velocity_X + "," + velocity_Y + "," + velocity_Z);
    , Q$ x% X4 ?! y                }* a  d; J& D3 J! J6 Q
                });0 P2 Q7 A8 A2 E+ E' i% }' s
                controller.setVirtualStickAdvancedModeEnabled(true);
    7 V/ H3 r( O" P7 R            controller.setRollPitchCoordinateSystem(FlightCoordinateSystem.BODY);
    , O3 U! h+ A; C7 {            controller.setVerticalControlMode(VerticalControlMode.VELOCITY);: x, h9 ~; a7 Z% b
                controller.setRollPitchControlMode(RollPitchControlMode.VELOCITY);" W5 C8 f' y( ^' F
                controller.setYawControlMode(YawControlMode.ANGULAR_VELOCITY);8 N  _9 ?% O# U
    //            controller.setTerrainFollowModeEnabled(false, new CommonCallbacks.CompletionCallback() {
    4 Y8 b6 \+ w$ T7 w$ G//                @Override: Z4 v; U) T6 `* h6 |
    //                public void onResult(DJIError djiError) {
    ; B. ?: W% F5 n% p) q. f) w% N9 \0 J//                    MyLog.d(djiError.getDescription());* I) p( }* M) O
    //                }/ x# d+ @4 }8 v7 H' [% F( i
    //            });
    ( n( l9 e8 ^7 T5 ^# Y! w( ^//            controller.setTripodModeEnabled(false, new CommonCallbacks.CompletionCallback() {
    0 h% I( X7 V" l& [# F4 }) K//                @Override1 V  {9 ^' Q# q) `" i
    //                public void onResult(DJIError djiError) {
    % B& e5 b# K' ~1 X( S  R3 |4 l; P//                    MyLog.d(djiError.getDescription());
    + Z, m- z5 b( b5 H2 t+ g! t- d//                }
    - h8 {& r  d  `: a" a//            });
    , F& _  r# F, D) V1 z//            controller.setFlightOrientationMode(FlightOrientationMode.AIRCRAFT_HEADING, new CommonCallbacks.CompletionCallback() {
    4 m  S: P/ v( |! p+ c//                @Override. a3 c! s9 c- X& l/ c! {
    //                public void onResult(DJIError djiError) {
    ( m- o- w" w* W3 C//                    MyLog.d(djiError.getDescription());- e3 u2 `$ S4 e
    //                    if (djiError==null){7 _' F. S1 i& s7 R4 q& A( ]
    //                        if (controller.isVirtualStickControlModeAvailable()){
    ; F$ h$ e8 }( z0 ^( d//8 O+ S: `5 z# ^" e. M: o
    //                        }else {& W6 v/ J3 o" d
    //                            MyLog.d("虚拟摇杆模式不可用");* \( g* T+ W% t( X7 `$ S
    //                        }' H7 }" k5 i) o& l3 w9 t! z! X
    //                    }8 ?7 d8 M2 X, B
    //                }
    + A" R, y2 T/ _$ @+ Q- z7 z//            });6 I2 s9 B6 Q* h* _
            }8 o# e; {$ x2 a) v( z: a6 L# }
        }9 i: H5 g) Q- e( {0 U7 ?
        //电池信息
    2 F' i0 C* \2 f  {- B    private void batteryInformation(BaseProduct mProduct) {
    % N) q4 @) E6 o& ?  g        if (null != mProduct && mProduct.isConnected()) {1 }! y4 t* y! W: W1 m) `7 o
                battery = ((Aircraft) mProduct).getBattery();5 p' Z5 A# R  g
            }
    7 I' X/ d0 H( J, m        if (battery != null) {# A  `1 e- ]! q
                battery.setStateCallback(new BatteryState.Callback() {
    9 k. \: H& `- P7 ?5 }                @Override
    0 `7 [7 i7 w4 Z: o                public void onUpdate(BatteryState batteryState) {5 r& ?) j7 ]4 r
                        //电池电量! P; X4 L0 E; j; a: N# E. t6 [* ?
                        power = batteryState.getChargeRemainingInPercent();( Y. w5 o" B; e- m3 n
                        //电池温度
    * K% S8 ?# }% l- f                    temperature = batteryState.getTemperature();& l( {+ \6 Z" f$ b$ x' a! Z
                    }
    + D+ i8 K% N4 _; p% N; H  D            });
    : j, W2 u8 c  v! z" @0 N' L        }# R$ G6 ?; I" E. U  k
        }+ ~9 ?3 ?2 P+ m) t
        //云台信息5 z) z/ O+ F! f3 [8 i7 ~
        private void cameraInformation(BaseProduct mProduct) {
    . B7 R  M0 s5 c! M5 M7 C8 N        if (null != mProduct && mProduct.isConnected()) {3 p/ `1 b# O0 b3 ?3 Q+ f( K* i
                gimbal = ((Aircraft) mProduct).getGimbal();
    . M' W: t, T5 }, z1 {        }
    1 n* P' @2 I* u        if (gimbal != null) {
    8 |3 w, x: K' ^. L5 u8 i& E            gimbal.setMode(GimbalMode.YAW_FOLLOW, null);
    4 p4 z5 V  l3 \& i            gimbal.setStateCallback(new GimbalState.Callback() {" M* ^9 t$ C6 N8 `
                    @Override' n/ y( `  x; J6 {
                    public void onUpdate(@NonNull GimbalState gimbalState) {# c# q4 s- ?, K9 P( `! q+ z
                        //俯仰角、滚转、偏航值$ e* q0 x0 s+ j* V) e9 N4 F* ?
                        g_attitude = gimbalState.getAttitudeInDegrees();4 j4 H/ F/ _8 w, w
                        g_pitch = g_attitude.getPitch();
    ( X- [+ S/ U8 S/ I2 o                    g_roll = g_attitude.getRoll();
    1 @0 Q. c6 J( z1 t# |/ B                    g_yaw = g_attitude.getYaw();
    1 d% A& M4 ]1 E3 L3 s                }
    0 b/ i7 K4 W, b- n            });$ Z4 f  I) O( F0 Y. m
            }" a/ A- ]" P! M6 C5 K( S
        }  |9 A3 }" e  n6 u/ ^# j
        private void camera(BaseProduct mProduct) {
    6 ]! H% g$ C4 W  e        if (null != mProduct && mProduct.isConnected()) {+ j/ g( ~2 m3 f2 C5 V/ y, U1 ~" P
                camera = ((Aircraft) mProduct).getCamera();: ^- [0 e# O- y; P# r6 {, t
            }
    ( r# y  [$ y( D$ k/ A        if (camera != null) {( _( R) a' a% Q; D4 `
                //            camera.setVideoCaptionEnabled(true, new CommonCallbacks.CompletionCallback() {" @$ x) {, I) s2 m# k
                //                @Override
    : z+ U, J" D$ E! c5 ?            //                public void onResult(DJIError djiError) {6 ?( B5 v2 ^& T6 @( S
                //                    MyLog.d("VideoCaptionEnabled"+djiError.toString());# s- K1 C, |5 V* m. |0 y0 o: Q
                //                }& a- f$ D6 G+ y# K4 [  {) T) O
                //            });
    9 l! e! ^- @8 X- D            //            camera.setMediaFileCustomInformation(projectId +","+trajectoryId, new CommonCallbacks.CompletionCallback() {* L. a  S2 l  G) u9 Z' e
                //                @Override' b3 ?, a& ?4 O5 S# ~. {1 g
                //                public void onResult(DJIError djiError) {
    ' Y% D$ K) S$ Q/ K6 v            //                    MyLog.d("自定义信息:"+djiError.toString());% _$ c0 g0 Q8 B% g: p% N$ m9 J
                //                }
    1 D6 P+ {* Y! }! D            //            });
    $ c) A3 {6 F7 _4 Q            camera.setSystemStateCallback(new SystemState.Callback() {" i( y: H* r3 e/ s# Q+ v: T
                    @RequiresApi(api = Build.VERSION_CODES.O)
    " @& S0 c  h6 K$ C) z                @Override+ g; M3 }/ b; ~% [. ^. ^
                    public void onUpdate(@NonNull SystemState systemState) {
    8 F2 l7 g* C" G: v; s6 M1 G                    if (systemState.getMode().equals(SettingsDefinitions.CameraMode.SHOOT_PHOTO)) {( {: ^+ i5 v% N8 G% z: l
                            if (systemState.isStoringPhoto()) {
    2 j0 D2 k; s0 T0 ]7 r                            dateStr = Long.toString(System.currentTimeMillis());
    / Y( S* }& x0 C1 H, d4 f9 T) H4 V                            list.add(new DeviceInfo(dateStr, lat, lon, high, pitch, roll, yaw, velocity_X, velocity_Y, velocity_Z, g_yaw, g_roll, g_pitch));, [- t) h5 d/ w/ ^
                                CsvWriter.getInstance(",", "UTF-8").writeDataToFile(list, FileUtil.checkDirPath(FLY_FILE_PATH + "/照片数据") + "/" + DateUtils.getCurrentDates() + ".csv");) [7 z: e. k4 N, ^- `4 g
                                list.clear();- x# M- o2 @" t5 W' A0 Q
                                return;( O. i$ I9 Q/ ~, L* B
                            }* R# T" q4 r% X5 E2 q
                        } else if (systemState.getMode().equals(SettingsDefinitions.CameraMode.RECORD_VIDEO)) {/ b: |, }( L5 U+ [9 \8 ~
                            if (systemState.isRecording()) {0 z- `6 ~7 j2 A2 W/ @
                                try {
    : z* `0 H$ i$ `+ @  b9 A! E                                dateStr = Long.toString(System.currentTimeMillis());6 L2 t4 N& m. L: v9 C) ], ^6 j; o5 Q
                                    list.add(new DeviceInfo(dateStr, lat, lon, high, pitch, roll, yaw, velocity_X, velocity_Y, velocity_Z, g_yaw, g_roll, g_pitch));* h2 F0 b) m! T8 c0 i
                                    getList.add(dateStr);
      E7 @0 O) O# p: ^  P  U! L                                Thread.sleep(100);
    8 [5 s! ?6 u! Y                            } catch (InterruptedException e) {
    ) y9 o, m+ R& F/ R' p4 C4 L                                e.printStackTrace();
    ; h/ V+ d4 {7 p; {) t6 `                            }
      e5 V- J- ?1 T3 M                        } else {0 U$ U0 ]1 F$ Z0 Z7 `; V
                                if (list.size() > 1) {
      b$ h3 n0 [. g+ _                                posName = DateUtils.getCurrentDates() + ".csv";
    . F" M, E2 j5 G$ C& J( D7 o+ M; f$ P                                CsvWriter.getInstance(",", "UTF-8").writeDataToFile(list, FileUtil.checkDirPath(FLY_FILE_PATH + "/视频数据") + "/" + posName);
    , _+ ?4 m* }. c$ A                                list.clear();
    8 h+ m0 I, s) l5 s- S( Q                                runOnUiThread(new Runnable() {
    # X3 U# H- N6 i$ L  `+ g2 X5 z( C/ O                                    @Override$ r7 p" {8 o+ M4 z, D+ M1 }6 Y
                                        public void run() {
    3 `2 i- }9 J8 [* b" s  m                                        getFileList("end");7 G. u$ ~3 }# N9 H, j7 w
                                        }6 d) N' ^; j& P& l
                                    });. K' }( O+ ]$ o; h7 Y( j
                                }
    4 [' q) @* G$ i- z6 m- B( d                        }% b' {" h+ b" j" U8 x
                        }5 I; f/ n3 V' C# q& V: v
                    }$ {5 D. o0 ]6 \6 E" x9 B
                });
    ( \' X7 Z* R2 i$ y! Y        }
    , t2 ^7 N& h- U* ~* A" L    }7 }: @; r5 ]; C4 ~1 D6 @! \
        //遥控器信息
    & \3 `& `# z' I0 o% Q& G    private void handheldInforamation(BaseProduct mProduct) {4 n* C: r9 f5 z; ?" U. F1 ~5 L  J
            if (null != mProduct && mProduct.isConnected()) {/ h+ r- @& L/ _+ h2 W0 Q
                handheldController = ((HandHeld) mProduct).getHandHeldController();
    5 V1 V; B+ ~: D6 K        }) \; S# c$ W; V
            if (handheldController != null) {
    , r$ H4 g5 N) o/ I/ L: N            handheldController.setPowerModeCallback(new PowerMode.Callback() {  [& q! R# W- Y' I8 W! n9 a9 ]
                    @Override9 \) S  T# e1 ~* |1 g2 G+ I, w; W
                    public void onUpdate(PowerMode powerMode) {6 N. j. c. B3 V& E0 r: x; Y# u
                        switch (powerMode) {
    4 {9 c, a/ v0 [/ L0 c                        case ON:' b* x4 y- Y* W0 e
                                Battery battery = ((HandHeld) mProduct).getBattery();4 E& ~' c, i$ y( R0 X
                                battery.setStateCallback(new BatteryState.Callback() {
    $ S% _) a( s) p& r! n                                @Override7 u9 m. U3 C3 {4 z$ x" o) q% j
                                    public void onUpdate(BatteryState batteryState) {7 W1 _+ u' g+ J, Q
                                        h_power = batteryState.getChargeRemainingInPercent();
    . ]) Y: S( ^7 \' X                                }
    1 p/ @' ~7 u4 W                            });
    ' C4 h2 Y' [" i" X2 k4 V7 \                            break;
    % h2 q2 s: P! Y& u+ f. }. K* q- c                    }4 g  ?1 O  Z- _* B
                    }& Z( S1 \& t+ ?; }6 j* z/ Q- i
                });
    " ~4 g3 k3 `, R  F8 Y8 H3 L. g        }6 z& t! G$ l: R; v+ i
        }
    ; k2 \% ]6 U! `/ X+ I1 T2 `) F   
    1 `3 S" x2 S# T# D3 b! y" ]9 j, ]    @Override$ Y, N2 f) H  s7 n
        public boolean onKeyDown(int keyCode, KeyEvent event) {
      B5 v. ~' f- j& a4 M        if (keyCode == KeyEvent.KEYCODE_BACK% ~$ X& S4 j, ?) Q" P
                    && event.getAction() == KeyEvent.ACTION_DOWN) {; O/ ]- {# Q$ o5 w+ w
    //                        closeConnect();2 y! M, [% t; |  \, z  M4 a6 V' P/ z/ d
                MainActivity.this.finish();  r' S( q( c6 t4 M: ]) q
            }
    ; D2 ^& }, _, x. t) Q+ z! n' {- F        return super.onKeyDown(keyCode, event);8 F# P3 g& p* h# T/ H5 }
        }
    ) p, U' M, f; @: M$ w. o/ x  x}
      x# ?. o+ V, k3 R# U5 w完成后界面如下所示:
    3 E2 r! c, T% U

    44z0q3cy2zr6406117454.jpg

    44z0q3cy2zr6406117454.jpg
    ; A( V8 d* N( {) N/ c
    上面的工作完成后就可以在无人且宽阔的地方进行无人机飞行了。5 ]. r: }8 k$ I; H& J7 |
    4. Y1 M! O. }: R8 Z) I
    多媒体资源的操作" Y. l. p0 k* y, D9 h+ Y
    多媒体文件操作,主要为多媒体文件的获取、查看、删除、下载的操作& }! L' B) y" R' a
    同样创建多媒体功能文件FileManagementActivity及activity_file_management.xml
    7 R  ?) h( w3 S0 N* V& [7 v; wactivity_file_management.xml
    0 @' O0 `8 Y6 V& ]' d6 ILinearLayout xmlns:android="http://schemas.android.com/apk/res/android"6 W6 R6 k, E' G' Y  a2 t
        xmlns:tools="http://schemas.android.com/tools"; [- w& P+ ~3 Q+ x- `+ o9 c# G! k
        android:layout_width="match_parent"1 U! S1 v: S3 s* D
        android:layout_height="match_parent"
    1 Q" t' c! D8 [- {% y* u8 S$ M    xmlns:custom="http://schemas.android.com/apk/res-auto"  G8 t% H4 W! D& k
        tools:context=".ui.FileManagementActivity": [2 B/ Q2 R) n7 L, ^: \" p" b
        android:orientation="vertical"* a: l" Z7 M+ ?7 i: G3 K; c4 @9 F7 L
        android:background="@drawable/shape_corner_eight">
    * @7 m) M! v( @    include layout="@layout/activity_toolbar"
    7 f& C, O+ S+ U4 w        android:id="@+id/layout_file">include>
      ~& C0 H% t5 d4 X' P2 {: F    LinearLayout
    & S- }1 A) m, ]; m$ Q: @# C- a        android:layout_width="match_parent"" f. Z$ |" ~7 Q3 M
            android:layout_height="match_parent"& K! M+ h7 K' m: ^+ M. b
            android:orientation="horizontal">
    8 D/ s4 J" N, f( m        LinearLayout
    7 @& o  `* @6 n  Y            android:layout_width="250dp"9 a( [! V. R4 m# }  ~
                android:layout_height="match_parent"0 J0 A) b! U, b: b
                android:orientation="vertical"" h: u: @8 Q) e" U% a' s; u1 H- r/ |
                android:layout_marginLeft="15dp"
    & [" Q. L1 J, s            android:layout_marginRight="15dp">
    8 h# H8 Y8 O8 e2 O. Z# I            RadioGroup
    2 R1 i% b( v) m& `7 X' {                android:id="@+id/rg_file_management"2 Y# ~# d6 I9 {9 P6 z
                    android:layout_width="match_parent"/ L3 W7 a( E7 V4 T) Q$ m) D$ x
                    android:layout_height="40dp"6 K  |' Z" S$ Q* l' {
                    android:orientation="horizontal"
      @! a) [7 V3 ?9 k3 w$ }% A                android:background="#2B3141"
    . B% k! `" ]4 O% z2 @" L' P+ U                android:gravity="center">
    7 V$ T; c0 E6 b5 T* T3 r                RadioButton
    & s) @2 B0 l2 ]+ f4 P1 }' E5 ?                    android:id="@+id/rb_file_all"
    1 J& g: }' ?" [                    android:layout_width="0dp"4 c$ C9 z2 F# `" [% S
                        android:layout_height="match_parent"
    1 q- g- f6 J; T                    android:layout_weight="1"& T* h/ N1 j% D0 x
                        android:button="@null"
    # q( s- B4 Z% C; p                    android:checked="true"5 o" G  p8 l; W3 M2 R& Y
                        android:gravity="center"
    ; V6 y" ]2 o, F( |* I' P2 ^                    android:text="全部"/ n% U9 s! ?) }( _) \; y
                        android:textColor="@drawable/nav_item_color_selector"
    1 N' S# k4 j& }                    android:textSize="18sp"
    ; ~, `  z- v1 q. c7 y2 M                    tools:ignore="TouchTargetSizeCheck">RadioButton>* u$ e6 v2 T) y+ b
                    RadioButton
    % ?$ ~& w( q8 v1 S7 M                    android:id="@+id/rb_file_photo", e- u7 n# z+ ]4 q+ s+ L& r3 H
                        android:layout_width="0dp"
      `  |4 T7 R  v' b                    android:layout_height="match_parent"
    * p9 h. C5 s# m) J. J& k( M$ V                    android:layout_weight="1"
    " d/ K$ N& }% ]                    android:button="@null"
    ) C4 z+ O' Q+ p                    android:gravity="center"1 I( k0 r5 H9 E5 K' U. z
                        android:text="照片"! Y" f5 z: j# T1 X
                        android:textColor="@drawable/nav_item_color_selector"- H9 o' ^2 O3 q; i! W
                        android:textSize="18sp"( J' K4 O/ ~5 k( p0 Z7 o9 o' U
                        tools:ignore="TouchTargetSizeCheck">RadioButton>
    0 D( @4 U# v8 a7 z4 o                RadioButton2 x7 v' X# [" |- h9 V: u% q$ V* G' ^0 Q
                        android:id="@+id/rb_file_video"
    7 D, F* U/ Y. r3 E& ~& i                    android:layout_width="0dp"9 c! g8 \  W$ P6 B
                        android:layout_height="match_parent"
    1 s3 x7 {$ Y& P7 j+ k$ C                    android:layout_weight="1"; Y% m! v: V. P5 I  V
                        android:button="@null"
    ; }- ]1 F* O! v                    android:gravity="center"
    8 c, N' t7 J: G8 n" f                    android:text="视频"
    . @6 e% S3 x! w* e' n2 F: p; G                    android:textColor="@drawable/nav_item_color_selector"
    - W( d  H$ a7 b6 c% s0 ^; s: b$ T                    android:textSize="18sp"
      {9 ?/ @% K. s1 e% F# p3 i) h                    tools:ignore="TouchTargetSizeCheck">RadioButton>
    9 e' P4 n: m- U! w  ]            RadioGroup>
    + @3 z( e5 C; J7 M& W! G            androidx.recyclerview.widget.RecyclerView
    8 F  v5 K( P& f' L& N                android:id="@+id/rv_file_management"( _5 F" }3 t8 b- {
                    android:layout_width="match_parent"
    ; p$ b* F& X0 V# x- V                android:layout_height="0dp"! H; v, K3 g# z8 k# w
                    android:layout_weight="1"! Z% \6 s+ |" ^6 q+ V  ]& B
                    android:layout_marginTop="10dp">androidx.recyclerview.widget.RecyclerView>
    " b+ `4 Z( ?1 o% c, o$ j        LinearLayout>% q; ~0 t! \8 V, ~  G' Z3 |$ h
            RelativeLayout
    5 v, v( `  E  S! j+ k: I            android:layout_width="0dp"
    ' W0 e# l1 }% Z& `0 L0 n            android:layout_weight="2"" A1 F9 L: d+ g% i$ h0 u
                android:layout_height="match_parent">% `; s: ]+ f3 r1 K  m8 t1 r
                RelativeLayout9 q# W: x. u$ `; v
                    android:layout_width="match_parent"
    ' ?, i* ~: f4 ?; G& [                android:layout_height="match_parent">/ X3 W7 W, K* g' u0 X
                    dji.ux.widget.FPVWidget( y: s# D6 z4 `
                        android:id="@+id/FPVWidget"* ?0 h- ]( H& N
                        android:layout_width="match_parent"
    4 _8 D8 T; P( E5 A" y& _3 T$ a" h+ Z                    android:layout_height="match_parent"/ S- N; Y: a! n; {+ t
                        android:layout_centerInParent="true"2 X2 G( ?3 F" {  {
                        custom:sourceCameraNameVisibility="false" />
    + y4 W; e" X+ A0 y            RelativeLayout>
    - e. k3 `) U  W+ r/ A* ?. o            ImageView
    6 E, m7 ?  d3 T9 M5 c                android:id="@+id/img_show"
    5 Z& [* D: r( g+ j+ r- t  g% t                android:layout_width="match_parent"+ h, P4 X- Q# i5 d4 x' [0 X
                    android:layout_height="match_parent"
    6 m8 d: W; J7 v% {+ n. z2 g                android:scaleType="fitXY"
    + a  x0 L8 q  \1 s                android:visibility="invisible">ImageView>8 j% E6 X5 R+ F8 C7 c5 x( Y
                LinearLayout( V3 J( U, I+ o- c4 `: z5 y0 v
                    android:id="@+id/ll_video_btn"* _* F" f4 I5 H/ w! p/ z" K
                    android:layout_width="match_parent"% b# l4 M4 _6 d5 s1 [+ R6 f
                    android:layout_height="50dp"
    7 Z) |: M! ~" q                android:orientation="horizontal"
    ( V3 J3 l  W" O4 |) ]. o6 f                android:gravity="center"5 X5 P3 z% ]  c& k' X- I
                    android:layout_marginBottom="15dp"- H, C* E1 y; S: }- d
                    android:layout_alignParentBottom="true"' c( [, A# i: m* ]: q1 m& W
                    android:visibility="gone">' A; W0 L, }$ B5 v" \; K0 |
                    ImageView6 r& N, Y; I! o( t& Y: D+ ?% ^
                        android:id="@+id/img_video_pause"
    8 B2 K7 e/ `$ c5 R                    android:layout_width="35dp"! k  Q2 ~! X) z) e7 P4 n
                        android:layout_height="35dp"9 ]' g( g0 B* l+ T8 Q
                        android:src="@drawable/background_stop_selector">ImageView># A6 A$ n, n# \% i) h
                    ImageView
    1 K! H1 N! u2 b6 p$ c9 m' ^6 r  n) {                    android:id="@+id/img_video_play"0 g) y/ T! t# A: E3 P
                        android:layout_width="45dp"( I2 Z4 ]* y2 ]0 D  Y4 e
                        android:layout_height="45dp"
    1 E& c7 R' |; b! J- Q                    android:layout_marginLeft="20dp"1 _8 M5 U2 t( U' L  T
                        android:src="@drawable/background_palyer_selector">ImageView>" Q+ H) E( v* d6 _1 c
                    ImageView
    - q9 \9 m* d/ n. v                    android:id="@+id/img_video_stop"
    ) P9 l. w. C- r. t' v! D3 X6 \& K                    android:layout_width="35dp"
    ( v& p" r! H; q                    android:layout_height="35dp"% M& q$ _. `7 _
                        android:layout_marginLeft="20dp"+ z2 N" R8 Z. [6 E: Z
                        android:src="@mipmap/ic_reset_36dp">ImageView>) Q$ ]9 }1 ~# G4 C3 H; j  P, L( t
                LinearLayout>$ O3 E7 l8 k, ?
            RelativeLayout>
    & \9 `0 f1 U7 A2 G! I( M    LinearLayout>  n) l7 e( [! ]) u$ L' g
    LinearLayout>
    1 L& D) w' \+ c$ pFileManagementActivity
    , X* Y, \% S7 m  @( L@Layout(R.layout.activity_file_management)6 L5 |  `! H5 M# S% |
    public class FileManagementActivity extends BaseActivity implements View.OnClickListener {
    + z" L5 B( H, Y, ^0 K4 R/ ~, a+ R    private static final String TAG = FileManagementActivity.class.getName();
    ' y+ P; C7 D" B6 _4 a3 `9 _    @BindView(R.id.layout_file)" R2 @2 i  D" X% I
        View mViewLayoutToolbar;
    - W# t$ B6 t% K/ S; _    @BindView(R.id.tv_toolbar_title)) \# ~( a! o% S  B' j
        TextView mTextViewToolbarTitle;& B( i: U6 O6 N& g3 k5 @. w8 k& H3 N: K
        @BindView(R.id.ll_file)) m  u' [) A. d4 ^  g( i
        LinearLayout mLinearLayout;
    . [- X# d1 Z' w    @BindView(R.id.rg_file_management)
    ( x' k0 w. E2 G7 \0 l    RadioGroup mRadioGroup;
    . o( \7 v. T- i/ t$ ^1 x    @BindView(R.id.rv_file_management)
    3 R& ?% ?5 T3 L, k# j& a    RecyclerView mRecyclerView;8 b; X+ B7 t9 D) }1 O3 z
        @BindView(R.id.img_show)
    $ O$ Y: a9 j! d2 w  L    ImageView mImageView;
    1 P, X. {/ |5 m8 B    @BindView(R.id.ll_video_btn)' _: }  g- c# O9 s
        LinearLayout mLinearLayoutVideo;5 ]: k1 z, \1 b* H1 U6 d1 K
        @BindView(R.id.img_video_play)
    2 z  s9 R) U+ O" u* P" W    ImageView mImageViewVideoPlay;
    2 |/ \$ ^; }! Q% U    @BindView(R.id.img_video_pause)/ G: n* ^+ q: @9 r
        ImageView mImageViewVideoPause;
    ; z8 ~4 c" _- ]8 k    private FileListAdapter mListAdapter;
    ; T' G/ }% q( b2 \; J    private List List = new ArrayList();
    3 Q8 [& H$ l, B2 b6 c# t    private List mediaFileList = new ArrayList();
      ]2 D1 y0 P& j! r    private MediaManager mMediaManager;
    : q( Q8 ?5 @$ M! n5 x2 i. Q1 D% S    private MediaManager.FileListState currentFileListState = MediaManager.FileListState.UNKNOWN;* n0 e2 x: ?1 p
        private MediaManager.VideoPlaybackState state;
    4 }0 i' \% h! I) [" Z- a8 i6 Q    private ProgressDialog mLoadingDialog;
    ! }5 l$ g& H" n# \+ j. C! n    private ProgressDialog mDownloadDialog;6 X. l! c  d7 b
        private FetchMediaTaskScheduler scheduler;1 ~( i7 W( D- m$ }) K
        private int lastClickViewIndex = -1;# e0 A: T& u2 E6 t" |' X0 t* H
        private int currentProgress = -1;
    + o2 @9 y' L8 `5 z# J* \9 [( ~    private String SavePath = "";
    6 K9 b- A5 l- J    private View lastClickView;% p+ w0 s2 a& n- f% J5 V, n5 w
        private boolean isResume = false;$ v! U) W" y; n, ?% I, j( ~
        private SFTPUtils sftp;; f# r& J7 I, _, H2 j
        private SettingsDefinitions.StorageLocation storageLocation;
    " O+ r9 f2 r+ j4 \( k# J    @Override
    9 B! s# B  n; I  G    public void initViews() {
    4 a0 P; d' x' ^* f! x+ o4 i        mLinearLayout.setVisibility(View.VISIBLE);4 m6 R3 f* T* l  J" u% `
            mTextViewToolbarTitle.setText("文件管理");
    - e6 M  Q- C1 u) I4 P        mImageViewVideoPlay.setEnabled(true);: T' v  P8 |$ b6 i$ a7 U! b6 L
            mImageViewVideoPause.setEnabled(false);$ Y7 {# w( X$ m# d$ z
            mRadioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
    ; o8 g- o9 |$ Z) X            @Override; E0 E+ h0 T0 d9 i" Z, J
                public void onCheckedChanged(RadioGroup group, int checkedId) {
    % m  ]" q8 M  d                List.clear();
    . C) l3 s% r; w. Z' \9 G                mediaFileList.clear();) Q8 P" ^# S0 \0 d" A- s* J% b/ L
                    switch (checkedId) {
    ; b% R( f8 h7 f$ I                    case R.id.rb_file_all:: w* F, j1 U! Q& D4 B1 t! Q2 r3 }  v
                            getFileList(0);! I3 `( U- C+ d+ ^. }
                            mListAdapter.notifyDataSetChanged();
    ) R: Z6 a  @& V1 j                        break;
    8 a( ~' h: P$ J. J! F- z                    case R.id.rb_file_photo:- _5 A0 A2 j. K$ S7 Q- s7 f
                            getFileList(1);
    5 n9 e: C/ A8 p9 p                        mListAdapter.notifyDataSetChanged();. E+ K. H- S7 ?% G) k. c
                            break;
    % M/ H% B4 [& a$ J3 ]                    case R.id.rb_file_video:
    " \! X7 w! E8 P" U# L                        getFileList(2);
    ; i2 j1 _4 G( X6 m2 q9 z                        mListAdapter.notifyDataSetChanged();" v" q8 R$ j3 L
                            break;2 |7 i( w# t4 R' a6 ?
                    }7 a" v/ E0 u: h( ^" n& m
                }
    1 F9 z. S& n$ A# Z! r* ^        });/ X# w: K: t& d' a* w
            LinearLayoutManager layoutManager = new LinearLayoutManager(FileManagementActivity.this, RecyclerView.VERTICAL, false);
    ! y* [( n5 p- i5 S. u0 K        mRecyclerView.setLayoutManager(layoutManager);- j% N# A# k: c9 i- I' j
            //Init FileListAdapter- D6 w5 U$ H. s
            mListAdapter = new FileListAdapter();
    ( `/ t; t4 x/ \3 h        mRecyclerView.setAdapter(mListAdapter);! Y1 z( k' z$ y) y1 O- Q
            //Init Loading Dialog* u6 u% A; J. s+ l5 I2 U
            mLoadingDialog = new ProgressDialog(FileManagementActivity.this);
    3 }8 j+ _2 \: @4 O- v0 f        mLoadingDialog.setMessage("请等待...");
    2 N) }2 j# y" w& k( j7 K3 u2 s: N& k        mLoadingDialog.setCanceledOnTouchOutside(false);% ]+ \* m- d4 r- n
            mLoadingDialog.setCancelable(false);
    & E7 g$ p1 j4 h  k: Q* z0 n        //Init Download Dialog
    - v0 n( w" o. |! c, W4 |; l: q        mDownloadDialog = new ProgressDialog(FileManagementActivity.this);
    , m9 {1 A2 w/ J* B0 ?7 I1 v        mDownloadDialog.setTitle("下载中...");4 A$ G  j4 ~- Y8 T- ]! S9 B6 j7 O: F$ T
            mDownloadDialog.setIcon(android.R.drawable.ic_dialog_info);
    0 G$ ~! k5 E+ {, c) j$ }        mDownloadDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
    : l4 \1 x1 `4 g3 i% ]7 d        mDownloadDialog.setCanceledOnTouchOutside(false);
    4 d% t) I# e4 T/ F: t3 t5 k        mDownloadDialog.setCancelable(true);
    , R! j( s7 r. q% m        mDownloadDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
    ' k; I: r$ @% k0 @% y& V            @Override
    " a5 L. P" b; n& u            public void onCancel(DialogInterface dialog) {5 T% u  L: k% w% w  }" |% z
                    if (mMediaManager != null) {8 H4 i- b0 e# H, M; C
                        mMediaManager.exitMediaDownloading();
    2 \6 r. ~/ E3 c$ J1 C; S9 T                }
    2 g/ t, z2 j$ B$ E3 j. `            }
    ' v  i0 @1 W3 _        });
    ) b8 P0 V- e' C* M4 w% G' @/ C        sftp = new SFTPUtils("49.4.79.249","uav","uavHHch@YREC.cn");  ]3 _* H. K6 }; f8 X
            ReceiverApplication.getAircraftInstance().getCamera().setStorageStateCallBack(new StorageState.Callback() {
    ) o0 f( j7 `8 L/ `            @Override( A  p% v' v/ ]% ~+ D
                public void onUpdate(@NonNull @NotNull StorageState storageState) {
    3 N" R% v, _2 o. Y; x8 Z                if(storageState.isInserted()) {' m4 `2 J# k* L+ z4 \
                        storageLocation = SettingsDefinitions.StorageLocation.SDCARD;
    * ~- e1 ]8 `4 h$ r) p) ]                    ReceiverApplication.getAircraftInstance().getCamera().setStorageLocation(SettingsDefinitions.StorageLocation.SDCARD, new CommonCallbacks.CompletionCallback() {# C, z; Y. r6 M: z" G9 y
                            @Override
    : _7 i- Y+ j  U" M8 ?, w                        public void onResult(DJIError djiError) {
    3 q- e% R7 m) `7 k                        }
    + V) t4 d& n+ Y0 h                    });* C* h5 |: _! X: O
                    } else {
    , A! m, G4 w: B6 Z* k- T- u                    storageLocation = SettingsDefinitions.StorageLocation.INTERNAL_STORAGE;
    * A- L  B: V0 `3 |) n! I5 x                    ReceiverApplication.getAircraftInstance().getCamera().setStorageLocation(SettingsDefinitions.StorageLocation.INTERNAL_STORAGE, new CommonCallbacks.CompletionCallback() {% w  M2 ^- g/ V: J) g; j9 {
                            @Override5 i8 V9 {4 {& L6 ~( k7 }( j
                            public void onResult(DJIError djiError) {+ e9 `3 h% G- o9 R
                            }, ^3 \7 b1 \6 O  M3 q. M- m) w
                        });
    . ~* {, z& o2 i; K                }
    - y; K1 Q9 T$ c5 s% D+ u( }& U            }% ^  [8 ~+ _9 ?
            });
    , D+ I& S8 c% |! u, j    }
    & x  N5 E' U' ?: i( |  d+ u+ R    @Override/ I- z1 D% @0 W+ ^0 m6 D2 a
        public void initDatas() {
    ) o8 p5 P, h  U9 D    }- L8 |) G  \. i; F9 c
        @Override  D. F- Z% h9 ]" {" J
        protected void requestData() {: S- x5 W7 B- b& [- y5 J5 R  ]
        }
    : q) k' N  F3 g; n$ A4 w0 b2 W    @Override
    4 G  ^2 C& C+ z, U8 u    public void onComplete(String url, String jsonStr) {0 ?0 N" m0 Y! M8 c$ W3 L
            super.onComplete(url, jsonStr);
    : N" Q) y( l' F7 R( j: ^4 E        switch (url){% l' p7 T, V/ O. q
                case POST_VIDEO_INFO:
    1 C6 \# I; Q& T8 n2 K$ h" l                break;' o: f6 f& a5 R" H; |
                default:4 |5 J6 I9 O  U; R# n5 Q1 B+ y
                    getVideoJson(jsonStr);
    * Q* s. W0 K8 L7 o                break;: W( V" ?3 v+ o6 F" V% @# I# z
            }
    6 Z, i2 I3 Z# ~    }
    5 }! ?0 V! ]' M5 E* z; c" }3 q* i    private void getVideoJson(String jsonStr) {
    - e  @' f7 k( W* v        VideoModule module = GsonUtil.GsonToBean(jsonStr,VideoModule.class);$ L9 E2 _0 c  V! h) k+ A
            if (module.getCode() == 200 && module.getRows().size() == 1){
    ! h; N) F* s& T$ X0 S$ T6 |            runOnUiThread(new Runnable() {' c* d4 w/ K' H; r" z
                    @Override7 q8 ~* F; J+ N; n  ^
                    public void run() {# h3 A; K* M' ?0 B# E6 d
                        UpdateFileModule fileModule = new UpdateFileModule(module.getRows().get(0).getId(),"/mnt/uavFtpFolder/"+module.getRows().get(0).getFileName());- R9 c2 q9 S3 X0 g2 n9 g/ k6 k9 g
                        http.getHttp(POST_VIDEO_INFO,"PUT",GsonUtil.GsonString(fileModule));  E8 J9 Y5 ~, ], ^
                    }0 R5 V! ?. _0 @
                });) V1 M+ U6 M6 L0 F( m
            }
    $ L- B: y9 n/ ~    }8 d$ V( S6 b6 e, o
        @Override2 d& k7 c9 W) a' ^8 C
        protected void onResume() {
    2 f& b) O% c3 z        super.onResume();
    3 b9 s1 n" ]9 d" L        initMediaManager();
    1 m$ x9 X. H5 o+ _5 |    }
      @( V7 s+ I' @6 ?( L' I/ X    @Override
    ' N; E: G; \+ U! |4 `    protected void onPause() {
    ) l+ u' p- z/ ^        super.onPause();1 B/ [% N* E' f; c
        }. W( i7 e6 \  l1 U/ `; S
        @Override
    # U; [, z3 R. P5 j) N  \    protected void onStop() {) @+ ], Q3 n+ n1 e  Q0 |2 ^
            super.onStop();4 q$ \7 Y; w1 T( w( b
        }/ ~* ]/ N$ o& B

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

    erlparwngkl6406117554.jpg

    erlparwngkl6406117554.jpg
    % D9 f5 Z1 U4 p

    9 F; y; p) Q5 @) K; U, L) e

    aamb1f3g2fw6406117654.png

    aamb1f3g2fw6406117654.png

    ; A5 P, q% D9 @6 D. S; F往期推荐LabVIEW OCR 实现车牌识别- H" z" E' H+ L/ G' H  i
    和12岁小同志搞创客开发:有意思的激光切割技术; O5 j- y7 p9 L, k$ E  R* I2 M: W
    JavaScript+TensorFlow.js让你在视频中瞬间消失! |0 Y- i" f2 _) n/ \  U/ R& n
    使用OpenCV测量图像中物体之间的距离0 V) L. g* r9 h5 H. _* v
    全网仅此一篇:工业级压力传感器设计及实现
    ) P7 v  b8 P9 |# ]9 S2 {; \
    7 D2 [3 x4 R/ ~$ M1 u: \

    2zmyv1n5at16406117754.jpg

    2zmyv1n5at16406117754.jpg
    * v; `% K" d" P  x$ v

    hbeu2dpxc1x6406117854.gif

    hbeu2dpxc1x6406117854.gif

    7 t2 _* i: i; O2 `5 b点击阅读原文,更精彩~
  • 回复

    使用道具 举报

    发表回复

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

    本版积分规则


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