|

n1njpvfuqfl64023083205.gif
( `/ q+ L' ^& k* s8 E) |: o' o点击上方蓝色字体,关注我们, I/ ?6 g& N5 B) b
: w; i" J6 I* p; y5 y G( U
上一篇文章(基于Mobile SDK V4版固件开发大疆无人机手机端遥控器(1))因为时间原因介绍了一部分内容,如果已经完成上一篇内容的操作就可以进行下面功能方面的制作了。自己开发的APP功能不是很多,但是已经将大疆无人机的常用功能进行了结合,同大家一起进行学习~
/ Y* F1 O6 ?1 @0 q9 [1
0 c, s1 [5 T0 ^应用程序激活与绑定
1 B8 b3 {5 c5 c: B; `& V如果在中国使用DJI飞行器固件,则需要使用该用户的DJI帐户激活控制DJI飞行器的移动应用程序。这将确保大疆能根据飞行器的地理位置和用户个人资料,为飞行器配置正确的地理空间信息和飞行功能集。激活系统的主要是:
! p' S! l. E" f+ D# C. [0 b6 {中国用户必须在每三个月至少登录一次DJI帐户以遍激活应用程序。激活信息将存储在应用程序中,直到用户注销为止。登录DJI帐号需要连接互联网。在中国境外,SDK会自动激活应用程序,无需用户登录。另外,中国用户必须将飞机绑定到DJI官方app中的用户帐户。这仅需要一次。如果未激活应用程序,未绑定飞机(如果需要)或使用旧版SDK(, k. i0 L1 d" R
7 y" u& J& A" K2
/ Y5 I0 I/ ]% X; F- O' O3 S3 Z为应用程序创建UI编写MApplication、ReceiverApplication和RegistrationActivity文件(此处粘贴部分代码)。$ W1 A! L+ H8 q# W: ~
public class MApplication extends MultiDexApplication {
# b+ D6 L2 O% d private ReceiverApplication receiverApplication;
- S% M" s5 }, U' Q' |$ c @Override3 j# D2 f2 }" j4 u' Z& n( X
protected void attachBaseContext(Context paramContext) {
& o* ]! m, F8 F& [ super.attachBaseContext(paramContext);
& {! k3 i. I, n: E' h0 C CrashHandler.getInstance().init(this);
$ Y9 K [; f' E& F, y, b Helper.install(MApplication.this);$ E0 y7 |# C- y. s8 o
if (receiverApplication == null) {
8 q7 D6 ?( I% O. D( K receiverApplication = new ReceiverApplication();2 C9 I' V" ]1 e/ j" o7 V% [$ F0 w
receiverApplication.setContext(this);' [, R$ Q3 o: c
}
& x0 o6 C x6 Y# A }- M( Z/ S6 P4 D5 p& h: k+ R2 u) H
@Override
. z* O* N7 T- J* @4 x' o public void onCreate() {
- \ b* v* ]8 X: k: x6 G! N3 `6 o super.onCreate();$ D @. s( v9 l% F. u' T3 x$ s
receiverApplication.onCreate();
5 d* T0 x# w, `# E }
2 c6 k1 ?2 G1 G} B1 T7 f/ q! w7 _
上面的代码实现了绑定当前APP,将后续需要用到的类函数封装到ReceiverApplication 中,在ReceiverApplication 中也能够进行账户登录的操作。
9 e! ?1 V" q5 Ypublic class ReceiverApplication extends MultiDexApplication {
: u' X5 h% z& t6 i$ @& E$ O: x public static final String FLAG_CONNECTION_CHANGE = "activation_connection_change";) i! v! W* `* e, ]3 X4 {6 M9 _, H
private static BaseProduct mProduct;( ~& X6 ~2 z# h7 x$ {3 h( l
public Handler mHandler;+ ^. u4 Z# z5 B K' F# Z! x7 Y
private Application instance;
( d1 a; Q6 _' i; y+ o$ F6 A public void setContext(Application application) {+ E& e t f3 [% G
instance = application; K% N3 W: m4 V7 g% E" o1 ]
}
/ b& J, @8 D, u* b& Z @Override6 v$ D9 a5 y5 Z* ~; E7 R, K
protected void attachBaseContext(Context base) {
! n& s' h9 }8 \ super.attachBaseContext(base);
4 E. q N4 X4 c9 I! Q Helper.install(this);2 |+ i3 V2 ~) K& z$ c
}
7 n, t2 e! j P9 i, U, ]- z# a @Override
6 M5 G# R. |! }1 J0 {- V public Context getApplicationContext() {: g( e) d+ z, | ^
return instance;
?1 [3 A8 c9 @+ v2 k8 ^ }" |( s* L7 Q b( A# ^* s
public ReceiverApplication() {6 x# q: m1 B. Q% T0 _
}
+ p2 _1 J" x2 O$ I& Y: ^1 R /**# I S, b. L3 [2 A
* This function is used to get the instance of DJIBaseProduct.
c# J7 n$ Q+ j/ C. O; a: o- [: M) X3 f. i * If no product is connected, it returns null.
X8 \/ D' Y, H* G8 V */2 L+ N) k7 \ g+ u$ u$ b3 ?
public static synchronized BaseProduct getProductInstance() {
% ^& w& ~# y8 K8 A3 J if (null == mProduct) {/ \. G4 [0 `6 ^% D' w' l' R- r; H
mProduct = DJISDKManager.getInstance().getProduct();
' H5 N4 ~; }, O }* V, K! S8 M% ~. ~' |- Z. R
return mProduct;
/ K4 K0 g1 Q" m$ c) K, | }! a* Y/ E7 P, W# {+ K
public static synchronized Aircraft getAircraftInstance() {
6 V" R% Q1 Y! u( w7 \ if (!isAircraftConnected()) return null;3 u- z" b) q$ E7 x
return (Aircraft) getProductInstance();; U; c T; q; [% u
}
- L, a! P; @0 X4 Z; M/ i J public static synchronized Camera getCameraInstance() {) F; S: B6 n8 { g* ], m9 p4 g
if (getProductInstance() == null) return null;: _( ]' l+ S8 k9 D
Camera camera = null;" m8 f2 l L+ k( |" _, ^1 m
if (getProductInstance() instanceof Aircraft){6 o0 m) S ]/ \. g8 t3 T d2 o
camera = ((Aircraft) getProductInstance()).getCamera();
1 ^$ |2 i9 i6 s& [. D2 R } else if (getProductInstance() instanceof HandHeld) {, |( f+ @0 h. o+ \( }' _
camera = ((HandHeld) getProductInstance()).getCamera();
& K" O! O0 z- q. @ }
# U, B8 T, y1 I1 C7 A6 W+ O" ~& t return camera;
8 R" t1 c( j6 i! C* k }
* g& D; Z% e9 V7 y; l public static boolean isAircraftConnected() {" y1 P$ r0 X4 |* ]' W8 }
return getProductInstance() != null && getProductInstance() instanceof Aircraft;
. a8 R2 ?" e1 D' K& q3 [ }/ d3 b8 ?4 G, U2 C! a
public static boolean isHandHeldConnected() {) K1 w) E, E K4 `4 k
return getProductInstance() != null && getProductInstance() instanceof HandHeld;, e% p7 O& [: ^# X( O, ?8 @, U
}) [7 H, |8 y5 S
public static boolean isProductModuleAvailable() {
+ @( }# f; A3 J; E' ~1 C return (null != ReceiverApplication.getProductInstance());
" r! ^5 k5 [9 a4 V! ? }
% g) s0 w% _. \3 b public static boolean isCameraModuleAvailable() {9 e! a$ H o; a! Q& U& o
return isProductModuleAvailable() &&
# _9 e/ B3 L1 i6 m }) ` (null != ReceiverApplication.getProductInstance().getCamera());
( |; B, i; J( a! H0 L8 v7 ~ }% u5 K2 X2 S/ J6 m3 i5 r
public static boolean isPlaybackAvailable() {
/ ^/ t, j$ n; |8 W; Q. J return isCameraModuleAvailable() &&
2 B6 C% K m2 N6 L( ?0 n2 @ (null != ReceiverApplication.getProductInstance().getCamera().getPlaybackManager());3 w; I* D% j) ]* ?& x
}
; `4 l$ R, V+ r" R @Override
# G5 _2 J" r/ s$ N$ v' S8 S public void onCreate() {7 I$ q; U# P$ F# M0 S+ r
super.onCreate();9 G. d$ g; Y9 K. [% H
mHandler = new Handler(Looper.getMainLooper());
% t( H- j/ |3 k, z# `% W! q$ K /**
2 t' f7 G; ^: x) ^ * When starting SDK services, an instance of interface DJISDKManager.DJISDKManagerCallback will be used to listen to
% N/ v @, s/ ]0 Z% s. e5 G * the SDK Registration result and the product changing.& `' W6 ~. f: B
*/
$ \8 ]% U! C- u" x //Listens to the SDK registration result
5 L/ q$ w1 I% U* P DJISDKManager.SDKManagerCallback mDJISDKManagerCallback = new DJISDKManager.SDKManagerCallback() {
3 k8 ?6 i5 S# W% ?+ S //Listens to the SDK registration result
Z; o- l! @8 L( s# ^! I# H @Override6 z5 W0 B: S' \. V: z2 s
public void onRegister(DJIError error) {9 c3 w4 u2 p) m4 D
if (error == DJISDKError.REGISTRATION_SUCCESS) {8 K) n( y+ K: p" v. d" l' ?. X
Handler handler = new Handler(Looper.getMainLooper());* i. X, g' e9 Z, }' t, ~2 s
handler.post(new Runnable() {9 C/ _& Y# w/ Q
@Override
4 O( f5 t8 Q' u- z1 k' r public void run() {; `0 z; I; E( Y% t9 \# C
// ToastUtils.showToast(getApplicationContext(), "注册成功");" L' q: B) k; z" t8 y1 j) I
// Toast.makeText(getApplicationContext(), "注册成功", Toast.LENGTH_LONG).show();
9 r0 g2 A F1 \1 R. A g3 c" z* h// loginAccount();& t. U, l& P! D+ M+ l% @0 a
}
/ R& N, d u$ G0 e2 `% l });0 r$ U1 F6 i2 h; z+ E" _% W+ L
DJISDKManager.getInstance().startConnectionToProduct();- i3 A/ U& r- }! P- Q
} else {- ~ e, N4 j0 y5 t
Handler handler = new Handler(Looper.getMainLooper());
% b) {1 K3 S; M! ^2 a handler.post(new Runnable() {$ |# S: k0 v& X/ f' v6 ]
@Override
+ E1 D6 a X2 L0 ]7 G7 f) V public void run() {
7 ^/ _. x5 b- A( ^" c// ToastUtils.showToast(getApplicationContext(), "注册sdk失败,请检查网络是否可用");4 D, u, W2 E( h1 z1 u
// Toast.makeText(getApplicationContext(), "注册sdk失败,请检查网络是否可用", Toast.LENGTH_LONG).show();- b6 `* d* L, |# p5 _6 `
}* r; J# w" J+ t! P: U
});
6 b3 y4 Z5 }! q* U/ d6 h }
; ~9 _% C/ U0 m5 ~7 m d Log.e("TAG", error.toString());1 l% M! b7 y2 u7 h( t
}
% F- n- l+ I5 X; ^( I: o @Override r" d, x' j& g! p# t e. v' v
public void onProductDisconnect() {
' ^* Y( `/ g, |. l" s Log.d("TAG", "设备连接");
0 M' Y7 C# x( T4 u2 p notifyStatusChange();2 \3 a. {) @8 N% {
} ^$ q/ }4 m5 s4 p
@Override, F1 T! ^) w% E6 S
public void onProductConnect(BaseProduct baseProduct) {
4 p7 p! Q& c, j# K' a. d! }2 D0 u: e Log.d("TAG", String.format("新设备连接:%s", baseProduct));
; \& U v6 H/ C, Z/ H0 S notifyStatusChange();
/ J2 A1 O- M, x4 i5 |1 T }
- J* c3 E- u( T! n0 D; \: f @Override; V( v/ J2 K8 k. |7 h( T8 }$ Q: K
public void onProductChanged(BaseProduct baseProduct) {
/ n! f5 v1 P3 H4 v/ Z }
6 n _9 R/ w! S1 ^2 \, N& x3 p @Override! z* q" n x$ w9 C% G, e
public void onComponentChange(BaseProduct.ComponentKey componentKey, BaseComponent oldComponent,) x# e, {* O5 M$ L, t6 W+ I
BaseComponent newComponent) {" H4 L' L0 M4 p* x0 C. _ j
if (newComponent != null) {
6 n( m# \( p3 `7 U6 j3 h9 m0 C3 L4 I newComponent.setComponentListener(new BaseComponent.ComponentListener() {: W3 \1 T5 e6 b1 a# P
@Override
/ P: [+ F1 d% O" j+ Z% m: W public void onConnectivityChange(boolean isConnected) {" t9 s- T \/ V, r1 |
Log.d("TAG", "设备连接已更改: " + isConnected);
* x) \! P9 t- z* i6 z) j notifyStatusChange();4 {3 N3 g4 A7 w, |9 g( o0 u! e4 x. V
}& H0 A1 b5 F1 n
});; u6 ^% L/ w X( \. ] P; K
}7 S! d" ^) Q/ f( ^6 }. n
Log.d("TAG",
9 U' _% P/ N1 U* n; r8 A, a5 w String.format("设备改变 key:%s, 旧设备:%s, 新设备:%s",/ B m1 R6 j v D7 o& s$ Q
componentKey,
" Z6 ^5 i0 d9 w. I6 g oldComponent,
# d9 ~" G0 J9 l( A) Y newComponent));. C% s" Z7 V) G5 e& X6 C
}
9 ~0 G2 ]7 g9 R0 W3 Q0 k2 C# J: q @Override
, o3 n2 n* `0 l$ Z public void onInitProcess(DJISDKInitEvent djisdkInitEvent, int i) {
# }$ ^+ w' d0 [ }
' L" h+ V# I) U @Override
4 a0 p% }0 d7 G4 |: f9 l3 r public void onDatabaseDownloadProgress(long l, long l1) {
; I1 B F# y; {4 @2 [& x0 h }3 L& e3 z$ F8 ?3 Q* G6 a3 C$ N
};
$ H- J) m( e2 ]0 t9 V& H, } //Check the permissions before registering the application for android system 6.0 above.5 ~) y* h4 W2 ~ Z j* T
int permissionCheck = ContextCompat.checkSelfPermission(getApplicationContext(), android.Manifest.permission.WRITE_EXTERNAL_STORAGE);' q8 a; o$ ?8 j( K& R
int permissionCheck2 = ContextCompat.checkSelfPermission(getApplicationContext(), android.Manifest.permission.READ_PHONE_STATE);
/ p! r; Y+ d8 i" f if (Build.VERSION.SDK_INT 0 && permissionCheck2 == 0)) {6 w; k2 L2 ]+ f/ }- W
//This is used to start SDK services and initiate SDK.4 h+ K4 j( @1 |4 h: m; B7 x$ u
DJISDKManager.getInstance().registerApp(getApplicationContext(), mDJISDKManagerCallback);* q1 k9 v8 R4 d8 v7 P; F$ f3 `" ^
// ToastUtils.showToast(getApplicationContext(), "正在注册,请等待...");: k; l. ] B. M4 ?
// Toast.makeText(getApplicationContext(), "正在注册,请等待...", Toast.LENGTH_LONG).show();+ `3 k0 t# Y- a/ L7 M5 [
} else {) Q9 y7 b4 L0 ]* R5 x
// ToastUtils.showToast(getApplicationContext(), "请检查是否授予了权限");( S% i! Q6 i* B4 I# B. `1 h
// Toast.makeText(getApplicationContext(), "请检查是否授予了权限。", Toast.LENGTH_LONG).show();) [8 ~$ s1 F" V+ O) c& z% y
}
7 v) h! n8 Y! S! i0 F" {# {" _ }
5 m. J- o; h' Q7 _ private void notifyStatusChange() {
* z! n5 b0 w @7 e4 m7 k7 N mHandler.removeCallbacks(updateRunnable);8 L) r. s3 r9 R0 y9 Y
mHandler.postDelayed(updateRunnable, 500);: P% ~: h& V5 [ R
}5 u. t$ y5 m% n" s& }
private Runnable updateRunnable = new Runnable() {
: G( [/ f( q! ^. e3 h @Override
; a. c9 ~+ S; E$ U7 D& J public void run() {
; L% m0 [ T! \; O! I5 h0 i2 | Intent intent = new Intent(FLAG_CONNECTION_CHANGE);, j: v E* _/ G0 i
getApplicationContext().sendBroadcast(intent);
1 s0 r2 ^1 `+ M0 ^ }% m* X# r/ u s0 Z: T0 ]
};
: f( v6 X' |% b3 K3 ^8 d}
$ o6 R5 A9 J, @& {$ O上面的代码是对BaseProduct、Aircraft和Camera类进行实例化,在后续使用中不用再去进行重复的实例化工作,减少内存的消耗。+ V: J+ S1 d v/ t6 o8 \0 \
@layout(R.layout.activity_registration). x; p0 t$ s1 y$ x. Z
public class RegistrationActivity extends BaseActivity implements View.OnClickListener{& x* A+ E% F* @9 Z% }( I: N
private static final String TAG = RegistrationActivity.class.getName();7 S; U2 @; b" E5 I
private AtomicBoolean isRegistrationInProgress = new AtomicBoolean(false);% Z# ~2 Z q; f5 Y( x2 q7 C+ `! {
private static final String[] permissions = new String[]{
( p- G( B) [2 l Manifest.permission.BLUETOOTH,/ W! D9 Z& |7 `) i9 `# _$ r
Manifest.permission.BLUETOOTH_ADMIN,
. ~/ ?6 M! x/ x# h4 g Manifest.permission.VIBRATE,8 @/ q' w5 \5 u6 O
Manifest.permission.INTERNET,
( z- U5 P: J' I# C! q% z( `# ~ Manifest.permission.ACCESS_WIFI_STATE,, p! S! f: J7 I/ l
Manifest.permission.ACCESS_COARSE_LOCATION,
9 L; W+ [7 d* V7 s$ F Manifest.permission.ACCESS_NETWORK_STATE,
5 r4 R# `( R- W& U Manifest.permission.ACCESS_FINE_LOCATION,, y5 A5 y7 |9 D, j8 D
Manifest.permission.CHANGE_WIFI_STATE,
7 g! J# ~6 {9 C Manifest.permission.RECORD_AUDIO,
& @* o9 E8 [0 F+ K* B- S: k Manifest.permission.WRITE_EXTERNAL_STORAGE,! N! R+ u% V i' d0 E
Manifest.permission.READ_EXTERNAL_STORAGE,' N' O% F' j! O3 g, [" o" ^
Manifest.permission.READ_PHONE_STATE,
0 K& h+ e7 N8 } };9 V9 O( l4 [+ t4 S- y. G
- H4 ] j7 k) \/ H) q2 i
@Override6 a: G0 p6 J+ X: m9 S
public void initViews() {
! I3 B, b# g/ h0 A; Z, [* P O, X isPermission();. ~; A5 f! o2 G b7 o8 x
IntentFilter filter = new IntentFilter();
# i( u9 \2 E" |+ G' R, ` filter.addAction(ReceiverApplication.FLAG_CONNECTION_CHANGE);
+ U3 N+ @* \* k, a! a) _ registerReceiver(mReceiver, filter);
: u/ q* j6 a+ x/ e }+ t3 a& B$ |0 p9 w% b9 e$ N
@Override( g' Y6 p5 y+ | |; z3 j
public void initDatas() {
% g2 r2 u9 K8 S z+ V) c- ? startSDKRegistration();
, E; o- c# K9 t v }+ O" p& B! b+ l) d# f
@Override
0 h4 t2 R9 T9 s# F& D2 E K! k. i8 E protected void requestData() {
1 s+ Y2 ~) q1 M, T7 O4 n
8 ]6 M! ^2 ?8 `! ] }
, `+ F# c: O* d8 M
- y0 ?7 u/ r! o9 U; |+ R @Override7 X: ]* _1 Y( U
protected void onResume() {
9 L. L( K1 M/ a# H/ `" P super.onResume();
; _3 y/ S' z" {( O6 F }) l' M' r8 Y0 s. {8 v
8 O! F$ k% {( i6 J2 o private void isPermission() {- C% X6 \- x4 T5 p n" o( m: \4 J) a
requestRunTimePermission(permissions, new IPermission() {. z& B+ u/ _$ _% h
@Override
; e% ~6 O1 M/ Z! ]$ a public void onGranted() {. [ _( u! A* o' G8 }
}
n% F' I& V& f! J: |2 \ @Override
K. _( p2 ~' q" ]7 @/ j' |, S public void onDenied(List deniedPermissions) {' d* Q' w! I0 {! g% Q y6 Q
}! S6 ?& \- g- g5 ]; [8 Y
});1 @2 W0 \) f2 J1 o- q
}
8 v4 w3 Q" W9 l( d/ ]1 V , S) y, a) v) z3 z* B5 O5 O; T
//无人机首次注册
% x( V ]- A* V4 C$ }9 ? private void startSDKRegistration() {
- L7 U# V$ @( |1 E3 T! V if (isRegistrationInProgress.compareAndSet(false, true)) {
5 g& z* g. _6 W8 b AsyncTask.execute(new Runnable() {
6 ~) F r$ i2 E6 S0 \ }2 q @Override' n5 k) i6 o8 c% |! W8 p3 e: x
public void run() {: U( J* J! X+ x
// showToasts("注册中,请等待...");
8 F7 H3 q" x3 W; P DJISDKManager.getInstance().registerApp(getApplicationContext(), new DJISDKManager.SDKManagerCallback() {
& o+ Y' X# }2 |2 k @Override
% b! X( E; B8 ?3 n: y5 O public void onRegister(DJIError djiError) {
- g! q @. K% P; ^& b if (djiError == DJISDKError.REGISTRATION_SUCCESS) {4 x3 @' j6 _7 G$ c$ i
DJILog.e("App 注册", DJISDKError.REGISTRATION_SUCCESS.getDescription());0 _- |- A8 J/ t2 j! ~5 D; T7 L
DJISDKManager.getInstance().startConnectionToProduct();
" s0 J- N" [; y0 h7 K9 H! H // showToasts("注册成功");- x# z0 h3 m! ?! S
loginAccount();; v" E3 ?4 C" |0 ?. b( J6 q
} else {
0 }; C# v% V% d3 @1 g5 a showToasts("注册sdk失败,请检查网络是否可用");
$ ?' ^) n$ o" W" U) ? }
; H+ C& K; U G1 u, b9 N Log.v(TAG, djiError.getDescription());( D; R* k( R/ o8 K) @9 k
}
6 D @: |* d( r' L& F# Z5 k) S @Override$ n R: S4 H6 W+ w
public void onProductDisconnect() {
) ?2 a X9 ~9 _( x( u$ V$ K. h1 L Log.d(TAG, "产品断开连接");8 j# l& Y( B9 T. q% U$ z
// showToasts("产品断开连接");, \+ T1 n3 P4 ?1 f4 w5 n
}
& `% ~+ q3 C' \& i! l5 l8 [6 _ @Override0 K1 G7 ?3 j3 x$ [0 J; Z1 O; V; C
public void onProductConnect(BaseProduct baseProduct) {& R) R) e& P. \! y+ P$ f5 f6 q
Log.d(TAG, String.format("新产品连接:%s", baseProduct));
V6 S; j- H g/ \9 u, C: W // showToasts("产品连接");
5 i+ `, J) v3 V b4 t }
. y( y$ L4 m% C. c. S7 i @Override9 n0 r& ]. ]6 x) c$ Y
public void onProductChanged(BaseProduct baseProduct) {# ?0 a) B3 {5 c$ k$ G
}+ b" R$ ? Y5 q3 y2 N6 x
@Override
5 J9 P# k/ h: ~. n public void onComponentChange(BaseProduct.ComponentKey componentKey, BaseComponent oldComponent,
; `0 ]1 x" z# D& V9 u BaseComponent newComponent) {' r' w) }6 ?+ I* u( l2 k- b
if (newComponent != null) {
6 S8 {8 W: M& _: ~' K newComponent.setComponentListener(new BaseComponent.ComponentListener() {; Z1 S4 Y3 \* q2 x6 C7 ~8 A' l
@Override
0 W( M& N. q5 K8 | public void onConnectivityChange(boolean isConnected) {
g+ }: O* d4 v3 D2 I Log.d(TAG, "组件连接已更改: " + isConnected);
8 h! Y4 w, @) U/ w }+ e! R. G- `1 l- Y, G2 `3 B5 @
});
+ |: l( T' ~2 {( h+ o }
3 H8 a# R/ G- S f% k Log.d(TAG, String.format("改变设备Key:%s, " + "旧设备:%s, " + "新设备:%s",
6 }$ x" c1 J- g componentKey, oldComponent, newComponent));: \3 d$ b9 \ i5 A9 [1 }
}
3 }# e) z2 `) V1 d @Override
- E7 ?$ E8 z. N1 y9 T2 ~9 [) l public void onInitProcess(DJISDKInitEvent djisdkInitEvent, int i) {
& h6 g' s2 P9 _. i0 Y }1 M* B$ M9 U+ e% o4 f+ B' f3 _
@Override
1 |9 V! H7 S( [( Y2 @: r& K0 R2 L public void onDatabaseDownloadProgress(long l, long l1) {
' ?, i7 x' I5 z5 ] }
7 Y# K5 q) q m9 J });
# T \& z6 ~/ [: ^" { }1 `( O& [- p8 }3 q* j
});8 K: R4 ^: G4 H* b# D- k7 j) b
}
6 I7 i/ @( v% r }
" j) U9 U7 t3 t: f9 F protected BroadcastReceiver mReceiver = new BroadcastReceiver() {
@& ^0 k5 k6 s2 c @Override
7 p9 c q l% U' A1 A; M" c! F9 ` public void onReceive(Context context, Intent intent) {/ m9 h. ]0 T! n( w a4 L
refreshSDKRelativeUI();7 B! O& s' K% t- } ]/ ]. `( K/ I
}6 i7 @! Q) m" K9 @" Y" C# c x) R- e
};
. x1 q Z3 w) E* u( c* _ private void refreshSDKRelativeUI() {
7 E; F0 W7 a1 |& ] BaseProduct mProduct = ReceiverApplication.getProductInstance();; r* n: k3 P6 p! ~5 j. i( M% B, G' m$ ~4 E: p
if (null != mProduct && mProduct.isConnected()) {
! y1 ?; Y4 m# x3 b: t7 j4 j+ J r Log.v(TAG, "刷新SDK: True");: d# x: B( O3 G- t6 g
mButtonFlightTask.setEnabled(true);1 @9 F$ R7 M, D( R/ A' ^3 @; ]* ]
mButtonSettingRoute.setEnabled(true);. _) R, p% ~% w* M0 Z5 B+ o
mButtonFileManagement.setEnabled(true);9 E% Z( N: z3 a
} else {
, M/ x1 |1 o. u% U! R3 Y Log.v(TAG, "刷新SDK: False");/ H2 ]& S7 w" b& J8 _
// mButtonOpen.setEnabled(false);- D4 E5 V$ q. i' k
// mButtonSettingRoute.setEnabled(false);9 }( E; V' g4 K, Q0 W
// mButtonFileManagement.setEnabled(false);8 z' _: Y% u6 a7 X! F! e
// startSDKRegistration();8 j% Y2 Z( ]& p
}+ z2 N, x) q) u
}
" q, v" w7 _/ f& @! O G protected long exitTime; //记录第一次点击时的时间6 }, u/ n" v5 _7 P6 Y" m5 ?
@Override! M# W( M9 ]9 W& G# { W( z: S/ p
public boolean onKeyDown(int keyCode, KeyEvent event) {1 C6 d9 ^8 z p X
if (keyCode == KeyEvent.KEYCODE_BACK0 \) e8 F Z; l0 e: o) K) D9 A
&& event.getAction() == KeyEvent.ACTION_DOWN) {: m% U7 x- ^) N1 }8 s# P
if ((System.currentTimeMillis() - exitTime) > 2000) {
: F( {" Y; f$ _+ } showToast("再按一次退出程序");/ [' a" z0 x% {" s# X- W
exitTime = System.currentTimeMillis();5 I5 x7 i, p% r5 N; B
} else {% r9 r9 q2 T+ `" z
RegistrationActivity.this.finish();8 ^/ a3 c1 O/ {4 n9 {$ z
System.exit(0);, V7 Y0 r+ }% S9 a
}
6 W1 g! `% }: e O return true;
* b5 H& `2 c& H" j: f4 l7 h3 { }1 s3 C5 d% }9 I1 H2 R
return super.onKeyDown(keyCode, event);
; Z- G( Y3 g+ |1 z6 l( [ }
" A8 M7 I# V, H' g g- W, M3 U' A1 J9 \9 I: X3 F m$ Z& S
private void loginAccount() {
. I0 Z+ I/ f) }9 M$ p7 y- T/ W UserAccountManager.getInstance().logIntoDJIUserAccount(this, new CommonCallbacks.CompletionCallbackWith[U]() {8 A" I7 @6 i! Q, ^" L
@Override
3 ]. q' m- z* l0 z6 X5 {& R5 G8 T public void onSuccess(UserAccountState userAccountState) {
: L. B9 M. b. P) L runOnUiThread(new Runnable() {2 K( ^# y- e8 S! A2 j: A
@Override
% Q6 Y$ e2 N/ g- i' l. t4 y5 |0 g public void run() {
! A% @) K) k4 X" ` mButtonFlightTask.setEnabled(true);
4 k, n) s; P8 U5 B# c) ~" c mButtonSettingRoute.setEnabled(true);0 j+ u" _' j u5 C
mButtonFileManagement.setEnabled(true);
0 Y6 x3 U0 m* K }
- r* a# R/ F% p7 _+ w5 t! v });
- C6 }0 z4 i; e) s1 C5 W- _7 z: } }3 J8 @$ z: N: r
@Override- U* @0 F# E- ?( r+ {
public void onFailure(DJIError djiError) {) N, C& ` V' W$ _; M. |; p
}" g. l! z% m4 k& C& S
});
3 y+ H5 Q1 r- Y" S) l2 o% } }: d9 }. M3 ?3 J9 U; N
}! T6 K# h2 P% C; F- f
上面的代码就要进行第一次注册登录了,当然你不需要自己去设计登录注册页面,大疆会调取自己的登录注册页面供你使用。! }' g0 I& a& a; t1 q% D4 R
5vvpks3hoqw64023083305.png
4 S7 @! u P. P# s
安装提示注册登录即可。
) F- ~2 M0 H! {1 ?上面的这些做完后,恭喜你!现在,您的移动应用程序和飞机可以在中国使用而没有任何问题。换句话说,您的应用程序现在可以看到飞机的视频流,并且飞行将不仅限于直径为100m和高度为30m的圆柱体区域。* `, Z2 F2 w( p. h \& U$ E& S5 f
34 `7 h. ~1 K3 p* k2 {# ~% V, c+ o6 Q
飞行界面使用2 w- z1 ^: b& w! E
虽然说可以正常飞行了,但是飞行需要设计飞行界面。那么创建一下飞行界面的UI及逻辑处理文件。逻辑处理文件中包含了获取飞机的实时姿态信息,代码中有注释内容,描述的内容就不多说了。, m* |7 l; J ^
; z9 O2 N! D0 u+ e/ j, K( p) r, k导入UX SDK依赖' q: E8 J; j/ @/ X- g x
上一节有说过集成部分,其中内容有导入UxSDk 的操作,这里再顺便提一下。再build.gradle文件中加入implementation "com.dji:dji-uxsdk:4.16"依赖,等待安装即可。
4 @6 {" e% a$ N9 Z" c$ h7 o9 m5 o. l" p2 y7 I; ]) R
设计界面UI
5 o/ V5 A- m- W5 K$ M% o8 m. `创建MainActivity文件及activity_main.xml。 G3 {3 a2 [- ~
RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"' u) R- E2 N$ w3 L
xmlns:tools="http://schemas.android.com/tools"
2 G6 Z7 q: l0 N. m( u( } xmlns:custom="http://schemas.android.com/apk/res-auto"
' h/ p; O# P( ]" m android:layout_width="match_parent"
& u) W; @- F, `" d, b, a- R' y android:layout_height="match_parent"' n( R1 @* w( A5 {
android:background="@color/background_blue"
& v- ^( e8 e( q$ {' u0 a5 y android:id="@+id/root_view"
5 F( p9 M6 K% s" o. Z$ { tools:context=".ui.MainActivity">
( y0 I6 X3 j* ?7 F
9 B' \; `/ c0 H3 m3 I; v0 U RelativeLayout" g2 x9 Z# O* I- m4 T1 o5 n
android:id="@+id/fpv_container"
6 ]& {, @* q7 [3 ] android:layout_width="match_parent"0 ~' W2 x( }) q8 h7 ?. b
android:layout_height="match_parent">
$ _1 [) c% h/ a3 a dji.ux.widget.FPVWidget0 b& j$ r# N$ E, c
android:id="@+id/fpv_widget"' U8 V: J- }+ }% M3 ^; j* L; e# W" g# q
android:layout_width="match_parent"
8 I# P) {) ^: R# _# ?8 F8 l8 ] android:layout_height="match_parent"$ A: k7 h& n1 h8 t4 F0 L
android:layout_centerInParent="true". x. R: S8 Q2 L! s+ V2 i
custom:sourceCameraNameVisibility="false" />- H1 N7 v h M# y8 q4 W" \1 {
RelativeLayout>' A$ k5 H7 r1 Q* F$ @& p2 k
dji.ux.widget.FPVOverlayWidget8 `: w" x) L/ E* e m
android:id="@+id/fpv_overlay_widget"3 n/ Y0 @$ [8 g! D" a9 ~: K- c* B
android:layout_width="match_parent"- z0 `6 x5 X% ~% F
android:layout_height="match_parent"/>- f1 P2 m/ w' I0 W
RelativeLayout
4 x% T' c; i6 I4 B5 E android:layout_width="match_parent"! j {" V6 v9 y& R" J7 @9 k
android:layout_height="match_parent"
: I! G# s3 i4 s; q# w e" R android:layout_marginBottom="40dp"3 t/ n K9 k6 y6 M9 T
android:layout_toRightOf="@+id/TakeOffReturnPanel"
# b$ C& S O! g( w% T" C android:layout_toLeftOf="@+id/CameraCapturePanel"- q3 r* m E0 V$ r) R4 k1 [# B
android:layout_below="@+id/camera"
3 Z4 l# y( C1 W/ t$ T tools:ignore="RtlHardcoded">* y: R4 Q; _( E" _- b4 ^; v
dji.ux.widget.RadarWidget( ^5 M9 o6 S1 S& h/ u
android:layout_width="wrap_content"2 H$ w1 Z8 p @$ F/ {
android:layout_height="wrap_content"
7 J& Q, x. m( r6 b android:layout_centerInParent="true"/>
! O, @& ?3 v1 c- R RelativeLayout>+ Q; v3 Y) d7 f* K( C: y
- c- {4 U3 S F2 r LinearLayout
$ ^! u+ w- Y$ H7 r* P4 U android:id="@+id/TakeOffReturnPanel") K; e5 X, \: i0 z; L6 h$ U
android:layout_width="40dp"
8 g1 {6 B S1 |( [ android:layout_height="wrap_content"( P3 i) l& B p2 B) Y0 d+ `
android:layout_marginLeft="12dp"
: m; ?3 h+ D4 t/ y android:layout_marginBottom="4dp"2 d& W: A: ?& ?2 P0 P) }0 K
android:layout_marginTop="50dp"; t! ]+ Y+ g' I1 `! }/ s, H, C
android:orientation="vertical", b' D7 C9 @ z/ C% ~( y
android:gravity="center">( m( H- \8 b9 c1 M$ A/ A2 y
ImageView
) [0 j0 U8 w$ U& h% X' \ android:id="@+id/img_show_back"- c5 t" l D; e4 G
android:layout_width="match_parent"5 O. C& i2 W$ R! h. P w; | C
android:layout_height="38dp"
; N3 q( [/ C1 _3 [- ^ android:src="@mipmap/ic_back_36dp". P9 ?! U5 y2 ^5 A$ U7 o& O& M
android:layout_marginBottom="10dp">ImageView>
9 h/ t! A- B7 N; N dji.ux.widget.TakeOffWidget
1 {" [+ s3 r& A) x7 [ android:layout_width="40dp"
; I2 P3 Y4 I5 x; B) P% X7 L7 z9 T- @ android:layout_height="40dp"
+ y* l) Q! h: F: Q. y android:layout_marginBottom="5dp" />
, x; J W/ V3 s" Q3 _" y9 i dji.ux.widget.ReturnHomeWidget4 }2 E" u. U& V( O
android:layout_width="40dp"
1 n0 Z$ J! } `, R% v# u android:layout_height="40dp": f r7 Y t" x; v
android:layout_marginTop="5dp". n% w3 v$ p& w4 v8 [1 i0 ^6 u
android:layout_marginBottom="5dp"/>0 u/ ]. `5 d W9 V" v* x9 R
ImageView
! N8 |! @. i1 |& D; ?2 g android:id="@+id/img_live", `! Z" Z8 j, Z/ z
android:layout_width="35dp"0 g% o x: W4 A5 y* W3 ?, P- U
android:layout_height="35dp"4 \8 d0 S$ U7 T, V% h( u
android:layout_marginTop="5dp"8 L* t$ [& e0 C, O2 a- |7 r' C
android:layout_marginBottom="5dp"
0 @ x0 n) ~/ j9 S% v. \9 k android:src="@mipmap/ic_live_write_36dp">ImageView>) c I1 v* Z% B- o. s4 @- H Q
LinearLayout>
" {% g, O$ w+ p& T FrameLayout$ z' \3 O/ n% I, D! Y, |0 h7 s# C
android:layout_width="150dp"
: m% g6 D: v3 i+ | android:layout_height="100dp": u0 T/ p* t% J/ w; @7 {
android:id="@+id/secondary_video_view"
( Z) D; S- J: [8 z& W4 w android:layout_marginLeft="12dp"
( b9 C1 j' ^( B8 ^# n2 ~$ q' w android:layout_marginBottom="7dp"6 o+ D: u' O) d8 [6 c( L1 F
android:layout_marginTop="50dp"3 ] i/ K9 u* L
android:layout_alignParentLeft="true"
# N& X c" r4 V v: P android:layout_below="@+id/TakeOffReturnPanel"
% V0 `) k7 S# U; | android:background="@color/black">. j5 v; N/ C& D) D8 s4 j
dji.ux.widget.FPVWidget
& ?2 R+ q! `/ t' G7 ]' B) p" f android:id="@+id/secondary_fpv_widget"
7 }: L% b9 q; ] android:layout_width="match_parent"5 P8 k) x3 }6 M; ?( ~0 g
android:layout_height="match_parent"
- r+ O* N9 p$ I! E; Y, t* M; @ custom:sourceCameraNameVisibility="false"
$ R. C* [5 x$ u$ g1 K custom:videoSource="secondary"/>
- [0 X, l6 Z3 K4 w$ y" ^ FrameLayout>
- a3 _% k+ Z) x1 Y n' A dji.ux.workflow.CompassCalibratingWorkFlow- _( ]1 y7 B9 k! H6 F! t5 M8 P
android:layout_width="match_parent"
# Z: x( d; d. ] android:layout_height="match_parent"/>
' S' _" I" K6 N7 s8 ? dji.ux.workflow.CameraSensorCleaningWorkFlow+ f! e, ?0 D8 q1 E* F
android:layout_width="match_parent"
6 z" ~) J5 ]5 O android:layout_height="match_parent"/>3 `9 \0 C( _+ s. z m* N( N
dji.ux.widget.RemainingFlightTimeWidget
. P7 n( O+ U* [ android:layout_alignParentTop="true"
; R7 \2 y+ ]: P. Q; c9 M$ \ android:layout_marginTop="18dp"
( d. P0 ~' {0 ?7 k2 y android:layout_width="match_parent"
4 b9 a9 A6 t* `! j) J8 g android:id="@+id/remaining_flight_time"8 v5 f. r9 k7 O( `
android:background="@color/transparent"
" f, [( H6 v0 S2 S; m) K android:layout_height="20dp"/># C' Y* x9 x, {7 X! x* [
LinearLayout; w" o( _( V; R5 e/ j8 P0 H
android:id="@+id/camera"
$ ^5 w7 H, ^# k: b6 d) j. H3 s, ^ android:layout_alignParentRight="true"
) a3 i, q( q$ C Y+ F4 S9 z9 b* z" l android:layout_width="wrap_content"
) Z5 s5 { x9 v7 `) D android:layout_height="wrap_content"4 f* s7 r- X5 }0 X
android:layout_below="@+id/signal"3 f& `# Q& q5 U4 G
android:layout_marginTop="15dp"
: p$ K y/ S/ P android:background="@color/dark_gray"4 O4 }/ E, L& d7 J9 F9 |, ~
android:orientation="horizontal">
+ t# _5 _5 S0 S; O( W7 |4 q dji.ux.widget.config.CameraConfigISOAndEIWidget% T/ h! [$ M4 C" Q
android:layout_width="50dp"/ c$ O8 n k, e5 c% F
android:layout_height="25dp"/>( i% i+ j8 m4 z6 I7 e
dji.ux.widget.config.CameraConfigShutterWidget
3 ^0 @8 L' r! G- _0 [2 U8 {# W" W android:layout_width="50dp"
- \6 H1 a" @7 t. r+ d* O android:layout_height="25dp"/>/ M, f" w' R5 \. b
dji.ux.widget.config.CameraConfigApertureWidget
6 K5 O# R3 L* I, K7 I android:layout_width="50dp"
" s1 v3 |- y6 q" U android:layout_height="25dp"/>
y* y* z* V2 }2 ]* ]# E: O dji.ux.widget.config.CameraConfigEVWidget$ j, R A/ f+ i: x
android:layout_width="50dp"
) F( n$ Q5 I+ c& w# v android:layout_height="25dp"/>
3 O' V0 b8 e" F; O L& y dji.ux.widget.config.CameraConfigWBWidget3 ^8 t$ k0 o# u& S5 _! J
android:layout_width="60dp"
9 s& s( o3 J, M, n0 U android:layout_height="25dp"/>
. ]6 c1 y7 \5 k6 I dji.ux.widget.config.CameraConfigStorageWidget
% V# w! e$ l- u' l' g/ ~ android:layout_width="108dp"
/ W9 W( h' E; Q) h# H" G" |. q android:layout_height="25dp"/>
( i4 C j. w& g% k% O4 A dji.ux.widget.config.CameraConfigSSDWidget& M$ g8 T% K' d: w# H: X
android:layout_width="125dp"
2 l4 h- t# D* U1 g8 g) O android:layout_height="25dp"/>
5 p: C: K) ?4 H LinearLayout>) b: d1 Y U' D% C+ r! D
LinearLayout4 i5 g' A& c1 t' R. q
android:id="@+id/camera2"5 b( o$ q4 i1 M9 Y0 h; ~
android:layout_width="wrap_content"$ T$ p8 s" U3 T# M! G0 V) Z1 m
android:layout_height="wrap_content"+ a! ~( m$ F) ^" z# C% d6 ]/ i
android:layout_marginTop="5dp"
# L2 \; f, e. G8 }; W' C5 F9 [( | android:layout_below="@id/camera"; S4 `; ]( f: d$ m7 \. @' ^
android:layout_toLeftOf="@+id/CameraCapturePanel"% {- ^ \+ _: }$ b# j! W2 y
android:background="@color/dark_gray"& k: Q. n( c, I5 y, S
android:orientation="horizontal">% R6 w2 w, G# T7 C5 ~* s
dji.ux.widget.SpeakerWidget* Q1 h2 q0 Z+ _3 t4 K% m8 P$ y$ p
android:layout_width="35dp". x( S4 j. G, I0 i" x( c8 K& j
android:layout_height="35dp"/>( _$ F, h' B2 g! J. p. x* K8 L
dji.ux.widget.AutoExposureLockWidget0 A/ e1 w+ I+ ?7 [8 ?7 U5 x
android:layout_width="35dp"
9 @* X$ n( g) z( c- Z android:layout_height="35dp"/>5 O9 @) P4 N' U [: w' e
dji.ux.widget.FocusModeWidget) G* R# g5 w& \- G, @+ Z
android:layout_width="35dp"/ m8 A) i' n2 _% n7 J5 u
android:layout_height="35dp"/>2 k/ W5 _! \3 }9 J: v
dji.ux.widget.FocusExposureSwitchWidget
# h% B7 v4 S) |. S- I android:layout_width="35dp"
/ A- [5 y. i3 p, n; e7 W android:layout_height="35dp"/>' g- r# C% k% \9 r; S( P9 j: `
dji.ux.widget.BeaconWidget
8 |& z! B' b1 I+ q! B* Q android:layout_width="35dp"! z; M3 ?: a' @, L
android:layout_height="35dp"/>& e9 a" {2 W$ f1 ~/ N& ?
dji.ux.widget.SpotlightWidget
, Z |: p- r* a0 F. m android:layout_width="35dp"
/ J C2 o% N7 ?5 S5 [* M9 z android:layout_height="35dp"/>8 n; R2 B# S$ q% T# T
dji.ux.widget.AccessLockerWidget
5 U; `, \5 [8 W9 }+ Z' H' T9 e& k android:layout_width="35dp"
4 Z% L, k) @8 K6 h; x: g android:layout_height="35dp"/>
! i/ Q5 f3 D8 C, a LinearLayout>. y- _ \6 _' p% o& S* q, S# \
dji.ux.widget.ManualFocusWidget! I* F) A1 f+ u2 C
android:layout_alignTop="@+id/camera2") i m5 \+ W) I, B6 k( Q
android:layout_toLeftOf="@+id/camera2"
5 i1 X1 c* ^; F+ F- V: s6 P# C: r android:layout_width="50dp"
, g9 A4 z3 \% o android:layout_height="210dp"
* ]8 a, h; U' F& x; r, q. h tools:ignore="RtlHardcoded"/>
& l7 G/ d) E6 `; I) V( f( K dji.ux.widget.MapWidget
" V; c% |8 ]! n" x7 G# x( M) ^, q android:id="@+id/map_widget"9 K9 t2 w1 F/ S% V7 F
android:layout_width="150dp"
1 v1 m( R+ r' K android:layout_height="100dp"
" B9 Y' `# D- d) t android:layout_marginRight="12dp"7 {! V7 v- ]& X, b# c! ]3 g" {
android:layout_marginBottom="12dp"
* ]! q6 z3 \, z: B0 `. H5 O android:layout_alignParentRight="true"
. x8 U# p1 m8 o7 k android:layout_alignParentBottom="true"/>
0 A2 w/ H I7 e* _ . F2 y( S4 } A. o# l
dji.ux.widget.controls.CameraControlsWidget& o6 I# Z0 s- s& o# D. j
android:id="@+id/CameraCapturePanel"
7 V$ [4 k O+ O. o8 ~# a5 K3 _1 {" n android:layout_alignParentRight="true"2 E" [. D$ o9 |' s& c* L; x( V. F
android:layout_below="@id/camera"
Y+ Q$ f1 }9 } android:layout_width="50dp"
+ t$ u: b, j% Y6 E P& d$ Z, L5 c android:layout_height="213dp": F' J, X0 m$ i0 s8 P8 Z
android:layout_marginTop="5dp"
$ M) R+ L/ B) M* T! F tools:ignore="RtlHardcoded"/>
# W5 P8 W2 @7 D# B
: t: V9 ]: W; P& `& G, H$ [ LinearLayout
" I$ y4 E2 n) S9 c android:id="@+id/signal": y% p9 ^* c4 S5 V$ W* }" ^
android:layout_width="match_parent"# C. c9 r; y1 D4 v# q" @7 Z3 g
android:layout_height="25dp"2 t3 S! ?: t0 B2 r
android:background="@color/dark_gray": j% Q* o1 j9 ^% f0 W/ J! N6 [/ W, e
android:orientation="horizontal">
& ]6 N% p Z# u/ j; Z: n3 W dji.ux.widget.PreFlightStatusWidget b, c( l, W! M9 u8 k
android:layout_width="180dp"
1 L6 A$ y2 ]8 d3 f android:layout_height="25dp"/>% h$ m. Q% ]0 Q" n
dji.ux.widget.FlightModeWidget; b9 m4 Q, |! v4 M) ~% W
android:layout_width="103dp"
. w8 ^1 p% j) N- T( K% f7 }4 A android:layout_height="22dp"/>" X5 b1 n* K- I9 A/ U$ U, { L
dji.ux.widget.GPSSignalWidget
; q+ @$ I5 |' D) H: g: F android:layout_width="44dp"
9 B0 u/ A p5 j/ U6 T, l% J android:layout_height="22dp"/>
( E* ^3 u9 z. n$ L9 |- H; z, Z dji.ux.widget.VisionWidget
7 } X2 Y. y" t9 l D* a6 n: r android:layout_width="22dp"% X" ^- ]" }+ B; K0 S( L; {- v' t" }$ a( S
android:layout_height="22dp"/>7 }# U& ?' ]+ [8 f! {; B* p
dji.ux.widget.RemoteControlSignalWidget
' W5 v9 c- ]7 z/ T" K7 d android:layout_width="38dp"' U$ w3 ^/ n1 l4 L. j7 M, e
android:layout_height="22dp"/>; _1 [# h: I+ r Y6 K7 A
dji.ux.widget.VideoSignalWidget
& G# q" E' y+ l, w5 h android:layout_width="38dp"
( `( n% v5 s5 q/ H2 W' h' X android:layout_height="22dp"/>
8 g) E: V- O8 [; e dji.ux.widget.WiFiSignalWidget
8 J$ L6 J' Q1 M+ ? { android:layout_width="32dp"3 j+ S1 t: U7 _9 b4 Y
android:layout_height="25dp"/>
8 i7 q, M4 ~# A, s7 H1 V7 A% \& c4 ^ dji.ux.widget.BatteryWidget3 h6 W+ ]( I2 ^
android:layout_width="96dp"
3 |7 u5 g% A# J( n! y4 A) O3 \* r# b android:layout_height="22dp"
9 z4 r- l8 O0 O9 u8 \ custom:excludeView="singleVoltage"/>
/ H# P4 y) D. X dji.ux.widget.ConnectionWidget
0 }; I# {2 d. s- v1 w( e0 ~ android:layout_marginTop="3dp"
k2 x J6 I- B* \7 R/ G9 V7 Y: O% G android:layout_width="18dp"
/ @; I7 _, {& d# B android:layout_height="18dp"/>
- }5 X; k! Y: I7 {/ ? [& I LinearLayout>( z0 B0 L- w6 F/ g- S$ w4 m
LinearLayout/ `! _+ S: v0 k4 i6 a/ y; v" n) z
android:id="@+id/dashboard_widget"
( s* F+ j& S( [* x android:layout_width="match_parent"3 z' e3 T9 N# t! m7 {9 W) C
android:layout_height="wrap_content"1 ? @9 t, Z7 `; }& P9 r9 Z! P
android:layout_alignParentBottom="true"
% g1 p# Z8 W+ ], e q* Q4 ^/ F android:orientation="horizontal"5 z$ P+ c+ n9 t) r. W/ I9 n$ q
android:padding="12dp">9 X1 O9 F9 M! Z1 s; T0 {% Y8 w \
dji.ux.widget.dashboard.DashboardWidget
9 A3 J1 L% K" e- f# }6 T+ p6 O android:id="@+id/Compass"0 A3 w2 x6 A/ G. E1 t B Z# ~" E
android:layout_width="405dp"! n- e. E1 i7 Z
android:layout_height="91dp"
5 J/ n* v) | M2 l) X android:layout_marginRight="12dp"
& I; K* Y. M Y: s$ R* s tools:ignore="RtlHardcoded" />
: x/ @* L& [# j6 u! P LinearLayout>$ F6 S' t' k- Q8 L. e# j+ l O7 n
, F" ?0 n7 e1 O0 q% N, Q) ?2 P* d
" _9 G s* R) `; C+ h& H0 A, {
' n( t- z4 b8 I0 A5 J: U) N4 ?6 c l dji.ux.widget.HistogramWidget; B) _5 N% ^" A7 w( v- o# a/ Q
android:layout_width="150dp"! N* _ `% q, W- {5 ^
android:layout_height="75dp"
9 k9 J6 X' |. L+ @! B2 ]5 W5 b android:layout_centerVertical="true"
8 G7 K/ |# h! o/ {: u2 M4 R9 \ android:layout_toRightOf="@+id/TakeOffReturnPanel"! A4 z* I$ d5 J$ Q5 @
tools:ignore="RtlHardcoded" />
6 V! [8 ^! | m% z: y' ] dji.ux.panel.CameraSettingExposurePanel
- W& g* z+ T: O! |, Q4 l android:layout_width="180dp"6 R3 x" H7 D! J. p4 X
android:layout_below="@id/camera"
$ ^8 @8 N, Q6 b% ]/ b android:layout_toLeftOf="@+id/CameraCapturePanel"5 P0 E6 U# v' ^0 V k! ]
android:gravity="center"
. x2 |7 W1 k) t1 c android:layout_height="263dp"" Y$ p1 m9 q5 F/ g* x7 o2 o6 m
android:visibility="gone"
" I2 K( C: a2 `: a* A4 M tools:ignore="RtlHardcoded"/>
0 O x; o# I( B! c dji.ux.panel.CameraSettingAdvancedPanel
% o3 s O6 v' p2 L0 s; p android:layout_width="180dp"2 S3 q1 U/ i/ f; Y
android:layout_height="263dp"
) f1 V' N6 C+ M j- L" H9 I android:layout_below="@id/camera"
6 N7 e0 x% f0 u0 v$ i android:layout_toLeftOf="@+id/CameraCapturePanel"
2 d. v$ a0 x5 O. f% w1 l android:gravity="center"
) A1 h" z( V( q8 k android:visibility="gone"9 l; y! I8 H1 \) f3 q
tools:ignore="RtlHardcoded"/>
# T# D P8 g) E' T/ m( {, K dji.ux.panel.RTKStatusPanel
8 @6 Z$ |0 K6 { android:id="@+id/rtk_panel"
" ]) G: G& D/ n. M0 _8 ] Q, U android:layout_width="500dp"5 ]; X. M) u; G. d
android:layout_height="350dp"
: a% c8 I; V2 _. o8 f4 R android:layout_below="@id/signal": D/ z- Y) ]: N( g7 |5 [
android:gravity="center"
! m: t! l7 i. r% h5 h r0 a7 C8 a android:layout_centerInParent="true"; C+ f# I& f4 H( O# J7 @1 W
android:visibility="gone"/>
d2 h- X( R; D) b; @- ~/ X8 U dji.ux.widget.ColorWaveformWidget
9 f+ f6 ~7 H2 d$ y android:layout_width="394dp"' Q3 y ^$ g$ r9 Y& q3 h
android:layout_height="300dp"
Z3 h' y9 e! l& u android:layout_below="@+id/camera". K& p0 i i- D5 q- j3 |" V+ c
android:gravity="center"
( t( n% R7 A7 a5 F2 d, K android:layout_centerInParent="true"
- R1 e- a/ Y8 U3 P android:visibility="gone"/>
4 H7 O _, U# f4 W% \' x K; v3 W 4 i$ E, g d5 I5 }- \3 c6 V
dji.ux.panel.PreFlightCheckListPanel
) ?, m* d) R# ]8 D+ X android:id="@+id/pre_flight_check_list"1 g0 F7 l/ O9 ~* b
android:layout_width="400dp"; x3 T6 [/ F! s2 o. Q' {
android:layout_height="wrap_content"
$ Y/ h9 `7 z" v" n8 S android:layout_below="@id/signal") I8 m" y) r2 o& l+ N W# G( S
custom:excludeItem="ESCStatus"
, J) Z2 h2 h0 A3 p- Y android:visibility="gone"/>
7 P& A W( B0 [' S dji.ux.panel.SpotlightPanel
E. D% U9 o) r android:id="@+id/spotlight_panel"
. c6 }6 T0 B, Y4 p" `. Z7 |4 s android:layout_width="300dp"6 d4 I& r- h3 e) z3 L
android:layout_height="wrap_content": P% j5 o; g2 R6 n- l. d
android:layout_below="@id/camera2"4 ^+ O: k5 x! D1 @
android:layout_alignRight="@+id/camera2"
6 N3 l4 ^# f; r c: K: S/ r android:visibility="gone"
! @( x! C7 d% x0 {: a android:gravity="center" />( S6 R* M' n7 s" B
dji.ux.panel.SpeakerPanel
# C K$ H' p/ y i android:id="@+id/speaker_panel"
: P$ Z! `9 y1 \: j8 ?% D android:layout_width="300dp"( V! q! q* X, O! q% C7 x6 g+ \
android:layout_height="match_parent"
: @' z7 w7 t% p6 p" c android:layout_alignParentLeft="true"* Y4 |+ ? B, d1 J* `
android:layout_below="@+id/signal"0 p; j% S, K* w8 u& h' H
android:visibility="gone"/ a r1 U4 N$ i/ f, m
android:gravity="center" />! f$ R) a. H" O( ~4 |9 T
RelativeLayout>
( e% a$ Q. v$ R4 d9 |@Layout(R.layout.activity_main)1 T' X/ \4 Q5 q+ M4 P* A
public class MainActivity extends BaseActivity implements View.OnClickListener {
1 [/ d$ g: D' A- B @BindView(R.id.img_live)
0 X+ f- k4 [! x4 ]6 L ImageView mImageViewLive;
4 l6 T0 {3 |; P |& L7 b private MapWidget mapWidget;3 Q2 @- R$ v5 r7 I% [
private DJIMap aMap;! Q! N) A6 Q, M! M. y9 f/ l
private ViewGroup parentView;
( \) [3 W0 [! D" k private FPVWidget fpvWidget;5 C0 L" ~: f/ G3 O0 C; T
private FPVWidget secondaryFPVWidget;% [# F3 N' J( y
private RelativeLayout primaryVideoView;
' i! t/ \7 q. e" m3 B; Q( i- v private FrameLayout secondaryVideoView;
. r- T7 v# Q: B3 ]1 v. V private boolean isMapMini = true;
3 X2 j& T0 O, g1 } @ private String liveShowUrl = "";: h9 w; T0 @- V$ {( ] y1 @
private int height;
) K0 r$ F8 @& z/ r5 h3 @; p5 r5 S private int width;' {% J' g1 B/ s2 y1 p
private int margin;
/ ]- a% L' S) g: ~+ i4 O private int deviceWidth;# Z" c" E1 T8 k% R; Z7 ^/ ^4 t
private int deviceHeight;
2 D9 R9 P) h1 H8 { private SharedPreUtils mSharedPreUtils;
5 t$ [" D1 D8 Q- r' t- N //unix时间戳
! o# O! F1 e2 E/ ~1 b8 m+ J private String dateStr = "";1 R; o5 Y8 L) r( I
//飞行器管理器5 w& `! u! w( w0 T
private FlightController controller; s z% R9 `! G |/ @
//经纬度
: Y* o# O& o4 e9 q8 _ private double lat = 0, lon = 0;
" j4 K+ U1 J) M" G- | //高度
5 @, @1 Z+ H* T+ A private float high = 0;0 T/ k! z+ e( [/ k0 K$ f& f
//飞机的姿态4 U, ~8 {3 F8 M( r
private Attitude attitude;
a z2 I: X$ S1 V" r% Z7 G) D. s //俯仰角、滚转、偏航值
( i1 ^3 s- @5 s! b6 e) Z& Z private double pitch = 0, roll = 0, yaw = 0;2 t( n5 b2 }( y1 y# X: D6 Q
//飞机的速度
, @' A! g, ^/ ]- R F6 X private float velocity_X = 0, velocity_Y = 0, velocity_Z = 0;
9 x8 _# d8 V5 W) F0 p //飞机/控制器电池管理器# g% ~. E5 u6 L7 U
private Battery battery;
6 L( ~1 s" k" U( f" T) b. H9 `. r* T7 ` //电池电量、温度
0 z: p+ `( q1 }7 a }; f! t private int power = 0;6 [( L3 p# V% P6 } R( T5 X) O
private float temperature = 0;
9 _& G% g1 d1 b7 C& e: { //云台管理器
8 m, T4 S3 x' M% q- L* S( T private Gimbal gimbal;
. e5 M- n7 p$ ` //云台的姿态
& U1 U- d9 g& h) ~9 a private dji.common.gimbal.Attitude g_attitude; x+ c& U# X/ l$ T! @. e
//俯仰角、滚转、偏航值/ B7 ~" \- v# o8 `9 C6 R. f! t
private double g_pitch = 0, g_roll = 0, g_yaw = 0;' w" w3 o- f2 X
private Camera camera;7 \1 J( n( {6 P
private List lens = new ArrayList();
/ t0 o- O+ j1 s2 x9 {6 B% m N private List djiList = new ArrayList();( ^/ J- L" n0 t8 G/ E" I0 t
//手柄控制器
2 J, z8 S5 I: l% `' h5 A7 ~/ Q private HandheldController handheldController;; \$ E% G6 F1 s
//手柄电量5 \) Y( ]- {1 r5 G) z5 I4 l0 B
private int h_power = 0;
* z" K% U6 u! m, ~3 P! q private static List list = new ArrayList();/ }2 T9 k9 H1 n0 C- I# E
private static List getList = new ArrayList();
7 P& |0 s a. h5 T# R* e/ j+ N; X private MediaManager mMediaManager;
; o! `- h( M; m0 w( H private MediaManager.FileListState currentFileListState = MediaManager.FileListState.UNKNOWN;* l; L$ |8 M' O2 C F! ^2 @
private List arrayList = new ArrayList();
6 p2 ?. {7 }6 l F) e, Q4 D2 w private List startList = new ArrayList();) p; @. a8 U3 I* z6 M j3 @) g
private List endList = new ArrayList();% `- }1 f5 A( X9 E2 |% S$ o% n
private boolean isStartLive = false;: ~% o! s! j! s: r- F' a, a
private boolean isFlying = false;
2 A0 Z6 R2 t5 p9 W! Z0 b- E+ E, U private boolean start = false;
. l7 t, H2 I2 n private BaseProduct mProduct;& H8 D8 i: E) L, G
private String posName = "";
& S% f. A! b6 W0 h8 j/ h y //webSocket
2 `* k7 E9 e/ P4 L. d$ } private JWebSocketClient client;
& ~( O+ A0 T7 R$ _% ?/ ] private Map params = new HashMap();- B1 a& {. `9 p" ]; a9 I2 n
Map mapData = new HashMap();, D) L/ \: Z/ E7 G% n6 m& [
@Override i; }; r( e7 f* w# J9 r6 t
protected void onCreate(Bundle savedInstanceState) {
8 }0 Q9 D! I2 C& `5 h: P super.onCreate(savedInstanceState);) q6 A& r- D' J* i% ?0 Y
height = ToolKit.dip2px(this, 100);9 I$ f8 U- o7 j: V2 T( f
width = ToolKit.dip2px(this, 150);
% G: n% ?3 @! t& N* p z( _ margin = ToolKit.dip2px(this, 12);8 \# M% W' w/ {
WindowManager windowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
W" V& v1 B2 Z! C4 I( _ final Display display = windowManager.getDefaultDisplay();
5 q% F, a' h' q5 u Point outPoint = new Point();
/ U7 f( D) ?+ {/ l X) n$ I) p display.getRealSize(outPoint); M6 Q, v2 l) T$ R
deviceHeight = outPoint.y;
! }3 o% G2 u+ Y- F. q8 ~ deviceWidth = outPoint.x;4 r. ?! U w+ k3 X n
parentView = (ViewGroup) findViewById(R.id.root_view);
+ n" U% ^+ s3 i: b1 {# |( D# X fpvWidget = findViewById(R.id.fpv_widget);0 U7 \# w0 Z3 ?- e
fpvWidget.setOnClickListener(new View.OnClickListener() {* {4 G `% a1 ]$ v
@Override8 v6 y: R$ J$ ?; h8 n
public void onClick(View view) {
; B% G9 [, T# Z% I onViewClick(fpvWidget);0 C$ ^4 r0 U' Y. y; @+ D- e# `
}
( u9 `- O# d/ o( ?, p });( _6 \; {( ]6 u* Y% C2 Y
primaryVideoView = (RelativeLayout) findViewById(R.id.fpv_container);
x8 M' \) D5 W; t4 v+ R( w* r6 l! y secondaryVideoView = (FrameLayout) findViewById(R.id.secondary_video_view);
% f% f9 `' I0 p0 X3 p' [5 Z secondaryFPVWidget = findViewById(R.id.secondary_fpv_widget);
* j& F" T1 S; ~! d m secondaryFPVWidget.setOnClickListener(new View.OnClickListener() {& j9 V* ^# Q& D- L& J
@Override6 h0 ]. K: j* T
public void onClick(View view) {( W' E* B9 ], a7 Q8 v* c) Y
swapVideoSource();
. O6 ~+ { {/ `& ~ }
4 { y0 d0 E; r" R' v });
7 l1 V' L" s9 d% k if (VideoFeeder.getInstance() != null) {4 o8 ^; a3 r% G* ~8 h% `! a
//If secondary video feed is already initialized, get video source
7 \' p. e o2 j, v, u9 \% r6 B updateSecondaryVideoVisibility(VideoFeeder.getInstance().getSecondaryVideoFeed().getVideoSource() != PhysicalSource.UNKNOWN);' x/ t, x& u, `( K7 T# e# L
//If secondary video feed is not yet initialized, wait for active status3 @% k; ^! f2 M4 E; X5 _! B% l
VideoFeeder.getInstance().getSecondaryVideoFeed()
+ B( X- `. y1 ?4 ^! W- q .addVideoActiveStatusListener(isActive ->5 B6 b! a1 T R( f0 p
runOnUiThread(() -> updateSecondaryVideoVisibility(isActive)));
" k d5 \' M9 H8 z; h( v* F6 { }- n( v8 ]) c0 E/ w! \
mSharedPreUtils = SharedPreUtils.getInStance(this);
. l ^ d4 F5 o+ W3 _' b! }9 } this.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
0 Z9 w1 v6 s8 M) T mapWidget = findViewById(R.id.map_widget);" i2 U# I" w. ~* d' Z% o
mapWidget.setFlightPathColor(Color.parseColor("#2fa8e7"));: q9 h% q' G- \4 a7 l0 ^/ ~; X- X
mapWidget.setFlightPathWidth(15);
5 {" v: K9 ?2 O mapWidget.setDirectionToHomeVisible(false);; N2 E$ ^9 h2 H1 f
mapWidget.initAMap(new MapWidget.OnMapReadyListener() {0 F1 E6 ~% H% `0 n4 l' u+ V
@Override" Z- a2 \% M* C
public void onMapReady(@NonNull DJIMap djiMap) {% Q6 D1 C* g3 W; A9 ~) B+ A, o3 \
djiMap.setOnMapClickListener(new DJIMap.OnMapClickListener() { w: L! @& {- V" H
@Override5 J- G& D9 Z: q
public void onMapClick(DJILatLng latLng) {
( c( I1 n; F! t& N, j$ e1 E onViewClick(mapWidget);4 W( U# a0 P6 c% C4 M, ?
}
# H) n& q, W2 _( i; a9 l });
, _& _0 s. V6 n7 R. A7 {. d' q djiMap.getUiSettings().setZoomControlsEnabled(false);
2 k$ ~8 N+ Y7 [# S: L1 B6 `& j/ j }
$ u, Z$ c1 ]& c, D });$ [2 g5 }: @& `7 k) p4 M# i- ]
if (aMap == null) {4 A3 R" {6 l% ^& t0 Y
aMap = mapWidget.getMap();
! F( _! ~0 B$ i. x# o; e }
) _4 g- W9 Q/ a% k1 x mapWidget.onCreate(savedInstanceState);
5 Q: ?$ H( ]+ O, N- M0 v' ? mProduct = ReceiverApplication.getProductInstance();
& n1 h8 N8 Y, v% ^* |) C if (null != mProduct && mProduct.isConnected()) {+ t! Q) ?( E* {9 J( r( {
flyInformation(mProduct);' d5 s; {2 m0 @1 x3 j6 }
batteryInformation(mProduct);
2 G$ W2 x! a9 j$ Y) A cameraInformation(mProduct);" g, a- T, |5 T. d
camera(mProduct);( @, `* a5 t& W& h/ I" D4 R
}) Z$ q0 N( N5 |- ]- m6 a
Timer timer = new Timer();4 t6 {7 L' C4 {! r- c+ q& W
timer.schedule(new TimerTask() {
. H; b, r- W4 v, M9 s3 { @Override# V. c; a' {7 y$ L( A k: {
public void run() {
: t( h7 T6 }( t4 G" m+ o Message msg = new Message();+ r$ D& f7 d9 V5 I# u* m+ A: S
if (isFlying && !start) {1 a& `& q' E1 y3 s7 P7 _% a; s
start = true;
& d- H6 L6 c/ B- m0 H/ l
! C8 D3 ]& B `9 Q 5 c6 L& a. [9 g& W
}6 }; ?: o% c6 k: b
if (!isFlying && start) {# \9 ?7 F* `! {
start = false;6 m- S1 V \( W6 h/ a- {# b
! J! c. x# n5 e; `; [! t
}
0 ?( Y2 @5 P% q) |/ J/ d9 \4 ^ if (isFlying && high >= 0) {0 b8 l! | U8 c# F1 H
msg.what = 1;! h$ ^6 `1 P5 Y# J! O
}7 \4 m( Q/ F; }$ j, S5 I, e+ n
mHandler.sendMessage(msg); [! Z' R# ?! o, n: S# @
}
9 n7 S7 e G9 [. C6 \- h }, 200, 200);3 ?' _' s v3 I7 K) I" r/ G
}, A( v, D1 S X0 f: p4 d+ s
Handler mHandler = new Handler() {
. P" O+ U, ]& Q1 |3 E @RequiresApi(api = Build.VERSION_CODES.O)4 H6 e( F. H* F. A; d2 j
@Override
( ]$ Y' r" J" h9 S8 i/ [ public void handleMessage(@NonNull Message msg) {7 e' Y( @% B( }$ j* Y
switch (msg.what) {8 y) k8 l0 V/ [0 E- M5 s2 l
case 1:
& m8 p! R' i; K Long time = System.currentTimeMillis();
! w' n5 @6 O7 B, v// MyLog.d("时间:"+time);. v/ v; h- @8 d+ L4 A
RecordModule module = new RecordModule(String.valueOf(projectId), String.valueOf(planeId),' G2 b0 {& I3 b, B
trajectoryId, time, String.valueOf(lon), String.valueOf(lat),. a# x. C3 [& M9 N1 w
String.valueOf(high), String.valueOf(yaw), String.valueOf(pitch), String.valueOf(roll),
2 s4 E+ X# `1 y0 n; e( v String.valueOf(""), String.valueOf(velocity_X), String.valueOf(velocity_Y),3 o, i, B* G; J# l5 s. ~. `% I
String.valueOf(velocity_Z), String.valueOf(g_yaw), String.valueOf(g_roll), String.valueOf(g_pitch));
( t0 Q/ g: N9 F% R2 Z http.getHttp(INSERT_DATA, GsonUtil.GsonString(module));+ F- i' `; W# z# p) v% ~2 q: z
break;
% R! {- G6 n3 P4 K9 ?7 R& D case 2:
' Q5 I+ S! I" P: { M! J* M. _ MyLog.d("飞机移动的数据:"+msg.obj.toString());$ F) ~- J6 [& [: T, W) `( f
ControlModule control = GsonUtil.GsonToBean(msg.obj.toString(),ControlModule.class);
, Y( o4 K4 o5 Y if (controller!=null&&isFlying){
5 e% ~, d( W0 _ if (control.getContent().isBack()){
6 E f. m! a+ `" L/ ` controller.sendVirtualStickFlightControlData(new FlightControlData(-10,0,0,0),null);
5 A% i) I8 h( Q/ O }
7 v% H* X. w. o6 ]- A4 `$ _ if (control.getContent().isFront()){6 u! \5 s2 Y- _' V$ l& d' P
controller.sendVirtualStickFlightControlData(new FlightControlData(10,0,0,0),null);2 F7 Z2 ~+ u" q, p1 g4 Z2 J
}
! t$ W; P2 G% R \, {$ i, p- z if (control.getContent().isDown()){/ v" e! r% m9 I5 c, H
controller.sendVirtualStickFlightControlData(new FlightControlData(0,0,0,-4),null);
6 s) x: Y2 ]" s2 N }$ ^9 ~: A) o0 z3 D8 P, r; a J+ D
if (control.getContent().isUp()){, N% V p2 W. T+ K! Y
controller.sendVirtualStickFlightControlData(new FlightControlData(0,0,0,4),null);7 K1 {3 J7 l' H' K3 |% f- Q
}
6 O: f* E! I6 a9 i& L6 x1 [8 r if (control.getContent().isLeft()){3 {* ?$ ^: Z1 d9 ^& ~) K" x: K
controller.sendVirtualStickFlightControlData(new FlightControlData(0,-10,0,0),null);
; W) n. K8 [( ]9 M- E }- R' Z; `: w H2 B9 z2 b1 O5 Z- g+ `
if (control.getContent().isRight()){" u6 J# p! H. t f# f; _+ h. ]
controller.sendVirtualStickFlightControlData(new FlightControlData(0,10,0,0),null);
5 | j, q& }$ R: h$ s& J. i }/ |/ G0 _5 ^& i, F# J' s
}else {; h5 k3 `0 g" O; z
MyLog.d("controller控制器为空");
9 z5 X/ s) U0 B$ ^ }
, L0 H/ ^8 l# s! y2 R break;, S/ j. P5 J+ m4 M
}9 t+ Y$ l+ X2 `) |- j0 Z2 N: Q
}
0 K$ z- b; a, X1 t( [ };
0 Y4 g2 `( l2 z' I @Override# k: U3 B5 c+ ~5 o' p) o& ~
public void initViews() {
& c8 f$ U, C6 _' Q mMediaManager = ReceiverApplication.getCameraInstance().getMediaManager();) }) L* l! E4 M: y1 I* ?
getFileList("start");
' M, o7 Q3 H* e) ^( R+ U+ p/ F }8 I9 j6 ~8 m$ D6 [9 y9 `
@Override
: \% n* T4 q& ^( v! |; ~ W3 p public void onComplete(String url, String jsonStr) {" O, q) r+ Y0 T' T& @
super.onComplete(url, jsonStr);+ A0 e A+ W2 M8 e" s, j: @
_% E! J; x+ }) _ n; Q }) l4 j( ~) H- P/ |1 V, p6 c
@Override& o0 L: l* t- ]3 Q, n* d; g- s% Z
public void initDatas() {
7 p4 s T2 M* |: h3 q; w; d* C }
. f7 y @' W1 {2 x" Q W private void onViewClick(View view) {) ]3 q1 y! t. z; N
if (view == fpvWidget && !isMapMini) {0 [' [& v8 t, G4 i, u
resizeFPVWidget(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT, 0, 0);+ ?) \2 s0 f' k
reorderCameraCapturePanel();' V" K' y% X. }& T v0 U3 M U7 x- L
ResizeAnimation mapViewAnimation = new ResizeAnimation(mapWidget, deviceWidth, deviceHeight, width, height, margin);
5 Q M' k2 \: W! t mapWidget.startAnimation(mapViewAnimation);5 K U/ z3 K/ Q
isMapMini = true;( P% o u! {2 V2 E$ K5 A2 `) p
} else if (view == mapWidget && isMapMini) {
2 b" B! w3 ?- e2 R! W y- w" X hidePanels();
$ W; M# N2 w W2 P6 A6 } resizeFPVWidget(width, height, margin, 12);
/ G4 K E& q) c3 B! h0 G6 R: {! K reorderCameraCapturePanel();% [/ e, m# x0 n; V {
ResizeAnimation mapViewAnimation = new ResizeAnimation(mapWidget, width, height, deviceWidth, deviceHeight, 0);- y1 `* l; q* `, b
mapWidget.startAnimation(mapViewAnimation);
$ ]% y$ j/ E5 u; A isMapMini = false;! U0 w+ [7 L9 w# G! R
}
6 a0 g! i5 t" M3 S$ ^1 D) V' q$ f }' [9 a! x0 y: g1 H
private void resizeFPVWidget(int width, int height, int margin, int fpvInsertPosition) {( i3 n8 O9 c5 c9 D) d6 }9 m) D
RelativeLayout.LayoutParams fpvParams = (RelativeLayout.LayoutParams) primaryVideoView.getLayoutParams();
* ?+ q0 B6 B o1 r fpvParams.height = height;
$ ^' M' d: u+ T! c& G! s5 P fpvParams.width = width;
7 V6 N* j9 ^7 \+ X3 g fpvParams.rightMargin = margin;! V$ l9 J; j. Y1 i
fpvParams.bottomMargin = margin;
6 W$ p( h+ z3 f g, {! I- G. G8 O if (isMapMini) {# B6 S/ ` T/ R2 a
fpvParams.addRule(RelativeLayout.CENTER_IN_PARENT, 0);
( }( d* b& P8 p3 Z# z. a! y* d9 Q fpvParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT, RelativeLayout.TRUE);' K( [+ r6 t# Y5 _: m# `1 `4 ]( p1 I
fpvParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, RelativeLayout.TRUE);
( `! @! G- ^1 H6 \" C. W } else {( b, O0 a1 B) W0 _# J/ a3 F( L! y4 `
fpvParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT, 0);
' v: B/ Y3 _+ w2 |2 S5 a1 P fpvParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, 0);( ^" e. ]1 }; A; {
fpvParams.addRule(RelativeLayout.CENTER_IN_PARENT, RelativeLayout.TRUE);" e4 e# H1 B( [7 t1 @
} {$ u; x T' Q! R2 m: h& D- m
primaryVideoView.setLayoutParams(fpvParams);$ F$ f- ^2 m+ `0 Y/ s& S0 }
parentView.removeView(primaryVideoView);! L( @% i+ l1 l+ Q
parentView.addView(primaryVideoView, fpvInsertPosition);7 y1 A2 X: j9 t4 ~0 o, Y& V
}
0 l- e. b. l0 `- d' q private void reorderCameraCapturePanel() {
6 r& S% W! y' I5 `' C q0 B( { View cameraCapturePanel = findViewById(R.id.CameraCapturePanel);
& R( b! [5 B) n' [6 c parentView.removeView(cameraCapturePanel);
9 z8 B5 }( f* V( L% R* ~ parentView.addView(cameraCapturePanel, isMapMini ? 9 : 13);% D" h7 D, [( {+ m& Q5 i: H0 _( n$ M' _ m
}
, v; m* j/ [! V3 T0 }, P private void swapVideoSource() {
- G/ t+ q- M; h* M! y! s8 I if (secondaryFPVWidget.getVideoSource() == FPVWidget.VideoSource.SECONDARY) {+ V+ }/ n$ o ?3 O1 d4 C
fpvWidget.setVideoSource(FPVWidget.VideoSource.SECONDARY);; _2 R" `7 Q3 x+ k0 e0 {
secondaryFPVWidget.setVideoSource(FPVWidget.VideoSource.PRIMARY);
/ x. d; f0 c' ?! v; ?8 o } else {9 L! E1 u0 r( H/ R# n# W& v% P
fpvWidget.setVideoSource(FPVWidget.VideoSource.PRIMARY); d' r, [$ j% X! F+ R
secondaryFPVWidget.setVideoSource(FPVWidget.VideoSource.SECONDARY);* v' b* ]; O3 V& S: P2 `
}
' s( F& j8 l# @0 g5 j% ? }0 }* o4 H P$ o, J" M0 I6 i4 C& b
private void updateSecondaryVideoVisibility(boolean isActive) {
5 z j4 N- B6 v8 K- V+ g if (isActive) {
: x7 R1 p7 \# e6 d secondaryVideoView.setVisibility(View.VISIBLE);/ S W* p( _& R k4 a- a" z
} else {7 k& ~$ Z/ y+ Z2 }
secondaryVideoView.setVisibility(View.GONE);
L9 W! c) b1 B+ f/ I }3 K2 j# f# L1 w) }# x8 U' K' L* l
}
* P b$ f! f' ^ }* D; w private void hidePanels() {
3 K! k! t$ u; ^( {- m% @% E# Q$ Q K //These panels appear based on keys from the drone itself.
6 u- c: i5 I/ @/ i, y; ? if (KeyManager.getInstance() != null) {# f; N; y9 h# N: R9 q4 [; Q
KeyManager.getInstance().setValue(CameraKey.create(CameraKey.HISTOGRAM_ENABLED), false, null);
/ Y. {$ k8 O0 x KeyManager.getInstance().setValue(CameraKey.create(CameraKey.COLOR_WAVEFORM_ENABLED), false, null);
3 E5 o3 N8 X% a9 f5 y1 V6 x' \' b+ i }
0 r# p/ e x' I8 o //These panels have buttons that toggle them, so call the methods to make sure the button state is correct.
0 x+ T! n& N* Y, F4 p CameraControlsWidget controlsWidget = findViewById(R.id.CameraCapturePanel);2 d$ u, x. u S' _3 a! N0 K, q! W
controlsWidget.setAdvancedPanelVisibility(false);7 `* C O) ]9 V- v5 v& N, x: O4 g4 P
controlsWidget.setExposurePanelVisibility(false);( b" Z0 f' u* o* R; v" U8 w
//These panels don't have a button state, so we can just hide them.
. h1 T+ h3 E8 C5 }2 [ findViewById(R.id.pre_flight_check_list).setVisibility(View.GONE);% h2 k* q3 X n1 y6 u t# d
findViewById(R.id.rtk_panel).setVisibility(View.GONE);
' n% r5 g* I" F/ A# O! q findViewById(R.id.spotlight_panel).setVisibility(View.GONE);
6 D$ F3 Q' `) @, @, ~, G% @6 d# d- r findViewById(R.id.speaker_panel).setVisibility(View.GONE);
: O" V! Z1 ?5 b5 K }. ^6 c) z3 P) a0 N# ?/ {
@Override* h" i2 V* I3 I+ J7 ~
protected void onResume() {
/ O/ j# F/ l4 o7 }9 T8 `& b3 Q A super.onResume();% C" N% w( ^% r
// Hide both the navigation bar and the status bar. S e! w1 y& \# P3 R
View decorView = getWindow().getDecorView();
. Z. L: o# i, U2 T decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE# W3 r' c$ @ R3 c1 P% b
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION" A+ O3 k- s/ H4 K; l, k8 ~
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN" `& V/ E/ j: I% _" q
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION, c3 x% b6 [# c8 p7 c# R
| View.SYSTEM_UI_FLAG_FULLSCREEN
4 a: x' R* c/ d$ P/ _ | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
! I/ C9 O) D; t6 A% F3 y mapWidget.onResume();' k, W+ F* }2 Q+ a: ~8 P
if (client == null) {( |1 |, g3 o2 @% W
MyLog.e("``````````````````````onResume");2 B+ U) r% [* t, @
// initWebSocket();
! B* {! T/ Y, ?) c% o! d- A' g } else if (!client.isOpen()) {
3 _+ S& A& z6 b' d; J reconnectWs();//进入页面发现断开开启重连: N$ V( r* t) f& ?2 q8 ~
}: i- I5 ~% `1 x7 f
}) L) X+ f( E1 p1 |: C
@Override9 D7 K5 M$ `" J0 |: r/ j1 H
protected void onStop() {
" A$ h" j4 h5 |3 H) ?. t super.onStop();
& m4 m% P. Z+ O- [$ h MyLog.e("``````````````````````````````onStop");6 U8 P1 j, j0 _" l) R& V
}
3 E, C* e$ y$ x5 Z0 r1 F4 g @Override
$ b7 u- p9 @, B; h protected void onPause() {
2 l% p) Y0 i7 O7 `/ U8 ~' r mapWidget.onPause();. o* w. X6 s/ X' y
super.onPause();' n* G" B* T% R) H7 V$ ~
}+ _& e& {. {; F+ B
@Override6 ~, T+ ~. j1 u6 y: ?6 M+ B2 I
protected void onDestroy() {
2 N# C4 ]$ _' E: M; ] mapWidget.onDestroy();
- s) B" K" t; }+ X2 w9 [) H super.onDestroy();
J3 \& p7 P# s* m" I MyLog.e( "`````````````````````````onDestroy");
0 }; f( C) B9 \) T3 t: Y closeConnect();
: i, F \9 U! B- q }9 L# X1 j9 ^0 b5 B
@Override! s4 M" g! x$ b1 I9 `. h& F! @- q+ w
protected void requestData() {
0 P) d2 ?- e* \6 C% _) D" S* R1 { }8 G; Z8 T1 q" h( q) T
@Override* }; t$ G6 D) [& t# z7 R" ~5 i4 K
protected void onSaveInstanceState(Bundle outState) {0 y# h; T, K9 C+ W) e
super.onSaveInstanceState(outState);
0 Y5 w4 p3 p: x mapWidget.onSaveInstanceState(outState);
; k1 l7 y3 l, Q1 S1 d8 @7 R x }/ w% o$ g7 K s. b2 P- G& P& {/ l' j
@Override& _+ }" K- D! o
public void onLowMemory() {* Q% \+ I: _- m& I, N; W3 M1 n
super.onLowMemory();
2 x9 v! a* r; o mapWidget.onLowMemory();
0 A a) v2 b0 v4 }5 N1 ?% n }
5 N" Y* L, N r2 m2 C$ M private class ResizeAnimation extends Animation {
3 \4 S2 a; ^) p% j9 Y private View mView;
8 X! x. K, M+ \- J9 L4 d private int mToHeight;2 ]- C7 t7 q% |; J: x N6 T
private int mFromHeight;
( z; ^& C0 O k2 J private int mToWidth;- y! g0 _; y( ~$ b
private int mFromWidth; g) v# Q. G: ~
private int mMargin;
' ^$ k7 L3 k4 ~ |0 v! R8 [ private ResizeAnimation(View v, int fromWidth, int fromHeight, int toWidth, int toHeight, int margin) {
- W( u* b+ t2 u1 `/ n mToHeight = toHeight;
5 v' V) X7 W3 L mToWidth = toWidth; `* ~2 ]3 g% V0 O! q( A
mFromHeight = fromHeight;
9 H/ V8 h7 U# z- I mFromWidth = fromWidth;5 ]' N7 F. Y) }* }' y3 n
mView = v;
/ j7 P/ r! _- H0 J mMargin = margin;. _8 y/ Y+ E& `, w* F
setDuration(300);; w+ ]7 ?2 P9 | Q5 b
}
' V0 R6 t$ h% ?/ a2 F1 m; `2 V9 e @Override7 V( q. w& u( S5 D
protected void applyTransformation(float interpolatedTime, Transformation t) {/ o/ y# x. G3 E! c0 N6 k+ E
float height = (mToHeight - mFromHeight) * interpolatedTime + mFromHeight;
3 b- C% ^) j; {. Z& L float width = (mToWidth - mFromWidth) * interpolatedTime + mFromWidth;
2 @: J- W0 s2 y. j1 ]# h9 c RelativeLayout.LayoutParams p = (RelativeLayout.LayoutParams) mView.getLayoutParams();0 ^+ c3 K+ O- y5 l' s G$ _8 E+ {, \
p.height = (int) height;4 h) W; \9 u6 k7 V
p.width = (int) width;
[+ g% R& |% o: l p.rightMargin = mMargin;( u4 _' c' k/ w; [. Y% @% s, b P
p.bottomMargin = mMargin;" t V9 c1 t. h9 Y
mView.requestLayout();
- T/ M# z# u5 S/ L2 o* n; u }. D: J: I1 {* F% K' {: C
}
& q- x$ Q8 l Q5 d2 M( B' S1 s7 v8 G- y" l
//直播流推送- O4 e: t: _. \% E# u% p
@RequiresApi(api = Build.VERSION_CODES.O)
! W6 }! q( Z* y9 N _; A& h \. B5 M* U @OnClick({R.id.img_live, R.id.img_show_back})& c% I7 s: v; I( H0 Q1 }; C6 L" @$ @
@Override1 p% D3 I; V( x; B5 W
public void onClick(View v) {% W z, ?1 C, b! W
switch (v.getId()) {/ q* z0 f! {0 q9 T' Y
case R.id.img_live:
1 I% R3 }" N! F0 ~' f6 Q. H% e params.clear();
! L4 R5 U6 g7 x) \- b9 ~! o. u mapData.clear();
, u2 r; @4 G9 r if (!isStartLive) {: Y* C; W' W" w8 A$ j' Q2 G7 i! ^
if (!TextUtils.isEmpty(mSharedPreUtils.getStringSharePre("rtmp_url"))) {
8 r% T; b- m, s/ H" R0 s liveShowUrl = mSharedPreUtils.getStringSharePre("rtmp_url") + trajectoryId;
# o0 e' N; M0 z) d// LiveModule module = new LiveModule("liveStreamStateChanged","plane",planeId,true,trajectoryId+"");1 Z5 B8 q$ r$ c6 R2 b
MyLog.d("地址:"+liveShowUrl);
: ?( Z7 y, R. c startLiveShow();) @6 T7 U) S2 r; h; `: \4 Z6 O( \
isStartLive = true;7 j" d1 K0 i# ^8 |) u5 m6 I& n
showToast("开始推流");$ ]3 R4 r& t( x4 x3 ^
} else {
4 N6 o% a3 }' e0 O, g5 d% | showToast("请先进行系统设置(RTMP)。");1 L! s7 M9 o: M0 H o
}
; r; M% S0 J; u: J/ A$ j7 w } else {
2 @# A, s D6 u9 r/ m4 K stopLiveShow();3 R* t4 m& Q& z1 V# m/ l) h) _
isStartLive = false;
) Z! p. q% ? R) S4 b2 }/ P$ x; { }
1 Q3 `- z. O0 m7 B% O3 n' L0 \ break;
$ ^0 P6 G# M$ z/ }! I, B case R.id.img_show_back:; e! M- ~' {' K3 a1 m. w' D5 o
// controller = null;
2 j" K3 U: Q5 G; J# M# j# l closeConnect();) P @' F# l' z9 E, G
MainActivity.this.finish();
" k' @/ f, P5 a break;# {# j$ j {0 E0 `) b6 {7 x q
}0 W2 s: H: f0 |3 g! U
}
9 a/ T& U8 R* c5 h private boolean isLiveStreamManagerOn() {# d, k5 N [# W% }1 F: R
if (DJISDKManager.getInstance().getLiveStreamManager() == null) {7 {7 w6 {3 C7 |# S) Y
return false;
( f1 h4 `; S; M7 L2 }" m }
6 C3 ]) a. F8 r# M5 E. m return true;; v# L; ?0 J' m! \; L+ K
}% T; O+ m* v4 C
private void startLiveShow() {* Q; m% [( y8 F5 p) H
if (!isLiveStreamManagerOn()) {$ T0 W9 a' W, l. s0 X
return;' ?6 b0 I* ?. r0 C" k
}
; C- {0 G2 h( v; I: D if (DJISDKManager.getInstance().getLiveStreamManager().isStreaming()) {& f7 ]3 F) g9 \) V
return;+ l0 P" g {4 O$ f
}' ]1 \! B: u+ R: n! ~/ g) ?
new Thread() {' N* n6 O: L& ?2 A1 K+ p
@Override
0 l2 F3 l/ K! `; I6 r+ U public void run() {
: o8 v$ W# A8 V$ ]5 W DJISDKManager.getInstance().getLiveStreamManager().setLiveUrl(liveShowUrl);9 L& D! S- ?( \. y2 F' `( D
DJISDKManager.getInstance().getLiveStreamManager().setAudioStreamingEnabled(true);
* D! I5 ^" ]4 X+ Z" l# }, y int result = DJISDKManager.getInstance().getLiveStreamManager().startStream();1 n! ?" M% p, H. J; o% ~+ G
DJISDKManager.getInstance().getLiveStreamManager().setStartTime();; d5 x0 Y2 a8 ^6 s
}
! y; _1 E* [) \ j1 v4 Z; ? }.start();
6 g* V# t+ l& K" {) K8 f4 S% h7 W. O# o }
( z2 N, w) T) r! s private void stopLiveShow() {
2 O9 e" J8 z$ _, S" `$ |; _; m AlertDialog.Builder Builder = new AlertDialog.Builder(MainActivity.this);- j# w$ S7 H3 d5 |0 T; h
Builder.setTitle("提示"); ~; X( }* a/ @7 Y, g% p
Builder.setMessage("是否结束推流?");; {0 @$ ?! I- k [+ z
Builder.setIcon(android.R.drawable.ic_dialog_alert);
* N6 x! G& O2 \& C0 O# K Builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {
; Y$ T% m, h* z$ `/ r4 G: |4 [ @Override
' g0 t& M' J; q public void onClick(DialogInterface dialog, int which) {
7 O% f; T( P1 b% X0 f if (!isLiveStreamManagerOn()) {7 A5 N0 q9 v6 f
return;
5 Y2 ^. r$ F; ~1 M! w" P. e }9 b9 E8 C2 \9 z. V9 G3 V$ [4 t5 t
DJISDKManager.getInstance().getLiveStreamManager().stopStream();
- ^/ e8 I2 B- J1 p showToast("结束推流");( N" z7 K0 a' ^4 S' ]
}6 W1 r8 S# T, n: w6 B, P( G( d
});* H5 {- `3 l4 X7 g! N
Builder.setNegativeButton("取消", null);$ q( {9 @* w7 a4 c1 o% l, l8 c a
Builder.show();, ~- y9 m) s, l0 E6 \- G* U
}7 H! [( w5 n# v" `) C0 s
- t0 E- b% {; e- Q. P //获取飞机信息、云台信息
* K9 m9 g1 \: h2 y* @4 ]% R/ P protected BroadcastReceiver mReceiver = new BroadcastReceiver() {
& B! L1 Q/ e# x+ X6 h @Override
1 u& O$ E) B2 Y public void onReceive(Context context, Intent intent) {
+ r4 @1 b6 k d/ z u- g BaseProduct mProduct = ReceiverApplication.getProductInstance();
6 ^3 `) `: s6 W( H if (null != mProduct && mProduct.isConnected()) {9 g! H8 k) D% A# w# H! ^! B
flyInformation(mProduct);
9 Y: M) \( R) v$ H6 z3 k- d* \8 g' E batteryInformation(mProduct);: l8 R( {" t a& z2 G
cameraInformation(mProduct);
; B7 [7 Z0 s" h# M* ~ camera(mProduct);. b" Y; u8 j5 N, M
// MobileRemote(mProduct);
" U$ r, m- j/ C" ~' G' x7 ]# l# O }/ F8 f Y8 B* h7 _
}
* {8 C2 q" O8 e3 K- ] };
2 e/ ~ a0 D% @; c; K. Q( h) X( ^1 V// private void MobileRemote(BaseProduct mProduct) {$ O3 A) M6 Q1 u, k( \
// if (null != mProduct && mProduct.isConnected()) {
/ c9 W) h/ l% n* z8 E7 n// mobileController = ((Aircraft) mProduct).getMobileRemoteController();4 x& i7 X6 j* w4 f
// }
8 n5 G. w; D7 K, W' E# W$ Y% |// }/ s1 i# c" v( s" J+ v
//获取飞机信息6 Q! U3 H' |5 [
private void flyInformation(BaseProduct mProduct) {" n' e3 t& g4 T0 M# t
if (null != mProduct && mProduct.isConnected()) {3 o0 {/ x& H* j/ g
controller = ((Aircraft) mProduct).getFlightController();
! D9 h4 W+ q: G7 J }
# |2 h) s1 y' X6 c+ v2 [ if (controller != null) {
2 Y) F9 s1 `. `1 X! ` controller.setStateCallback(new FlightControllerState.Callback() {
1 O/ ]: S$ }* o7 E$ r @RequiresApi(api = Build.VERSION_CODES.O)- T+ f; Q* y0 [! ^ |) I
@Override
) B( w5 f( `- K public void onUpdate(@NonNull FlightControllerState flightControllerState) {
) j/ n) q' {. _. u8 c- S //纬度、经度、高度、俯仰角、滚转、偏航值、速度 n- n% ~! o) T% R5 m$ }
lat = flightControllerState.getAircraftLocation().getLatitude();5 c6 h! K, n' b5 r5 g7 u0 W
lon = flightControllerState.getAircraftLocation().getLongitude();
1 q) N. h4 I9 n8 `) j& U+ D high = flightControllerState.getAircraftLocation().getAltitude();( J+ l1 ]% g7 C
attitude = flightControllerState.getAttitude();2 Y* k. A1 f# v: `$ E( I4 {% N
pitch = attitude.pitch; k- }. S* g r- F+ k2 @3 r" I0 v
roll = attitude.roll;$ ~* u( w0 q" {. H3 b4 X! [
yaw = attitude.yaw;
# F- ]6 z ]$ L7 f9 g5 A velocity_X = flightControllerState.getVelocityX();
1 D! E. R0 V. j+ h7 g& I velocity_Y = flightControllerState.getVelocityY();$ h1 K* O- r+ c2 U; H9 M, e, D+ g/ r
velocity_Z = flightControllerState.getVelocityZ();3 q6 b% W# L' Q
isFlying = flightControllerState.isFlying();& M' U7 s! L$ p: l( \6 ^
// MyLog.d("经度:" + lat + ",纬度:" + lon + ",高度:" + high + ",角度:" + pitch + ",速度:" + velocity_X + "," + velocity_Y + "," + velocity_Z);7 R/ `( F4 L% t/ K5 ^3 j
}
! J& e% e/ h8 v/ ?5 l/ D; R; i( o });2 b$ y3 w5 B+ E8 l; n/ |! I4 `% D0 Y [
controller.setVirtualStickAdvancedModeEnabled(true);
+ C0 h# M8 G$ h controller.setRollPitchCoordinateSystem(FlightCoordinateSystem.BODY);
+ [& N4 e3 T7 r controller.setVerticalControlMode(VerticalControlMode.VELOCITY);) k% d: @& i. i) e
controller.setRollPitchControlMode(RollPitchControlMode.VELOCITY);
' t* [: g0 [, g M" `: i+ m) M# R# X controller.setYawControlMode(YawControlMode.ANGULAR_VELOCITY);, T" J1 b% _* _, x$ n; |! e' f$ k) D- y
// controller.setTerrainFollowModeEnabled(false, new CommonCallbacks.CompletionCallback() {4 a; l, x' ?! \4 t$ u/ l$ E! Q3 x
// @Override
! y8 l5 [9 W- n% F// public void onResult(DJIError djiError) {
- C( O8 ~6 U6 o* o3 a, r& _0 @( F// MyLog.d(djiError.getDescription());
& S- m4 r" F- d5 N// }9 a. U) m6 Z3 Z6 Q9 D
// });- S( z y) h R- b& m$ X
// controller.setTripodModeEnabled(false, new CommonCallbacks.CompletionCallback() {$ ~" W1 z# \/ [6 q+ C0 R" V# o
// @Override, P: t3 \( a5 f8 o
// public void onResult(DJIError djiError) {
& I, B! K' t E$ W! h7 H// MyLog.d(djiError.getDescription());
6 i& W6 @! I2 @% b+ r" F: P1 i// }
" M& w& [+ s% J7 V3 ~: _- x// });
: i1 ~8 \: J9 ?// controller.setFlightOrientationMode(FlightOrientationMode.AIRCRAFT_HEADING, new CommonCallbacks.CompletionCallback() {
2 x- E( P6 X" _3 B( n. ?// @Override
5 Y2 D# Z% o' `8 U, h8 \// public void onResult(DJIError djiError) {; o, _' e j& ?( C" W* Q/ z }% G
// MyLog.d(djiError.getDescription());
3 n# P1 f. x5 |3 X7 x! D" R// if (djiError==null){
0 M! Y( _6 P$ N// if (controller.isVirtualStickControlModeAvailable()){
O) @" M( v2 v* [0 c. K//
. k# d3 H* D6 A$ a# H1 S// }else {
" s" ]3 O# p c+ R/ ?. Q- F9 |8 k% h// MyLog.d("虚拟摇杆模式不可用");" _- d6 w; O6 ?. N' A9 K
// }
) h) ~ _ L& c9 w// }
2 I- `. W: O- j5 ?- J// }
x+ \( S/ Z) ^, J' \8 S// });
' U& F: f- ], C# J: R1 H }
4 D1 U5 D& z2 ]+ e0 ` }# I$ N3 Q# Q4 x/ |/ Q
//电池信息
4 U2 t- {: m2 Z# @+ T% j private void batteryInformation(BaseProduct mProduct) {
& S! k9 c8 C+ B2 u9 a if (null != mProduct && mProduct.isConnected()) {
7 C1 f9 m5 G- S2 i# m5 x: l: p battery = ((Aircraft) mProduct).getBattery();
+ t5 s- I+ v/ j, P' g }3 w% G; h# A! P/ s# D" o L# _- `
if (battery != null) {
/ J6 O4 V8 n/ N3 T+ F battery.setStateCallback(new BatteryState.Callback() {- y* q8 } ]2 X7 O6 I" F
@Override
* D/ {( w- g: w/ J9 n3 u$ a; Y* G public void onUpdate(BatteryState batteryState) {9 y+ Z* R5 H. j2 X9 ^9 D$ {2 v
//电池电量
& L8 _4 R" `' q, H K; Z3 V! q power = batteryState.getChargeRemainingInPercent();
! }+ f @& O& U //电池温度
+ N+ b. D* Y6 ~8 c temperature = batteryState.getTemperature();
9 r9 K: w! I1 a# J3 X* X* e }1 g$ E4 {" D& y l+ V
});
3 n7 E+ T1 h4 X1 g7 S }% @7 y1 C4 C% v* _# D9 ^* x+ O! M! i
}! Q) P( b, j8 O
//云台信息$ [3 B J# @' U0 y+ ~5 A) d3 i6 ?9 ^
private void cameraInformation(BaseProduct mProduct) {, A# i& _0 S' a# R, Y2 h- A
if (null != mProduct && mProduct.isConnected()) {' u0 S. k6 y# A% u2 X+ j- p
gimbal = ((Aircraft) mProduct).getGimbal();9 V8 @( Q5 {$ Y2 }9 \
}
' L7 Y" r/ W8 B if (gimbal != null) {
* I' H4 l( i, n! @2 x gimbal.setMode(GimbalMode.YAW_FOLLOW, null);2 t2 P9 J" G- Q
gimbal.setStateCallback(new GimbalState.Callback() {+ r& w7 O9 q$ P8 i* V) N: {
@Override$ h; q# ~' I4 {- t
public void onUpdate(@NonNull GimbalState gimbalState) {" W" a/ J* B, L
//俯仰角、滚转、偏航值6 [% u# @( ]" w0 \% ~1 S) P3 z+ f
g_attitude = gimbalState.getAttitudeInDegrees();
6 @* A' `" s$ P+ h g_pitch = g_attitude.getPitch();0 q& Z. ^2 J$ a1 x/ I6 V
g_roll = g_attitude.getRoll();
9 z' ~1 u9 }) X. I5 w0 {! e2 A/ ] g_yaw = g_attitude.getYaw();
+ [1 a; J8 d/ P6 F' L' v }( T9 q% G" a4 ]
});
0 K, N& @: P5 L" F }+ U& P2 i; P' a) m# E3 V
}
1 w+ }: }1 a7 w+ d private void camera(BaseProduct mProduct) {8 ~- o7 B7 b8 D1 v; y0 {
if (null != mProduct && mProduct.isConnected()) {
7 J8 G8 e! @0 H# w camera = ((Aircraft) mProduct).getCamera();& o! ~- Q. a/ `3 h; J1 g: {* x$ m
}
& a; s* m) J- n Y- S' u if (camera != null) {4 Y2 t/ y L4 d( V6 t
// camera.setVideoCaptionEnabled(true, new CommonCallbacks.CompletionCallback() {. R5 Y7 ^( \8 U4 u, M, u- F( S
// @Override
9 [. j) I. H( |( Y7 L( \ // public void onResult(DJIError djiError) {
0 [' z; `- ~/ m // MyLog.d("VideoCaptionEnabled"+djiError.toString());* ?) `' u& H# h T3 E
// }/ j% f+ f* W' C" z ?
// });0 d6 ^) M" G- J/ R7 Y2 ^
// camera.setMediaFileCustomInformation(projectId +","+trajectoryId, new CommonCallbacks.CompletionCallback() {
9 s% `+ @% Q* i9 ?' n6 ?8 L // @Override; A& Y1 M* i/ m9 j" {- K
// public void onResult(DJIError djiError) {- P1 {- c0 \) p, R c4 U
// MyLog.d("自定义信息:"+djiError.toString());) e3 {3 N- w4 Y
// }3 a& t. D6 K' z6 w$ v1 y0 @, O
// });
% a, G4 P6 k9 _0 a. M camera.setSystemStateCallback(new SystemState.Callback() {" K# O: v5 i0 {' T* k" w
@RequiresApi(api = Build.VERSION_CODES.O)
5 H6 R' Z4 B( e& G# A @Override
. [2 Y' i# k' d9 \ public void onUpdate(@NonNull SystemState systemState) {1 a# W H# I1 ^% K' I
if (systemState.getMode().equals(SettingsDefinitions.CameraMode.SHOOT_PHOTO)) {
1 f& I! n. C& b+ N8 ` if (systemState.isStoringPhoto()) {( _+ }( o7 m G7 Q2 r
dateStr = Long.toString(System.currentTimeMillis());
) L* m, q, I# F0 V list.add(new DeviceInfo(dateStr, lat, lon, high, pitch, roll, yaw, velocity_X, velocity_Y, velocity_Z, g_yaw, g_roll, g_pitch));, V* W! l* [$ a' D3 c2 n8 v! ]
CsvWriter.getInstance(",", "UTF-8").writeDataToFile(list, FileUtil.checkDirPath(FLY_FILE_PATH + "/照片数据") + "/" + DateUtils.getCurrentDates() + ".csv");2 H7 G2 c: ~3 Y/ l) {
list.clear();$ W) G: i5 P1 U8 i1 y
return;
8 u! s8 P! z* z# ]( p }
' T' r* N0 W/ {: N- ~2 i# r5 S } else if (systemState.getMode().equals(SettingsDefinitions.CameraMode.RECORD_VIDEO)) {$ |& _$ c% ?, x( k/ }# |! r
if (systemState.isRecording()) {* R/ o5 Z5 v$ u$ a/ S
try { t5 u9 |! k1 ]
dateStr = Long.toString(System.currentTimeMillis());( u9 g9 @+ l, p$ Z" P
list.add(new DeviceInfo(dateStr, lat, lon, high, pitch, roll, yaw, velocity_X, velocity_Y, velocity_Z, g_yaw, g_roll, g_pitch));5 T3 G$ d( N$ Q8 q
getList.add(dateStr);" [4 F( _+ r. C) y) x( M
Thread.sleep(100);
8 C. m5 c6 c% _( l! F } catch (InterruptedException e) {
7 @7 C: u7 K0 m+ W; O e.printStackTrace();
6 q/ C, l; W, k5 h/ [3 M2 j }
. A0 h! G S" m% h3 w6 D* b } else {
0 `+ q' X" }; ]+ ]# }6 U if (list.size() > 1) {+ w. M) Y( _9 J+ ?, m/ E
posName = DateUtils.getCurrentDates() + ".csv";
$ g3 }6 E, c- S- X! p; D& T8 q v CsvWriter.getInstance(",", "UTF-8").writeDataToFile(list, FileUtil.checkDirPath(FLY_FILE_PATH + "/视频数据") + "/" + posName);, A& U+ [" K' J3 z$ X8 @
list.clear();( l* D* l# b, z6 V9 u
runOnUiThread(new Runnable() {
2 D T! D' H& ^, D% O' E @Override3 `0 v. Q* ]/ d3 [
public void run() {
% i$ t( g) n) D" \' M getFileList("end");
4 ^; y* @, ^7 |/ _7 g& B }
2 x! v7 S) y' t' e });9 l, d* q5 Q# ~# q$ U3 E
}
' |, D0 m$ L0 N7 a' ?* M# s1 o }9 A9 W x2 ], f# p1 I
}# R1 S# |4 ~2 q; p3 k% d' Y) t6 i* P
}
5 `: B2 T# `# W/ b" E+ Y });4 _+ P4 Y3 @ c4 I5 j2 H
}0 a# V! H; S* b w1 {
}
. S$ M7 Z% S O$ R0 x ] //遥控器信息
, u" [* }& o+ I7 u private void handheldInforamation(BaseProduct mProduct) {" Z6 k) D7 S# @, h9 F3 Y4 h/ W
if (null != mProduct && mProduct.isConnected()) {
! z! C; q# z) C% w* G6 V handheldController = ((HandHeld) mProduct).getHandHeldController();9 ]2 }! k8 {' e5 G; z
}
( d( G2 P' ^/ X/ q, G+ r if (handheldController != null) {
1 ]+ N0 X; X. F/ w, P handheldController.setPowerModeCallback(new PowerMode.Callback() {
' n1 v- _) t5 l/ ?8 O; R" C @Override
3 g0 |: Q1 h% Y/ x1 Q+ ~" Y public void onUpdate(PowerMode powerMode) {
% n$ M) P1 R' X+ R) `5 K$ V. I/ u switch (powerMode) {
! q* g( v/ u2 Q2 q9 G case ON: q5 y# ^8 T6 y3 y, B
Battery battery = ((HandHeld) mProduct).getBattery();+ n4 ?8 }$ ]1 ?9 ]; d9 F
battery.setStateCallback(new BatteryState.Callback() {
5 \- v X. P3 ]- U ?! s4 n" U: M" o E @Override1 o' R2 X. M; L! ^' |; Y; H5 `8 v# Y
public void onUpdate(BatteryState batteryState) {: u2 _0 v! ]1 }- X A3 y
h_power = batteryState.getChargeRemainingInPercent();
6 ?. \3 Y/ J# k& l5 r- U9 v/ l }1 h* J: }9 W) j8 }
});: D* ?! k" K) t% s
break;
9 s$ [1 L; ~& h2 E% o* p9 E }3 a/ R6 ^9 h4 h3 N
}' \: r+ {' ?5 Z+ N7 j5 d. b
});
/ N M$ o8 @6 t3 }2 _ }: l Z# a% j+ x& o) c' ?
}
# O O- _! N* N. g {& | B% f+ A; o : e- D4 R) ?! ?2 \
@Override% B: h1 u3 Y& D5 F$ k+ H: f$ L( h
public boolean onKeyDown(int keyCode, KeyEvent event) {8 j2 n: G4 G$ \% ] G) w D; z3 m
if (keyCode == KeyEvent.KEYCODE_BACK8 x+ _! a+ _, y5 I- z% I7 ^! G! |1 x7 ?
&& event.getAction() == KeyEvent.ACTION_DOWN) {( H! J7 h9 P/ q5 ?
// closeConnect();
& E% ?9 |) U) t6 U3 @( ~$ b; r) Z( n8 \ MainActivity.this.finish();6 b5 @1 M" K% J7 {- q- P
}
* Z7 K- v5 P5 I( z8 o6 [; ~ return super.onKeyDown(keyCode, event);7 e. E2 \1 h! G& t5 R* _" N5 J
}/ {" y% O& l& q
}
! U9 X$ Z4 r* [3 G; _' l: g3 J4 M完成后界面如下所示:$ Q6 o& o$ C$ X/ n% E
rndxjmine2a64023083406.jpg
: E) A, h! \0 V6 R9 z
上面的工作完成后就可以在无人且宽阔的地方进行无人机飞行了。
, t- R8 J4 D/ q4 H, r. i4 x* v8 b" b% I( |5 J5 N& y) I n
多媒体资源的操作
K* r# g/ Q$ y' w* l P多媒体文件操作,主要为多媒体文件的获取、查看、删除、下载的操作1 p. W4 i2 W! f" Y, x
同样创建多媒体功能文件FileManagementActivity及activity_file_management.xml
. d, [2 ?: y* X& P8 iactivity_file_management.xml
3 U* j+ q: C. \# kLinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
( G% m% A, r4 q x xmlns:tools="http://schemas.android.com/tools"
9 `( b' ]* e) I9 [; l android:layout_width="match_parent"
& K4 d, Y# l! Y; A/ U android:layout_height="match_parent"9 E, f% l+ x. |* w0 q
xmlns:custom="http://schemas.android.com/apk/res-auto"/ j' X G( u1 Y5 ^& u
tools:context=".ui.FileManagementActivity"
. `3 h' _. |3 {+ _6 ^ android:orientation="vertical"& ~ m* F$ T9 `& d% F: E3 t* j# Q
android:background="@drawable/shape_corner_eight">
/ O& @. y( T9 }% [9 Z include layout="@layout/activity_toolbar"$ T" D2 X, J5 S! F
android:id="@+id/layout_file">include>0 m* @" _' x# [1 q K* ?4 Z+ z
LinearLayout5 a4 r' i: _0 K
android:layout_width="match_parent"1 G( j0 [& U1 N( y6 W+ k! d$ S' z. ^
android:layout_height="match_parent", X2 L/ L$ n! P# x1 [3 ~; Y
android:orientation="horizontal">. w' n. V* m. b' d- d$ b2 ?5 M. Z+ U
LinearLayout
/ ^9 n2 K4 Q" _ android:layout_width="250dp"
`% _7 {' R2 ]- Q8 E! i$ h) _; I android:layout_height="match_parent"
4 _3 T9 i$ u! |( i6 M2 s: p android:orientation="vertical" `4 z% x1 e1 [
android:layout_marginLeft="15dp"# t0 ` n8 C) t
android:layout_marginRight="15dp">
1 N* f* P1 u; ?* E% R. s' T! ] RadioGroup
- W* o6 f f5 @ android:id="@+id/rg_file_management"
% I9 N' v& K% z9 j* \ android:layout_width="match_parent"$ N; z* G2 N* N- W1 n
android:layout_height="40dp"4 l0 b/ U2 E0 S; {# w! R# ?8 @& ?
android:orientation="horizontal"
1 L f# }( k' o/ _3 K z android:background="#2B3141"" x! o' i* g" ~! J* c- c2 `
android:gravity="center">* X! J7 R/ K( c$ ~. u
RadioButton) E; C1 [. |$ V) N8 `6 ^
android:id="@+id/rb_file_all"
' ], m3 G% \% h6 l0 k# G/ n android:layout_width="0dp": L" ^7 O: ~5 V$ p' `# ~ ?
android:layout_height="match_parent"* m- B# z8 \" l$ N' h4 }& C
android:layout_weight="1"" D4 J7 C$ ?$ @ E( C
android:button="@null"
* p+ m$ P5 V! ] android:checked="true"; H, v: r6 o6 ?
android:gravity="center"
: N7 r3 G% F/ S. m1 y android:text="全部"' `# J' {' n: w* Q4 E2 ?0 V
android:textColor="@drawable/nav_item_color_selector", T/ s9 ^# |/ v6 ?! ~$ |: g
android:textSize="18sp"5 S1 @3 j0 _4 c7 D! t7 x7 n- f
tools:ignore="TouchTargetSizeCheck">RadioButton>* o a( G9 |3 ]1 ?5 f' H
RadioButton
# U, u- o" J2 R3 ?2 | android:id="@+id/rb_file_photo"8 j0 t4 t4 c" R# T3 j/ Z; o
android:layout_width="0dp": G! a9 r+ g6 X$ G
android:layout_height="match_parent"& q ~, X) [ Y, L; l" l9 C" V* J
android:layout_weight="1"0 Z& s" ~4 S W/ j
android:button="@null"7 S; C7 P, D; a6 j$ Z
android:gravity="center"
, T9 ^4 y* }, I& b- E android:text="照片"0 j% Z: } i0 w6 @0 s( W% s
android:textColor="@drawable/nav_item_color_selector"* [# T; Q( q4 R% Y- K
android:textSize="18sp"
a" A! l! Z* v: N- l( L* ^ P tools:ignore="TouchTargetSizeCheck">RadioButton>/ Q7 a# h& H: d4 ^* ~! t. R% w
RadioButton
4 H0 z7 s& m8 X android:id="@+id/rb_file_video"2 l( l% w2 {2 o8 H# v z5 E. w) j" s
android:layout_width="0dp"
9 m0 H- {7 t- f) R android:layout_height="match_parent"
! y4 x2 o2 U) ~) h android:layout_weight="1"$ u( ^7 S9 f, l; S+ f5 I
android:button="@null"; i3 C; @& X- W
android:gravity="center"
\* _, `$ B% I P, m: v android:text="视频") D7 \! z8 I; D! B. F# U
android:textColor="@drawable/nav_item_color_selector"3 {0 Y( @; A7 s0 y
android:textSize="18sp"
9 `; t F: J$ k4 Q1 ~' E3 |% U tools:ignore="TouchTargetSizeCheck">RadioButton>
3 E( |2 ~# ~3 U' L* e3 l: p3 _ RadioGroup>0 v y% E: Q: ?6 V
androidx.recyclerview.widget.RecyclerView
; m) Q$ ~2 e. }6 x" |+ V android:id="@+id/rv_file_management"
/ C$ h. X. r ?8 k, A F android:layout_width="match_parent"
& [6 z/ [3 k) k' I2 n android:layout_height="0dp"
! o( @# P7 r! t android:layout_weight="1"9 Z* w) g3 s2 R x# n
android:layout_marginTop="10dp">androidx.recyclerview.widget.RecyclerView>, a. s( {$ R* l) \ `
LinearLayout>
: r% f: O7 O) u4 z1 L- o RelativeLayout: I" O- {) w, u( \' G% t
android:layout_width="0dp"
2 V: y% N$ a8 Y5 x9 [' {" L. M6 _ android:layout_weight="2"$ z, c/ {0 M. ?4 ~" I) j( w
android:layout_height="match_parent">0 h0 w! L" a. ~: a6 U3 c0 y
RelativeLayout6 S9 P" s# g1 I; R" {* |1 d
android:layout_width="match_parent"
5 _. }# {( d/ k3 N android:layout_height="match_parent">( l; c, j6 B% Z8 M& R' N& T2 l3 ]+ l( h
dji.ux.widget.FPVWidget+ D" x/ m( I* O, G j1 h
android:id="@+id/FPVWidget". {( p' m6 N- b5 t' ?( T9 t. d
android:layout_width="match_parent"
; z3 @7 M, S7 Q$ o9 {; R android:layout_height="match_parent"
' Z5 ]; o( g% H2 i3 z; {( B* ] android:layout_centerInParent="true"- \: F) M$ c! _7 L
custom:sourceCameraNameVisibility="false" />( @; P. ]& W+ Q; o& P+ z7 k4 c) a
RelativeLayout>
# G/ h+ T9 ^6 z6 T ImageView
3 B1 t0 O8 i7 T, c6 D android:id="@+id/img_show"' F* p/ J o7 u& x) y: `! g8 l( e
android:layout_width="match_parent"' E# m7 {, U: q2 Z
android:layout_height="match_parent"
+ o1 P+ W O" r% ] android:scaleType="fitXY"8 J1 f$ s5 Y8 s5 m A9 t; f, \6 O
android:visibility="invisible">ImageView>
! G/ K# G# m7 M4 `& L- w$ Q LinearLayout: y y2 p8 l* U u( B2 y% j5 H
android:id="@+id/ll_video_btn"' [; E$ L9 \( Y
android:layout_width="match_parent"
% V" W- f$ m4 s: K android:layout_height="50dp"$ k0 a' [) u3 o, I) i
android:orientation="horizontal"* k0 n" B+ U- h0 d* o* T( K3 l
android:gravity="center"3 H. m2 c) N1 X8 b/ x* E, L
android:layout_marginBottom="15dp"
# B9 z3 |: N6 G6 u& c" \+ R android:layout_alignParentBottom="true"8 w3 u2 B: J7 O* I) f! y3 c
android:visibility="gone">, s3 a( P' h/ G' r p
ImageView) v0 ]* B3 O- m5 }1 Y$ a
android:id="@+id/img_video_pause"
2 C5 Y4 T* D6 K% }5 G9 _ android:layout_width="35dp"
% K3 O+ \* w4 x# ?# F9 J. p4 l android:layout_height="35dp"
1 `8 s4 |7 n0 r8 z9 C* Y/ D android:src="@drawable/background_stop_selector">ImageView>* o) n( Q- o! P
ImageView: a) J% R+ j. ~* W/ F( e
android:id="@+id/img_video_play"
8 v- G2 q) I l, V" q9 |4 S& f android:layout_width="45dp"7 d1 ]" k& ?- e) M _$ c/ h9 z! n
android:layout_height="45dp"
8 N( y7 f6 F8 ]3 a* K android:layout_marginLeft="20dp". o w+ e3 v6 C
android:src="@drawable/background_palyer_selector">ImageView>
( T- q) N9 F. H" y1 ]# _& @ ImageView2 C1 y b! J- J+ j. e8 L
android:id="@+id/img_video_stop"
) t$ g8 q5 K, S8 \) M1 z, V android:layout_width="35dp"& B) u) _4 _2 [- u& D' p' l
android:layout_height="35dp"
" d* s6 F3 {# c( d7 g2 _( z2 A/ Z android:layout_marginLeft="20dp"; Z/ i$ C K+ U; T' f( Y; S5 t0 E; n0 w
android:src="@mipmap/ic_reset_36dp">ImageView>
# n1 K; |3 k; R; m' I/ I |: R LinearLayout>7 h0 Y$ u6 @; e/ H B% V
RelativeLayout>
. ~3 Z! R4 w) i- _, ~, F" u' p9 } LinearLayout>- z& Z$ w5 Z8 f* E# U4 f
LinearLayout>
1 D. x/ H/ \0 ~" {FileManagementActivity9 Q. W% o. E) K0 P) Y$ P
@Layout(R.layout.activity_file_management)
0 m' x/ v( W4 h7 w% p- _public class FileManagementActivity extends BaseActivity implements View.OnClickListener {
; [" W8 P/ o5 R private static final String TAG = FileManagementActivity.class.getName();
, K: d5 c: |7 F5 W- j [ @BindView(R.id.layout_file)' a+ Q* `) J( e1 u( h
View mViewLayoutToolbar;
# z- R; F* n3 [ @BindView(R.id.tv_toolbar_title)9 J* i" P7 L5 k. g$ p# S6 D" S7 S
TextView mTextViewToolbarTitle; W& T+ [' Y: a( P2 A6 j7 w
@BindView(R.id.ll_file)) X$ e; `- d, k1 ^
LinearLayout mLinearLayout;
; f+ ?* W m1 m8 H @BindView(R.id.rg_file_management)
; m+ p1 t3 n+ G% F0 |1 q* Z# d2 h RadioGroup mRadioGroup;+ g7 X4 {. K8 j' d5 f8 R8 ~
@BindView(R.id.rv_file_management)
h7 \! A' I, E RecyclerView mRecyclerView;3 J* B" r: b% E+ J3 Z
@BindView(R.id.img_show)
3 ?) W3 x, G' y ImageView mImageView;2 J1 h+ T5 L8 D& @' {
@BindView(R.id.ll_video_btn)
8 d/ D' e h# U# r3 e! O LinearLayout mLinearLayoutVideo;1 `' V% l: H: ~, p: `4 Q* i9 w
@BindView(R.id.img_video_play)* b- L4 \: h: N; O+ q5 Y$ J
ImageView mImageViewVideoPlay;
" o; M0 c8 R6 S0 }+ N1 W- Z' @2 n @BindView(R.id.img_video_pause)
! j k6 ~3 Z- V- N5 W8 e* z1 x ImageView mImageViewVideoPause;
- ~+ _+ q0 e7 A3 ^ J! H private FileListAdapter mListAdapter;+ m( E( Z, z5 w: a1 Z9 ?+ }; S3 h
private List List = new ArrayList();
7 a+ Q S* F |& w private List mediaFileList = new ArrayList();
. r0 I8 R: O, o3 l& m7 y& C6 } private MediaManager mMediaManager;
. W3 {& q' d5 h private MediaManager.FileListState currentFileListState = MediaManager.FileListState.UNKNOWN;4 d& t9 Q7 K D* B8 A8 @
private MediaManager.VideoPlaybackState state;2 N' N& R1 ^9 E1 k
private ProgressDialog mLoadingDialog;& k3 n E1 @# \0 p! Z
private ProgressDialog mDownloadDialog;
& N9 |4 y1 }5 Z private FetchMediaTaskScheduler scheduler;' `1 L3 Z2 @: T, O! `
private int lastClickViewIndex = -1;
6 D2 W8 c0 S! n! e- m private int currentProgress = -1;
6 ~1 q9 }" Z6 O! z" ^ private String SavePath = "";- K% g7 b; c( l, |/ s) A
private View lastClickView;
* H5 F( _" j6 A1 W private boolean isResume = false;
9 e; W) a1 r% x0 O) u) f private SFTPUtils sftp;
% r# b3 T/ _3 w& c1 X7 c& [* Z R$ x private SettingsDefinitions.StorageLocation storageLocation;3 }% i2 v9 Q: |8 d4 L: x
@Override) I/ c+ J5 Y6 V# g/ b8 W9 p
public void initViews() {6 G+ L9 Z% G/ p O7 J2 E* }
mLinearLayout.setVisibility(View.VISIBLE);& {, x' v# H) ^3 U1 t
mTextViewToolbarTitle.setText("文件管理");
" Q, N3 E% }7 q5 R0 a mImageViewVideoPlay.setEnabled(true);; f& P! s. R9 R# i. D
mImageViewVideoPause.setEnabled(false);/ F+ n6 T, g2 e% [
mRadioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() { r+ F V" _* i/ S/ U2 Q
@Override
" Y0 _7 h) J5 {. B- c public void onCheckedChanged(RadioGroup group, int checkedId) {
' r5 S! H+ n: l( [# b) U7 j List.clear();
4 E+ ^/ G& e( {$ \$ R0 y9 ?+ L5 s mediaFileList.clear();
7 n( V& n9 B$ Q switch (checkedId) {/ O3 c8 d* {& d$ ]. f. g2 v* ~
case R.id.rb_file_all:) @ L, }+ K' ^
getFileList(0);1 I4 r& w* _" W& i
mListAdapter.notifyDataSetChanged();1 t [3 W; Y3 }, U9 g! d8 ^: e
break;) z2 O% c: c0 V# a8 X+ w( p
case R.id.rb_file_photo:- Y K5 |& R7 v% D& b2 y$ S
getFileList(1);# q5 L# H. t$ c8 B4 l! J* u
mListAdapter.notifyDataSetChanged();: Q/ o5 W8 ^9 P4 x- Z# q- z: h
break;
# l+ O+ _9 A* Q. M& Z$ p, l; A2 C case R.id.rb_file_video:4 r2 N \# e! i5 V
getFileList(2);
& K. \2 g! L* g, ? mListAdapter.notifyDataSetChanged();# w2 X, C* C" B0 A" z
break;- N' h5 S+ @/ U9 W% X; B7 a
}
/ e" ]9 ^, }' I5 o, l& a }7 v% K3 i) ?- U2 Q/ o% @
});8 A! g, f0 e; c& D
LinearLayoutManager layoutManager = new LinearLayoutManager(FileManagementActivity.this, RecyclerView.VERTICAL, false);
( c' [' u; K2 E0 l' _0 @4 L3 v1 U; | mRecyclerView.setLayoutManager(layoutManager);3 U6 H0 `2 b, C5 u) Q3 m' N! q
//Init FileListAdapter9 I b7 Z8 }+ e% g. k+ W: {3 B
mListAdapter = new FileListAdapter();, j5 E! R5 ?+ U" r& o$ Q
mRecyclerView.setAdapter(mListAdapter);3 K4 U# u3 h' N! h8 p8 w9 |+ j
//Init Loading Dialog
/ ?$ V7 i8 }+ n! k C* _! }$ O9 d/ u mLoadingDialog = new ProgressDialog(FileManagementActivity.this);5 L9 p- e v" Z) r
mLoadingDialog.setMessage("请等待...");6 L6 K/ s, X: g
mLoadingDialog.setCanceledOnTouchOutside(false);; @, T6 E$ F8 z' m
mLoadingDialog.setCancelable(false);
; c. U$ j4 E( }. @) B //Init Download Dialog# E) J, |! o& u6 p/ P+ {4 ^. E5 G
mDownloadDialog = new ProgressDialog(FileManagementActivity.this);' M3 y( g3 k( B5 w0 b" ?
mDownloadDialog.setTitle("下载中...");
) ?: C! q' P! l, K8 g" I mDownloadDialog.setIcon(android.R.drawable.ic_dialog_info);3 k5 S8 r. p# m/ s G3 S, J
mDownloadDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);3 s0 m0 X1 b2 s8 _' i
mDownloadDialog.setCanceledOnTouchOutside(false);. X& o5 X0 b3 c" z
mDownloadDialog.setCancelable(true);
2 r( S3 ]: F5 V( w4 M4 e" f# h mDownloadDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {2 A* L: O' Q ^* d
@Override
) x; b& o/ H9 [' V& J1 _ public void onCancel(DialogInterface dialog) {# s% X& F$ Z5 U2 S0 U9 f3 ?! c
if (mMediaManager != null) {4 M" z4 \1 x2 E
mMediaManager.exitMediaDownloading();
: Z% d5 l$ a6 J$ T$ _* w9 F }- T% f( g6 Y* e6 s
}( w1 f$ p$ q# W7 r
});& v8 O- ]5 E8 H
sftp = new SFTPUtils("49.4.79.249","uav","uavHHch@YREC.cn");" @7 U4 N6 [: d: d6 Q
ReceiverApplication.getAircraftInstance().getCamera().setStorageStateCallBack(new StorageState.Callback() {
# r2 z8 S, D' U3 w @Override
( `9 w1 T7 X; m1 G! ]6 v8 d% y* E/ O: t public void onUpdate(@NonNull @NotNull StorageState storageState) {
" o* b) @5 D1 h: C if(storageState.isInserted()) {
0 Q8 H* ~, a7 A0 q+ S' T( Q# _ storageLocation = SettingsDefinitions.StorageLocation.SDCARD;
: Y1 b: j( m) r ReceiverApplication.getAircraftInstance().getCamera().setStorageLocation(SettingsDefinitions.StorageLocation.SDCARD, new CommonCallbacks.CompletionCallback() {8 Y4 P' _" p8 M) ^( L' }/ V
@Override
' z# _+ A' Y6 g/ G) L- @- ^: Q public void onResult(DJIError djiError) {
% l8 c% h3 `9 d. D5 N+ L3 w }
) v" M& T& ~% l* B4 Y4 ^" L });: a3 M3 i& j. C: z; o
} else {
% L' ?' L& D. Z& S1 ` storageLocation = SettingsDefinitions.StorageLocation.INTERNAL_STORAGE;
% o% p# j0 h* c ReceiverApplication.getAircraftInstance().getCamera().setStorageLocation(SettingsDefinitions.StorageLocation.INTERNAL_STORAGE, new CommonCallbacks.CompletionCallback() {- n( w3 K. j- e7 ?
@Override
: Y% H1 @/ g3 ^; S, m+ g/ G/ _ public void onResult(DJIError djiError) {1 p8 ]7 R' [( Y9 B* ?
}* c! d. d( w( a; _6 Q+ W
});
8 g3 ~5 k, x, ?4 r }
d$ [- |0 I; }, v! f" v5 L }
8 G: }3 j/ ~/ x- ~# c0 m' `- L });! t5 J4 @4 `3 o( M% \
}2 P( V4 }0 Q& z D: x l2 ?
@Override X% N+ `7 L3 L' y
public void initDatas() {
* L4 B Q3 H: {& ] }) r; c4 T9 y: f3 {; o6 y
@Override
' r# f) L, ?0 g/ n3 R' f+ S/ i4 X# Q protected void requestData() {1 p, |! ]7 `' H1 u
}
4 }$ u1 U% Q U- i @Override
+ X3 Q( E4 {8 Y" x/ E public void onComplete(String url, String jsonStr) {
" {& S4 q% H3 w( D# [) c7 E super.onComplete(url, jsonStr);+ [$ T- I3 h8 A( I
switch (url){6 X S1 x5 O: K y+ t
case POST_VIDEO_INFO:) f4 ~' s& o' s* r9 A1 A, s+ R( y
break;' a5 R, ^; F S [( n3 @
default:
. f' s5 j; b/ \, q: ]& s getVideoJson(jsonStr);2 l% S3 ~/ m) E. g5 k2 a% W+ w
break;) Y+ q# N0 F2 D1 w% M
}; { \5 M: D; P# Z% V& Z& r
}
7 z5 a$ Y! w$ ]6 c! t6 D private void getVideoJson(String jsonStr) {3 T8 }" B# p; t) ]0 v2 Y
VideoModule module = GsonUtil.GsonToBean(jsonStr,VideoModule.class);
7 Z0 v; A0 A2 U. I/ c: K if (module.getCode() == 200 && module.getRows().size() == 1){+ M. k, F* n% y5 d8 [5 G
runOnUiThread(new Runnable() {9 e* G& m. F/ t5 E. e, |
@Override
6 t6 \& P4 G7 J2 K9 E+ { public void run() {
% t! _2 P, E6 b- t, l5 Y UpdateFileModule fileModule = new UpdateFileModule(module.getRows().get(0).getId(),"/mnt/uavFtpFolder/"+module.getRows().get(0).getFileName());1 X4 l/ S5 w# _
http.getHttp(POST_VIDEO_INFO,"PUT",GsonUtil.GsonString(fileModule)); B c& d3 u5 C ~" N
}# J5 W0 q0 X4 s. F
});
. N/ C, q! k3 v/ p h }
m/ N% u# n; ~) B. w }
( j3 |0 k' y: U# ]# z5 J5 I @Override
; a( ~- I- f; W' t protected void onResume() {( O6 w& }- O& Z: @$ E$ j# Z
super.onResume();4 `1 K% \! T- h2 H; N% s
initMediaManager();
: {, k! ]# `4 s, x$ U7 |- S: _ }4 ^) t! v/ V* a: D4 I, z
@Override
6 H, T1 V. u7 x5 _4 S3 b+ H protected void onPause() {
: x* ?& C5 e: i: ^. l' ]: q3 W" n super.onPause();
. ^5 s g K2 C+ ^7 w8 j, T }
) `$ Y5 y4 u- P$ R1 _, N @Override
: o2 \2 l+ Z% X7 Q) } protected void onStop() {" @8 k3 k4 G2 Y! A7 J( V% l
super.onStop();0 E; @$ B! j, y0 P
}
: g4 j# y0 i, B9 W' @( v
& k( ]5 H P5 O* S @Override
, w0 W* v6 p, C( V' l/ t protected void onDestroy() {$ X; q' {2 Z8 p8 V6 h6 [7 D/ x" U
lastClickView = null;
/ A R$ T- ^/ a0 W' R if (mMediaManager != null) {
( h& O7 e% A6 @ _5 l mMediaManager.stop(null);& i# ^5 Y8 g# X
mMediaManager.removeFileListStateCallback(this.updateFileListStateListener);1 C- N3 \! O8 Y9 u& z8 Z* W
mMediaManager.exitMediaDownloading();
* p3 L( f! [3 S% h3 x if (scheduler != null) {6 f" F. T8 S5 a* `2 ], m0 \ h
scheduler.removeAllTasks();; s3 Y+ h8 A. g7 ^6 c* |0 b3 w" U
}
8 v- l" x+ r9 N; [ }4 e/ N7 X ~7 T# S! m3 F# S
if (isMavicAir2() || isM300()) {. V$ k% X( l: T9 D) k7 ?
if (ReceiverApplication.getCameraInstance() != null) {1 v* Q5 t. {* |# W
ReceiverApplication.getCameraInstance().exitPlayback(djiError -> {6 j/ P; q O' X
if (djiError != null) {
6 v( d3 |" v8 A ReceiverApplication.getCameraInstance().setFlatMode(SettingsDefinitions.FlatCameraMode.PHOTO_SINGLE, djiError1 -> {
9 O! E: }5 A9 K: S- e if (djiError1 != null) {% ^. `* b' e* {+ L' D$ p
showToasts("设置单张拍照模式失败. " + djiError1.getDescription());6 G( q2 @$ H- V& y' F# X8 H7 L
}. I" z5 L# A" z( ?8 v: m2 D! G- a
});5 Q4 `" i6 J k4 r
}
9 V) m7 Q: p5 k' n- {# E$ n: n! R });1 K3 R6 s# M; a/ L% W: K- I
} else {1 M- T( {: R0 T- \1 I R _4 g8 u, O
ReceiverApplication.getCameraInstance().setMode(SettingsDefinitions.CameraMode.SHOOT_PHOTO, djiError -> {
2 G5 V" @8 E- ^& P" X$ L2 B if (djiError != null) {
8 x2 ` G) w8 u! k showToasts("设置拍照模式失败. " + djiError.getDescription());1 X9 F h9 D/ H" C. n
}
/ r$ Q/ O* r1 a0 |8 e1 V });9 n2 `% x$ w; M. ^1 R0 J5 A* w# }
}4 w% ?$ \: g! P: m
}& q) G" r5 A% @1 I1 M
if (mediaFileList != null) {& x) k& D3 k1 a( K9 V* A
// List.clear();$ i9 v- W0 Y7 }
mediaFileList.clear();; N. ]2 L6 X" R$ w; {) N, }
}. M) G8 p1 O0 L" P0 b# G/ y% T( |
super.onDestroy();. a" D$ L3 [7 K9 t- ]% r
}
+ Q: Z7 [, Q& h \1 B5 H private void showProgressDialogs() {1 i& d8 h2 H2 `
runOnUiThread(new Runnable() {
9 x4 V' F& Q3 U# U4 L" b0 W ? public void run() {/ W1 Y/ B1 v1 E
if (mLoadingDialog != null) {
# z! x( y m$ p) v9 F( c1 j mLoadingDialog.show();; w4 o9 |4 ^' i% E. }& A
} a( C" M7 S/ E* Q4 ~) F: f1 O x
}3 N1 [$ B( d0 B- O3 {
});1 @8 Z- C! g1 \, z8 Z/ k4 T, \: q
}
+ f' H8 }1 w* \ private void hideProgressDialog() {
. D2 E |3 v/ T+ b runOnUiThread(new Runnable() {
$ Z3 U3 F! w8 k; r# O7 D public void run() {5 _; P; @( ?$ B5 W$ N, t4 h9 e* C
if (null != mLoadingDialog && mLoadingDialog.isShowing()) {" T+ `4 ^+ c$ o8 C- H
mLoadingDialog.dismiss();
^" i4 l: S' l8 D) Q5 G }- p" L2 x7 U" ~: a: L- `
}
& p+ t1 U" z4 \* o/ B });, ~# a( y4 i" |8 M O( N
}6 [. j9 p* u* f2 u; n0 Z
private void ShowDownloadProgressDialog() {
4 L* ^1 V7 Q) q+ `6 u& Q if (mDownloadDialog != null) {
# Z# | H4 x* K% g, o# R" M runOnUiThread(new Runnable() {
& |* O- `9 {0 @ public void run() {
3 Z k$ N6 N; s2 v9 @( o mDownloadDialog.incrementProgressBy(-mDownloadDialog.getProgress());% V* ~" S2 e% l8 p; u+ X& {
mDownloadDialog.show();+ c' a9 e" K+ `3 ]0 {: F1 m/ S, |
}
3 M$ U" l: z2 j0 | });! g9 R7 s! D: p; q
}, e$ h- t1 ^( w' W9 k" W0 y) n
}$ S- d8 V3 I; X5 {
private void HideDownloadProgressDialog() {6 |- b3 d; _& D* ?0 k9 y
if (null != mDownloadDialog && mDownloadDialog.isShowing()) {! B. e4 z; f; D- W. o- q
runOnUiThread(new Runnable() {
$ z2 h9 p" \& M$ S public void run() {; n/ g( q" W7 [
mDownloadDialog.dismiss();/ X0 V: i" m- e1 j; v# z
}$ L5 b% ]0 X9 @, A1 Q+ ?/ w
});
$ |5 V- Q0 o m3 B* X }, ^8 M* ~9 V' v, v
}0 a3 i5 i. _ O/ u& A9 C: a8 d
private void initMediaManager() {
- ^0 s8 P Z! b: Q; R, } if (ReceiverApplication.getProductInstance() == null) {
% }2 p. G) B! }2 \1 |2 E2 ]* p4 x mediaFileList.clear();. m* W. |" {) N/ |
mListAdapter.notifyDataSetChanged();
2 |/ ~1 W O5 y, _& l q9 ?& ` DJILog.e(TAG, "设备已断开");
: D+ y/ {' H- w0 P return;
3 d* I5 Y( _; r1 _ } else {! r" w4 Y- h4 G+ u0 V3 {' ?* p' Q
if (null != ReceiverApplication.getCameraInstance() && ReceiverApplication.getCameraInstance().isMediaDownloadModeSupported()) {
H" X x1 D! G5 d5 b mMediaManager = ReceiverApplication.getCameraInstance().getMediaManager();5 y4 ]' E4 K8 \) s# g
if (null != mMediaManager) {& V$ l9 A3 f* Y9 [2 Q
mMediaManager.addUpdateFileListStateListener(this.updateFileListStateListener);
" M: c6 K1 l9 w5 \1 d mMediaManager.addMediaUpdatedVideoPlaybackStateListener(new MediaManager.VideoPlaybackStateListener() {
& P5 }# [6 b1 q8 R- G D @Override: _+ [" J" e( L! [1 U# Z
public void onUpdate(MediaManager.VideoPlaybackState videoPlaybackState) {& e( o# I' m. S& S( \% n- M) d
state = videoPlaybackState;
$ q! z4 M% D- `% J- [2 Q9 { if (videoPlaybackState.getPlaybackStatus() == MediaFile.VideoPlaybackStatus.STOPPED){2 C! [( F$ j) c% i
runOnUiThread(new Runnable() {2 v8 Z: I0 c: u! \& i% [) K' t; F4 B
@Override
# ` j8 [+ x& P. ~9 Y7 q: Z* v" a public void run() {
/ J7 p0 c: Y% O2 @// mImageViewVideoPlay.setEnabled(true);
% p0 @0 y; ~7 N- i+ p9 G$ y% B// mImageViewVideoPause.setEnabled(false);* C: }" d) B+ s" r N5 {6 |
}0 ]) \# h- G F0 S) w2 j$ A4 [
});! h- D4 q, S' t; @; ]
} p: d4 u( O* B& c
}
* J7 Z) E$ q6 P7 { });
- f, F% M% R" V1 B* a+ O if (isMavicAir2() || isM300()) {
0 Z" |# Y0 a5 {) \' z* C ReceiverApplication.getCameraInstance().enterPlayback(djiError -> {
+ s0 ^7 \4 f* o9 O8 O/ O if (djiError == null) {
2 `/ O8 H- G6 }9 F5 J: U DJILog.e(TAG, "设置cameraMode成功");
( F3 M- n* Q$ r showProgressDialogs();4 R. ]* x4 i* a! U# A5 k4 U; {
getFileList(0);
% d- U5 A6 m4 P% Q$ L } else {+ A+ n5 p- {- V! i% c4 M
showToasts("设置cameraMode失败");; a& Q2 C1 I# Z: U; _5 g$ o2 m
}2 Z5 f, [2 c9 t+ C9 [$ @
});# v- \' s# i. j* I: ]
} else {! t+ Y6 T( D( O: _3 C+ B
ReceiverApplication.getCameraInstance().setMode(SettingsDefinitions.CameraMode.MEDIA_DOWNLOAD, error -> {
9 N, d' T# P5 @9 ^; y" L if (error == null) {
8 e; a: k2 S- p6 S: ? DJILog.e(TAG, "设置cameraMode成功");2 C" N, h4 }- z
showProgressDialogs();; g" `! {' Z3 |
getFileList(0);3 N" F1 O. b) a/ f$ B9 T B* i7 w( @$ L
} else {& L4 N$ D! x4 b3 X' J, g
showToasts("设置cameraMode失败");
' L5 u' M I: r1 S6 t* D4 e+ Y& ? }
! X- J( _* M2 g: h });
5 Q& a# k# d+ u2 a! T3 g }. X7 T3 v/ e4 l4 E5 Z
if (mMediaManager.isVideoPlaybackSupported()) {
- E( z) r% f: ^8 O- H. ]: f DJILog.e(TAG, "摄像头支持视频播放!");
# f/ `+ S, t- U- N/ Y7 ?$ z } else {* e$ T- E5 D3 U! P/ @2 d5 g/ A& Y _ S
showToasts("摄像头不支持视频播放!");
1 e( S2 K* @6 c5 W# y }
$ T# Y" h b8 h6 Z' a8 i+ ?3 ^ scheduler = mMediaManager.getScheduler();
$ M8 b: H5 |$ t+ C }: H9 u' @$ I5 }' v. V! {/ ^1 i
} else if (null != ReceiverApplication.getCameraInstance()
! V. ]5 }7 K; Z && !ReceiverApplication.getCameraInstance().isMediaDownloadModeSupported()) {$ a+ j2 S- B# I+ z) M
showToasts("不支持媒体下载模式");. C' Z- a [. O& w# H
}/ s4 S+ w; m+ \
}
" J- z& C' Y! z3 Y return;
- r) T% m" ^. u8 o; p. V( ^ }
" r/ N$ q9 Q: g# A/ \6 \ private void getFileList(int index) {
3 j, Q* k9 t! H. ]5 S0 t mMediaManager = ReceiverApplication.getCameraInstance().getMediaManager();
( p! J/ W6 C. ?7 k# y8 q5 f if (mMediaManager != null) {4 }3 A) n1 C5 L: I; a, R% |- p# M5 o
if ((currentFileListState == MediaManager.FileListState.SYNCING) || (currentFileListState == MediaManager.FileListState.DELETING)) {" x- A) d! s8 ]/ x
DJILog.e(TAG, "媒体管理器正忙.");
) e; Q1 N; {1 e1 d D+ {4 w: k } else { y7 d7 z3 N+ X8 w. Y$ v
mMediaManager.refreshFileListOfStorageLocation(storageLocation, djiError -> {
! \+ u; k6 ?8 X$ \, h" \// mMediaManager.refreshFileListOfStorageLocation(SettingsDefinitions.StorageLocation.SDCARD, djiError -> {# k* v0 w" M$ A" `3 L; V
if (null == djiError) {# A0 w$ ]' h# c- G
hideProgressDialog();
$ F: f) x# D( e0 V0 _; x //Reset data! r! G; _/ l8 L8 p
if (currentFileListState != MediaManager.FileListState.INCOMPLETE) {6 E* i3 Z9 N; j ]
List.clear();
% U, `' l: P. j4 T, y7 s mediaFileList.clear();
~! ? v+ M. L6 h2 X# o lastClickViewIndex = -1;2 ?1 }; t# O7 j$ G
}
" H ?, V7 B2 k" i// List = mMediaManager.getSDCardFileListSnapshot();" R; Q- _ F9 \" Y
// List = mMediaManager.getInternalStorageFileListSnapshot();4 v7 ?" N; H8 o' f% m
if (storageLocation == SettingsDefinitions.StorageLocation.SDCARD) {: h9 K& X* A% V; X' J
List = mMediaManager.getSDCardFileListSnapshot();8 M1 h: {2 ]& j/ a9 I
} else {# C! ~; K) D' V& J& a+ ?
List = mMediaManager.getInternalStorageFileListSnapshot();
+ L: s6 @0 \! T2 q }) G8 n& ]' R J( l
switch (index) {
8 |0 Z- L: M& E case 0:
6 S, R, G3 l; v for (int i = 0; i break;
# F; p' A/ _; q4 C, }( j case 1:
- k; R8 s- R3 L5 Q/ Z8 e* f for (int i = 0; i if (List.get(i).getMediaType() == MediaFile.MediaType.JPEG) {' }5 G8 x* l0 S% K/ q, _$ ]; n Z) k
mediaFileList.add(List.get(i));
1 C; H; A/ K# e) ~ MyLog.d("图片名称:"+List.get(i).getFileName()); U" q5 j( h! n0 F8 @7 z
}
! u p/ P# K0 a } F. [# _7 b0 P" @" f _7 T- H% `- y
break;9 O7 Y8 d/ F1 \: v+ e
case 2:
6 u- l( A+ q2 \. W" j for (int i = 0; i if ((List.get(i).getMediaType() == MediaFile.MediaType.MOV) || (List.get(i).getMediaType() == MediaFile.MediaType.MP4)) {4 f& P4 C8 O, a1 Y4 J% R4 K7 X
mediaFileList.add(List.get(i));
! X5 j0 t5 Z/ E- P" x0 }3 H4 h MyLog.d("视频名称:"+List.get(i).getFileName());' g. ~" m3 @0 g+ A3 p! T
}
7 T, M) K2 Z6 b, K; J1 u7 y }
2 g% \/ C1 M& y5 | break;
8 J) _: O" j% k( V h' V" K }0 ^% P m9 i% R& z
if (mediaFileList != null) {. u, E" a7 n- z+ p- x
Collections.sort(mediaFileList, (lhs, rhs) -> {) x8 L+ ~9 M: L
if (lhs.getTimeCreated() return 1;
6 H% c8 t7 A" _# ]; {: _ X } else if (lhs.getTimeCreated() > rhs.getTimeCreated()) {- N& z f8 F9 Z/ G
return -1; E! ~, B* m& [7 L" P
}
& \' y" Q" l/ ], ] return 0;
/ \, _4 B' D7 p5 v) U. S });
' Q) o8 t% F5 u }
5 j3 R2 K4 `! ~2 K. G; {1 Z9 C scheduler.resume(error -> {
; \. W% }. u; ` if (error == null) {
5 z' y z2 f+ ~. v getThumbnails();* \% Y2 m x- K( R. G
}
" {3 R+ r& b3 u });
! U5 v* a( @9 ?% E( T } else {
$ T9 f* b! |8 Z/ d+ o) a; l hideProgressDialog();* C" A) N; i p! g% v& A
showToasts("获取媒体文件列表失败:" + djiError.getDescription());% Y; ?7 `3 l" f |
}
7 l5 o; b/ {0 F/ y: L });- O& f( ?1 C$ p& J' D# T
}
: ?+ P3 [8 i$ ~( A/ |; b }& m+ E8 b0 ~ M' ~9 d' f6 A
}- i% `8 d2 T2 @, X1 p, |
private void getThumbnails() {+ u0 l; D9 M- p+ Q# ~. S( T
if (mediaFileList.size() 0) {5 w' R1 }$ A3 y' r d
showToasts("没有用于下载缩略图的文件信息");
( t0 J1 L3 e$ L return;
+ v' r* \4 d7 `" j G$ H }
0 b F7 J; P+ y5 g8 d0 B+ f/ p for (int i = 0; i private FetchMediaTask.Callback taskCallback = new FetchMediaTask.Callback() {
8 l0 K. H9 \9 \8 y9 F) b @Override2 K0 ~, k8 `% e4 g$ C0 T
public void onUpdate(MediaFile file, FetchMediaTaskContent option, DJIError error) {
4 m# s' i" {) F# S if (null == error) {
2 D! n6 g8 M& ?! D if (option == FetchMediaTaskContent.PREVIEW) {
0 u. X& a/ g2 \* e2 z runOnUiThread(new Runnable() {
+ L* J" C9 g- S3 K# d& i. X6 m public void run() {1 z# [7 W8 G: m/ Y0 z; B
mListAdapter.notifyDataSetChanged();" @$ o1 M r% G
}
: d6 Y- S6 q4 N6 {) c });
' A& L( {* c0 `) K) i }
/ y2 t* {: C. ]# S if (option == FetchMediaTaskContent.THUMBNAIL) {
: }- Y3 \, N6 Z: U# h. ^ runOnUiThread(new Runnable() {2 q- \ L2 F w2 Q- [
public void run() {: _* J: l6 J5 ?% C& \. N8 ^% p
mListAdapter.notifyDataSetChanged();0 d" {+ m: M( f. Q% y p: H* ~
}" q# V% C: T! Q: D/ o
});
2 M# `' G9 U% h6 S6 _ }' @7 |, h: L) h7 ~# N. V
} else {- G9 B. U) o5 h) E
DJILog.e(TAG, "获取媒体任务失败" + error.getDescription());- h8 v' k- R" n( \
}
6 e; H4 z4 a* Z# f }
8 K# p1 D) ]( f4 q9 P5 \ };
6 {, V x2 W% `- q% M) z private void getThumbnailByIndex(final int index) {1 [* P* V' x& N2 e3 Q5 f8 V! @
FetchMediaTask task = new FetchMediaTask(mediaFileList.get(index), FetchMediaTaskContent.THUMBNAIL, taskCallback);
7 H, [- D4 _; y M( I5 g scheduler.moveTaskToEnd(task);
$ c! E" b8 D! ~ }0 A4 B0 C, W5 V5 a! i/ W9 l
class ItemHolder extends RecyclerView.ViewHolder {
3 W3 G4 k2 \+ m ImageView thumbnail_img;; n- F j' z; ]/ T. W/ k: [
TextView file_name;
: c( q+ h2 C" G8 r; l4 H/ q TextView file_type;/ P/ e- I' @4 u# a# b
TextView file_size;
+ K9 W h$ R3 J( O TextView file_time; f+ |+ S( {) t$ u# m# j2 P8 O
public ItemHolder(View itemView) {
( j& p2 G3 r# M3 `1 b$ N$ e5 S4 k super(itemView);
z4 i0 j7 Q: L) U this.thumbnail_img = (ImageView) itemView.findViewById(R.id.filethumbnail);
; i8 l: Q0 D$ K( O% k7 Q/ r this.file_name = (TextView) itemView.findViewById(R.id.filename);
9 `/ G8 S. C4 C- C* o |! L this.file_type = (TextView) itemView.findViewById(R.id.filetype);
- A( |0 k+ A$ U8 { this.file_size = (TextView) itemView.findViewById(R.id.fileSize);% z1 N! M3 U: S [) |9 j" I4 R3 S
this.file_time = (TextView) itemView.findViewById(R.id.filetime);
8 J6 `$ e A( Y4 e' y }0 \2 y( _+ E2 m+ q5 q9 N
}
: `. \+ M0 ~* u8 J6 H- ] private class FileListAdapter extends RecyclerView.AdapterItemHolder> {: [7 X9 p, `' I
@Override) c! l* @9 v+ p6 |; D7 b3 g2 L
public int getItemcount() {
: t% q+ C/ |+ \# ]# R if (mediaFileList != null) {
8 Y% b5 }1 ]/ _: b# c return mediaFileList.size();
3 \. N4 L. C. W }% l. K7 u7 j5 [" k
return 0;
+ Z8 S0 t3 F0 P6 T0 T2 Z% l }
2 W* s: W# t4 ?+ U) ` @Override
k% c( z5 x9 C; L public ItemHolder onCreateViewHolder(ViewGroup parent, int viewType) {# B* a- `: I1 N* ]0 {8 g
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.media_info_item, parent, false);
3 a6 w. U* T0 H( Y" H" h return new ItemHolder(view);+ ^( ~' I/ B# F. I5 ^
} y% `; t8 D- ^# ?6 ]( A
@Override, `( V8 B4 S/ M z# `) K3 Y6 U! C8 h
public void onBindViewHolder(ItemHolder mItemHolder, final int index) {
7 R/ r( n- e2 j* Y5 x$ F3 r final MediaFile mediaFile = mediaFileList.get(index);7 u/ G; f6 x$ J$ U" Z5 `7 S( S/ l
if (mediaFile != null) {
9 H! F6 g1 E3 F if (mediaFile.getMediaType() != MediaFile.MediaType.MOV && mediaFile.getMediaType() != MediaFile.MediaType.MP4) {- Y; `6 T* A0 g9 f r. S/ V
mItemHolder.file_time.setVisibility(View.GONE);
+ l$ `- X! U' M } else {
: k: ~9 X' h( v mItemHolder.file_time.setVisibility(View.VISIBLE);
. y1 w$ a8 P. u9 J% v8 v! K mItemHolder.file_time.setText(mediaFile.getDurationInSeconds() + " s");4 Z# e) K3 A( A( ^
}4 I* x0 m5 B! R+ Y& A
mItemHolder.file_name.setText(mediaFile.getFileName());
. j& }% e+ a U! Z6 [/ [ mItemHolder.file_type.setText(mediaFile.getMediaType().name());
" g, t- r# L, Y ]! D d% i. u mItemHolder.file_size.setText(String.format("%.2f", (double) (mediaFile.getFileSize() / 1048576d)) + " MB");: a. x6 o8 }: B
mItemHolder.thumbnail_img.setImageBitmap(mediaFile.getThumbnail());6 H6 G$ @( ]* H8 w
mItemHolder.thumbnail_img.setTag(mediaFile); O4 V" x; V$ t+ d0 D
mItemHolder.itemView.setTag(index);
2 u4 _: Q, o% H+ W& l$ f( ^% z if (lastClickViewIndex == index) {
) J) T1 m* @0 q mItemHolder.itemView.setSelected(true);# b' y1 Q( ?4 H& F
} else {
" H$ ^4 \9 ?5 S7 ^. E( L mItemHolder.itemView.setSelected(false);
* k% g! _. J& A( _. i0 W) | }
" ~* J \2 l+ s" p5 [ mItemHolder.itemView.setOnClickListener(itemViewOnClickListener);
. G _8 ~/ x1 d. x) E! Z1 S }
* h4 i8 q) s* p }; |& |( i' b! _ K$ N+ C' g+ n" r
}4 {: l! r0 ~4 ^1 E" i
private View.OnClickListener itemViewOnClickListener = new View.OnClickListener() { g( k0 j. r! a) M, Y
@Override! `# F3 O8 ^: W) U* O4 j2 d
public void onClick(View v) {# r1 b1 L5 p- ?% [3 Y0 B
lastClickViewIndex = (int) (v.getTag());0 A3 h" b4 x; w1 L: z7 z. R
if (lastClickView != null && lastClickView != v) {: C! \5 E' d/ R% v! ~) x9 o
lastClickView.setSelected(false);( A! B' D3 T; q0 s. ^1 ~: A! u
}
2 d- B- }+ T8 L" Z4 u9 d' p6 _; ^ v.setSelected(true);" e& ^. k; x! i- V3 u
lastClickView = v;$ U! a H* m! ?' K( g# ?
MediaFile selectedMedia = mediaFileList.get(lastClickViewIndex);! G0 [) ?' |8 b& _
if (selectedMedia != null && mMediaManager != null) {1 z9 \5 Y1 o6 ], {$ y8 l; F+ l
addMediaTask(selectedMedia);
_2 r* [/ [+ S1 s( @6 {2 L }
' f+ I* u N( v$ B+ P7 p }6 M9 I! Y7 M# P3 |$ f* I Q
};/ }) T7 W$ [ T( h5 s
private void addMediaTask(final MediaFile mediaFile) {" p) s" U( c4 J
final FetchMediaTaskScheduler scheduler = mMediaManager.getScheduler();
) Y2 {7 E, y( c8 r6 A final FetchMediaTask task =
, B) ?3 b2 L" H+ t new FetchMediaTask(mediaFile, FetchMediaTaskContent.PREVIEW, new FetchMediaTask.Callback() {
3 \+ X, b3 W! L, ?% ~0 b# Y4 g$ f @Override
# Q8 H5 F8 ]4 k6 Q, D public void onUpdate(final MediaFile mediaFile, FetchMediaTaskContent fetchMediaTaskContent, DJIError error) {
- K4 T, `" s$ b( l& D/ w if (null == error) {% `* q% u. \, q g/ P
if (mediaFile.getPreview() != null) {5 }" Q" Z1 G; _5 W3 p
runOnUiThread(new Runnable() {
0 n" U6 R8 c V- g @Override, d/ S* o1 E8 Z) T& [0 M7 w- W
public void run() {
( \+ c1 m5 M% {9 b0 \" C* y4 }2 F final Bitmap previewBitmap = mediaFile.getPreview();/ e6 P3 G4 X0 p# \; L8 P
mImageView.setVisibility(View.VISIBLE);
' F& i5 r2 |* ^9 ^# L# w- Q mImageView.setImageBitmap(previewBitmap);( v c) Q( z' k9 p6 S
if (mediaFile.getMediaType() == MediaFile.MediaType.MP4){
9 r3 a! H+ T) i% t mLinearLayoutVideo.setVisibility(View.VISIBLE);; Y4 _' I; X; B' U. E
}else {
$ v8 V- u9 z2 c3 ] mLinearLayoutVideo.setVisibility(View.GONE);
3 {# B$ R1 D. f" D6 j1 s }- ]" z3 r1 \2 e+ g+ n
}3 ~7 |) F" A( v- Y
});
1 k1 g- F5 s$ x+ ^0 ~: y } else {
) ~) N& ~: Y" [* X) e showToasts("没有图像bitmap!");0 P0 r: e8 z0 s+ Q
}
& n' l! E' N% E# B7 Y } else {7 t% _% W, D' Z# Y: p
showToasts("查找图像内容失败: " + error.getDescription());4 W3 U% a: R b
}/ [0 E5 A& ]- W) a) ^ p/ {9 G, T
}6 W, u6 I4 J; N* Z" z' `
});
0 Q6 l/ _0 _1 n! c2 f1 p' X, I scheduler.resume(error -> {0 C2 I4 r# y1 y q( u5 U8 g
if (error == null) {
7 A' \; O2 |, W scheduler.moveTaskToNext(task);
" c0 S8 E% R1 H+ Z3 }7 Q$ c } else {
, [3 H- S2 l2 E6 }" ` showToasts("恢复计划程序失败: " + error.getDescription());
; c2 X3 u# c& @) P7 m" G }# k7 A% T2 w, ]" |) c8 U
});
" B0 I4 _ b; I! h { }4 U6 H- X- \# w4 x' R
//Listeners
" P! i( K; n. Z9 o% }+ O. ?" y private MediaManager.FileListStateListener updateFileListStateListener = state -> currentFileListState = state;( F/ v6 D! ?; l' h; a4 A5 D7 u1 _
6 }0 _' Y. \, O& T2 Q7 `& t private void deleteFileByIndex(final int index) {* l* o5 v5 s( f. {! \( m& `) A
ArrayList fileToDelete = new ArrayList();$ m( L/ V/ N J) w+ W; r! [
if (mediaFileList.size() > index) {2 j9 Q/ b; u2 ~5 v0 s; g3 y
fileToDelete.add(mediaFileList.get(index));" E8 r% _! b+ v! |/ s
mMediaManager.deleteFiles(fileToDelete, new CommonCallbacks.CompletionCallbackWithTwoParam, DJICameraError>() {
& [3 J% }" I2 N2 [# x' M' F! R @Override3 A, P% @5 C5 ]; c
public void onSuccess(List x, DJICameraError y) {; w5 c! N8 E# m: S5 M& t) z2 K+ o
DJILog.e(TAG, "Delete file success");
; C. e7 W. F h: S' N% V2 `" X) E runOnUiThread(new Runnable() {% Z) t. x3 @: y( H' W
public void run() {5 g3 H" f6 n9 \6 d& w5 h# X0 o
mediaFileList.remove(index);
$ h3 L; q$ v: h" O //Reset select view
" e3 y/ P$ O# I) L9 f, i' o& _ lastClickViewIndex = -1;$ s j: z1 [! S2 \# c# T$ H, ^- b
lastClickView = null;
" z6 `( u# ~; j7 B //Update recyclerView
6 A; c# v$ d9 Z" m$ x mListAdapter.notifyDataSetChanged();
, X9 _" M4 F- |$ I# Y6 a1 g$ T V }1 m" p, G9 T4 P5 d! a. v7 x) z# \
});; a3 R# z5 \" m/ s+ x' X: J$ {" d
}
J$ ?% h5 Y8 z @Override' L8 J7 ~8 i7 F9 @* u
public void onFailure(DJIError error) {: ]+ t/ J% Y5 \. D; Z: m
showToasts("删除失败");5 b- M, \, g" |- B3 k8 i
}
0 A; b0 R) `) e( \ });" v0 H# W, @- l! t1 A+ k7 M, E
}
+ q' x0 h: ]% \" t }
# E5 I# d0 `/ @+ _/ G private void downloadFileByIndex(final int index) {3 [+ C* c1 q. @ W( d/ H
if ((mediaFileList.get(index).getMediaType() == MediaFile.MediaType.PANORAMA); Q+ y: U! X i
|| (mediaFileList.get(index).getMediaType() == MediaFile.MediaType.SHALLOW_FOCUS)) {, w- f9 k* S9 O+ T+ H3 L6 K! [/ W; Z
return;0 I% Y$ t8 s# @- @: b
}" T- ^* u& P7 f* A. @$ Z
if ((mediaFileList.get(index).getMediaType() == MediaFile.MediaType.MOV) || (mediaFileList.get(index).getMediaType() == MediaFile.MediaType.MP4)) {) Q" d' o7 Z; t' e, [2 @
SavePath = MyStatic.FLY_FILE_VIDEO;/ z" N* G4 U- M- b* E
} else if (mediaFileList.get(index).getMediaType() == MediaFile.MediaType.JPEG) {* b7 l, ]/ m+ o+ x+ G4 n3 ]8 _
SavePath = MyStatic.FLY_FILE_PHOTO;
! j+ t3 o1 V0 F1 ^, |: d- |- k }
0 H/ t6 p( U; v) i9 _ File destDir = new File(FileUtil.checkDirPath(SavePath));7 y9 O; g4 x( C% m+ B' L9 k. d1 Q
mediaFileList.get(index).fetchFileData(destDir,null, new DownloadListener() {
, B; s) ]& Z, l* G; U3 V. q @Override
3 ?$ s& S" {9 B. a7 Y- R; l public void onFailure(DJIError error) {8 K0 u. _2 m9 Y# u/ D# J0 C( W
HideDownloadProgressDialog();! _4 d* ~4 J% [# C
showToasts("下载失败" + error.getDescription());2 \% I* f9 m! [: _, R/ @; U
currentProgress = -1;
6 |; r) j" `0 M1 X( Q( R }
W" j- R+ w. B- O/ u0 j; D @Override# t" z3 T- v9 }% s- w
public void onProgress(long total, long current) {
0 R* R: b" {6 N" V% ?3 ]% u }
4 H: ^+ M' k4 w0 @* b, o @Override" E z4 x& Y2 R, d
public void onRateUpdate(long total, long current, long persize) {/ K; R1 w- |4 ]8 d
int tmpProgress = (int) (1.0 * current / total * 100);
- A* T4 l' ^& ?: _4 ~9 M* ` if (tmpProgress != currentProgress) {( }& }/ X* L* r
mDownloadDialog.setProgress(tmpProgress);
k% u8 P# n4 S% z" r7 B currentProgress = tmpProgress;: q# Q) {/ E. o3 x. O- e1 t
}5 n* q X7 t- j6 I, i
}
( m0 \- @* {, l% Z @Override
5 {/ h; {0 F* i) {5 r/ Y3 j public void onRealtimeDataUpdate(byte[] bytes, long l, boolean b) {
8 n- W* Z2 n: z- D3 b }. V( ~' u7 S, R) ~7 `
@Override
6 O( l! I& K, Q' B1 E7 e$ m public void onStart() {
. `! }7 m9 ~" ^- p" y$ N0 r' Q currentProgress = -1;
% A4 C" T7 A3 d8 t ShowDownloadProgressDialog();
* F: f- d/ G8 H, @6 l* f }
' |6 I2 Q! w7 P6 ^) _0 y @Override$ x' Q) h7 B' B, Z* c8 f E
public void onSuccess(String filePath) {
3 Q* _3 |5 ? f) d9 W; Q HideDownloadProgressDialog();
/ o9 F) f+ L3 ?/ a1 Y showToasts("下载成功" + ":" + filePath);1 V4 M8 [' k9 j2 o$ V1 w: v0 r9 v
currentProgress = -1;4 C" w3 t6 i( P! Q; n& E
}
) T" `, Q4 Q B% t8 u });$ O; S8 ^& V) k( Q! @3 l
// mediaFileList.get(index).fetchFileByteData(0, new DownloadListener() {3 O% ~& b& d! [
// @Override3 D& M& \- o/ S$ d; t
// public void onStart() {& J; O5 H0 Y# d* }, r
// currentProgress = -1;" p& E/ v& ~7 Q9 i8 c7 N
// ShowDownloadProgressDialog();3 Q3 i4 B( Z- N' ^, t; D$ b
// }- N; u! g- \5 ]2 ?/ A6 n) L
//
: o- V6 K/ }1 K. T* l. y// @Override% Q( l- z" z. `; y7 d
// public void onRateUpdate(long total, long current, long persize) { E* l _8 b7 C9 b A+ [
// int tmpProgress = (int) (1.0 * current / total * 100);" T3 B( S% L3 ~8 A
// if (tmpProgress != currentProgress) {
* a3 Q# k; ^6 D% {. A: q) O# H- P// mDownloadDialog.setProgress(tmpProgress);
5 S7 p+ T7 Y3 ?$ d6 ?// currentProgress = tmpProgress;# K( M6 l u8 `" `, }& }' W; f
// }) k6 N: o6 d/ ]
// }# m+ c5 X: D+ V- A6 {
//
$ Y: V8 ~# K- h) w; |4 ^// @Override
4 L: K8 L8 W1 T6 T' O" Z9 K// public void onRealtimeDataUpdate(byte[] bytes, long l, boolean b) {
& g: h9 ^6 a0 ~// byteToFile(bytes, FileUtil.checkDirPath(SavePath)+mediaFileList.get(index).getFileName());
1 ]& y. m1 O& X* ]! `0 @" X7 l. x// }
. O+ z; I4 D8 [& O! {//
5 W4 t1 i9 f) G% }# q# V ^% Y, K9 ~// @Override
6 X& Z. l3 f; z F: y9 ~// public void onProgress(long l, long l1) {
6 X" x& Q# q% B$ M0 A& d//
0 Z( J: x; M7 I8 l// }
, m% A' H g9 @//
, b. u: h) y5 j' ?$ R- ^ b. ^// @Override4 @! m# B& d9 j% H+ v6 ?
// public void onSuccess(String s) {& \" Q7 [' Q2 o' g) ^
// HideDownloadProgressDialog();+ t% M* T" n7 k
// showToasts("下载成功" + ":" + s);
) [& P# a' j/ \5 [, }1 I// currentProgress = -1;$ L, T6 ^- @0 w N6 Z$ A
// }
/ d+ X/ J7 J' e+ Y: a//
, ]4 @# b. Q! a( Y* F" a$ d// @Override
5 F. h5 Q) O: P! Z2 V* b. n9 N// public void onFailure(DJIError djiError) {: D x: x7 V* t) f
//
. k9 Y: h3 B! F; m// }
" X& F4 _" B3 A* Y- ~5 Z, h% C// });: o6 j, q: C# e c) K4 X! B* O
}
* j/ a# X2 ?8 g public static void byteToFile(byte[] bytes, String path)
0 T6 s, k$ J- ]9 Z1 A {0 G( n* s" j ~2 e0 [0 Y' J! |
try
" z; P. C# C; t C1 E {
+ `! p9 v4 Q! j! w6 Y // 根据绝对路径初始化文件$ }! S3 @2 ] I+ [8 }- i
File localFile = new File(path);& c% I% T7 k. p$ l
if (!localFile.exists()). r" ?' R( X1 |# L
{
+ D% s/ n1 |0 I! b localFile.createNewFile();& T$ n/ O% E; j4 w- S7 }- A
}& i/ a% O" \8 s% b
// 输出流
9 Z! U: K6 T1 f+ }! b2 I+ k r' p0 [ OutputStream os = new FileOutputStream(localFile);
; M1 @. a4 R# R. g8 j! X1 p' g' P4 i os.write(bytes);
, x) p- t- w1 j os.close();
2 y( G$ F: X" g9 H3 Q; s }) [3 M% Q1 ^& ]6 b( f& r8 `9 x
catch (Exception e)
% K4 B6 Y( @9 v* m& o, f {
9 G! o/ i" u# G& U e.printStackTrace();- P) Q' t+ P7 J# ]" Z$ n5 M& z2 h; d
}
7 U1 }" f7 K" a }' q* r8 w5 C# u$ P
private void playVideo() {
0 h; p6 {4 O5 v% s mImageView.setVisibility(View.INVISIBLE);
$ w3 W7 R; @; E" y MediaFile selectedMediaFile = mediaFileList.get(lastClickViewIndex);" o/ A7 k3 d* F& S/ G6 f" g/ [6 R, Z
if ((selectedMediaFile.getMediaType() == MediaFile.MediaType.MOV) || (selectedMediaFile.getMediaType() == MediaFile.MediaType.MP4)) {; @# s p2 W, F4 `
mMediaManager.playVideoMediaFile(selectedMediaFile, error -> {& w, M$ n, [/ R+ A
if (null != error) {6 N$ G$ R) N; }
showToasts("播放失败 " + error.getDescription());+ i: M$ Q1 x, K: e; s/ Z# \
} else { c* ]* e* r- x! u# O9 f7 P+ K
DJILog.e(TAG, "播放成功");: }8 E$ \0 S9 s H$ p
runOnUiThread(new Runnable() {" Q/ `2 I4 e% v; K2 E: y: k
@Override
& E+ d. e' B$ G4 }) E, f" { public void run() {' c, O# X( a: s7 X; E+ b* n) H
mImageViewVideoPlay.setEnabled(false);
9 p& @+ N ~/ w6 X mImageViewVideoPause.setEnabled(true);
. B/ X; n) e& `7 k1 P( P( N) d }3 r7 V W! l1 C. P& c( D
});: B2 p0 M! l, l E' D
}
! O- u! R$ k) Y; I0 u4 t6 | });
4 u1 @ A5 p- `/ V6 Z0 t% z }
+ ~& S6 d& o, G8 U }/ _2 b/ W( T4 m, c1 G) ^
@OnClick({R.id.img_back, R.id.img_delete, R.id.img_download, R.id.img_upload, R.id.img_video_play,3 ]) Z( U# w# a, I5 M, Z
R.id.img_video_pause, R.id.img_video_stop})
2 P7 H* X; o! B3 D4 }8 Q* q$ n @Override
. ?2 r- V" y3 i- _2 E public void onClick(View v) {
) F9 ~4 s; W4 s switch (v.getId()) {
7 l' r) T2 i. o \& h W' V2 o case R.id.img_back:/ i) K* q) O3 Z6 k7 q
FileManagementActivity.this.finish();! _& V+ q4 j3 C* a
break;
! x- g" \1 X' z" Z8 F case R.id.img_delete:/ g- _. c, U) Y# v4 x& V
if (lastClickViewIndex >= 0) {
1 G/ ^' V) N; M& [) z. H! Q, c# r& V. U deleteFileByIndex(lastClickViewIndex);/ v& Y' q L& B7 S; ~: i2 B
} else {
9 A6 C- U. W) ]+ w% L* n% a4 A showToasts("请先选择文件。");
% w \; [. g" b }
+ c6 H& F6 D- e* `' U- I break;
, F/ s1 D: R" [8 d8 q case R.id.img_download:
2 y+ W. e# Z* C* d' D( g if (lastClickViewIndex >= 0) {: f9 |( l/ z7 Z4 v3 V* ?$ Z
downloadFileByIndex(lastClickViewIndex);
, X% g4 |4 J6 }" C/ M# a2 @ } else {
" `7 R1 G3 p. W+ }6 t/ H. L0 ` showToasts("请先选择文件。");
( d* ]- F2 c& O$ R2 q' d' h0 _* ^& W7 s( G }: f* Q8 ?/ r& t5 J
break;
( [/ f F3 R, p' ^. t5 Z" R, o case R.id.img_upload:
$ d2 K" u9 ~* E, V) X( z$ U) m if (lastClickViewIndex >= 0) {
* `# J' J1 I+ d3 q uploadFileByIndex(lastClickViewIndex);' d/ y9 J9 _$ i/ f
} else {
$ }: } Z! g3 w# S& V) B* }1 d showToasts("请先选择文件。");
5 E2 j% M- z( B2 u }1 b! W/ w5 I- W9 r& u; q) {5 Y
break;
* K( C, D0 `/ C# ]' r case R.id.img_video_play:
: A- d$ |. G( g% | if (state.getPlaybackStatus() == MediaFile.VideoPlaybackStatus.STOPPED){
: M+ h, t3 v3 j: l, o- i+ g playVideo();
) q5 z+ F' l C. o: U* j }else if (state.getPlaybackStatus() == MediaFile.VideoPlaybackStatus.PAUSED){9 i! R, p* i) u$ G5 [2 I
mMediaManager.resume(error -> {$ [ `1 L5 D8 G' j, e9 t3 u5 T
if (null != error) {8 B1 n0 ^) H) j/ `0 u" ~* z; t, k
showToasts("继续播放失败:" + error.getDescription());' ~! `! u+ M# p, n" v# ~. w
} else {
. \4 }' v, z6 D. o% Y5 V DJILog.e(TAG, "继续播放成功");
, y# m o' A I( |" g runOnUiThread(new Runnable() {
/ a0 ^3 B( I' i/ o: } @Override
! O# M7 ~" k1 Z' r5 U public void run() {2 J$ O- T5 [ r- l$ K5 ]
mImageViewVideoPlay.setEnabled(false);! S1 t6 |5 x( m, @" L5 y0 h
mImageViewVideoPause.setEnabled(true);$ A: i% W- ~9 O _, R9 _1 f. ~
}
1 @- Q0 |9 ^8 ^5 ] });
' x2 m9 C5 |+ v9 z; m3 y3 c/ Q }
( n$ `6 C ]* t2 E7 O0 _ r });
) z: e: l( {; z- C6 f }
- l; _/ t7 K0 Z break;
0 h# a9 M1 J5 H( R/ @ case R.id.img_video_pause:" N/ k% ^" F5 U) o
mMediaManager.pause(error -> {! W" ^5 k$ W- g1 s; z
if (null != error) {
% ~$ R4 F3 V4 a7 n showToasts("暂停播放失败:" + error.getDescription());
7 S- R& ^' o6 E } else {
! e, F$ p# S' h. K8 @% t5 F DJILog.e(TAG, "暂停播放成功");
4 S: M2 F# U, j; b2 x0 ~! B+ T runOnUiThread(new Runnable() {2 X8 |2 G& b* T$ D* z6 N% @
@Override0 V0 z; [1 {% q) S& R
public void run() {
# w6 w( n* U7 R. m1 U$ R' c mImageViewVideoPlay.setEnabled(true);4 e }+ k% z; Y1 X9 Q8 s, _* a
mImageViewVideoPause.setEnabled(false);
' R% ?" o t1 k8 u9 u7 V: j% _ }( e; v3 e. c0 }/ n- G1 U! A+ O* L2 `
});
* l( |' S# b, Q: c- R+ [& F. \+ Q! C }
8 M# A4 k( _3 \2 _/ ~& ?! ` });" R! `5 \6 s; j* J$ H! M R7 I9 `7 w
break;
- q7 f; R* u$ @7 L. n: m$ l case R.id.img_video_stop:) ^2 ^2 f) k5 U1 O: M$ {
mMediaManager.stop(error -> {
0 A' z) F) N; \ `9 E$ ?% t0 b" w if (null != error) {
5 a, z! i3 a% V6 {9 M# p- V showToasts("停止播放失败:" + error.getDescription());
% W- i( v0 e& H2 q$ T7 ? } else {1 S/ t5 P2 S+ B1 }
DJILog.e(TAG, "停止播放成功");
# J- s+ Z5 r) z }
+ {. [/ T W5 {$ s4 x A% z });3 {9 T0 W+ ]# y- P2 O X0 c
break;2 c" }, F n5 ?8 T' U7 A t
}
4 b. B6 ~+ M8 [ }5 F! D+ i8 M4 H2 ^! W
private void uploadFileByIndex(int index) {4 b- B# e' n3 C8 i" ]6 A2 ^+ ^
if ((mediaFileList.get(index).getMediaType() == MediaFile.MediaType.MOV) || (mediaFileList.get(index).getMediaType() == MediaFile.MediaType.MP4)) {9 m% }7 y8 b! s& q( _1 ]6 E
showProgressDialog("正在上传");
5 T( E/ a4 d& \ new Thread(new Runnable() {
/ ?* W0 S' j" X8 k3 d# S @Override
9 H# ]+ |+ Z# X E public void run() {
8 @0 V/ x. ]/ {# C5 A% n' e+ ^ boolean isConnect = sftp.connect().isConnected();6 {9 }. G( P) ` v% Q/ }
if (isConnect){
2 I0 }/ _% p+ Z7 x8 D2 }5 _- h boolean isUpdate = sftp.uploadFile("/mnt/uavFtpFolder/",mediaFileList.get(index).getFileName(), FLY_FILE_VIDEO, mediaFileList.get(index).getFileName());
0 O* u3 A3 \+ `# |/ F if (isUpdate){; S* r# ] I$ z. N' S/ |
runOnUiThread(new Runnable() {
( F5 {) r8 ~, W6 b0 j B, | @Override
& K; t2 L7 x3 [% d, d/ Q/ v public void run() {
}# j, b( H; U% P3 K- B removeProgressDialog();
) D: ~* @ ^* a0 \3 {! O http.getHttp(GET_VIDEO_INFO+"?fileName="+mediaFileList.get(index).getFileName(),"GET");* ]5 P O7 s5 D
}( [, b8 T9 Y8 P F# o1 b) i5 C
});
3 d. O6 [, q4 p# t) Z- A& E sftp.disconnect();6 k1 s* `- I7 z" ]
}else {
8 R5 D( h' d( `2 G runOnUiThread(new Runnable() {) N/ P0 f4 W& H( Z+ e* i4 j% d
@Override9 @1 q3 n- |3 B" y* l9 ?
public void run() {
' U" F, G( }+ s showErrorTip("上传失败");
0 O R9 s' n' E4 i$ P removeProgressDialog();+ C3 U1 N; U) E' J
}2 r# o7 ]' G; Y$ _/ Y8 i3 e* I! V
});& G, Y+ W; z& x: k' T$ K
}
; _% t+ a9 m5 e0 \2 G$ t: J }else {/ @) ]+ x" K' Z3 W4 d
runOnUiThread(new Runnable() {
& }0 {5 V; Q `& H @Override
1 S7 ^! T3 c- S- y: e9 ]* g& u public void run() {: p; a7 z3 w" F. i
showErrorTip("服务器连接失败");
4 ?& ^7 Z1 f Y' p: d" ^ removeProgressDialog();
! i8 P$ ~; C+ c3 T }& c7 l- H4 l/ P2 ^5 e. I- a
});4 Q7 n% r, _4 Y& W. }' `3 C9 H
}
- r" l2 d0 _8 {: l7 O }
) \6 R3 V9 x- D n3 [! o Q3 a }).start();
7 W- V3 I+ H0 E! m9 s. F3 Q3 ? }else {
3 H. \) g. @1 D; G, V# N showToasts("当前仅支持视频上传,请选择视频文件!");
( W; T7 K' S% t# G1 Y }' E$ q1 c9 n) D6 h4 H5 _
}/ v$ B% z& Q9 M8 R
private boolean isMavicAir2() {
+ p: p3 V$ g2 L/ x3 m N% [9 l BaseProduct baseProduct = ReceiverApplication.getProductInstance();
4 m4 ?, k( c( q6 m' T if (baseProduct != null) {+ ]- B, V, t8 k' i
return baseProduct.getModel() == Model.MAVIC_AIR_2;6 B3 X0 v$ }1 ]4 L1 f$ n- L
}
/ L" x; j. ?- _, | return false;; j% u3 i' |' L) b& {7 L
}
; r' j& R* V q5 V private boolean isM300() {
6 G# d( l2 L, p& ^+ W# w BaseProduct baseProduct = ReceiverApplication.getProductInstance();
0 U* V- I2 l* w* U3 p' o if (baseProduct != null) {
, p" }: l: `8 K- u- H" O return baseProduct.getModel() == Model.MATRICE_300_RTK;
# F1 \" D1 X6 Z$ r; N. P: G' V }
( y. b8 ^9 ^+ {- h0 x return false;
d/ R4 V: H6 b' l5 U }
2 g3 _5 \& d3 ]" A, D* Q5 H! Y}( c$ G& ?4 H. R' E8 x, w! p
运行后界面如下:4 g. z7 l5 {% W. j; h
dwx4hpo5o5k64023083506.jpg
# {& ^8 p4 Q& f+ T F/ M: e6 y4 P$ W7 u5 X" O. C# o# R5 ~: Q8 [
uiwobraut0x64023083606.png
0 W( |6 Q7 Q l" {4 K往期推荐LabVIEW OCR 实现车牌识别$ C/ j7 a+ k: {/ f/ D3 D! U( ?
和12岁小同志搞创客开发:有意思的激光切割技术0 o3 k2 O9 y* \0 N; N4 g
JavaScript+TensorFlow.js让你在视频中瞬间消失
8 i3 N6 U$ U# v' N Q* B& M3 O8 Y1 a使用OpenCV测量图像中物体之间的距离4 q6 u* M7 I& U
全网仅此一篇:工业级压力传感器设计及实现- J9 n; K- S/ f$ P+ A" k7 O% T' e, d
; _0 {5 \% E3 o
qye2bh0mhdb64023083706.jpg
- v1 m, p4 m/ s5 V/ a6 l
cnnb1olyf5d64023083806.gif
5 g$ s4 s9 P# [. ~4 s+ \点击阅读原文,更精彩~ |
|