"); //-->
上一篇文章(基于Mobile SDK V4版固件开发大疆无人机手机端遥控器(1))因为时间原因介绍了一部分内容,如果已经完成上一篇内容的操作就可以进行下面功能方面的制作了。自己开发的APP功能不是很多,但是已经将大疆无人机的常用功能进行了结合,同大家一起进行学习~
1
应用程序激活与绑定如果在中国使用DJI飞行器固件,则需要使用该用户的DJI帐户激活控制DJI飞行器的移动应用程序。这将确保大疆能根据飞行器的地理位置和用户个人资料,为飞行器配置正确的地理空间信息和飞行功能集。激活系统的主要是:
中国用户必须在每三个月至少登录一次DJI帐户以遍激活应用程序。
激活信息将存储在应用程序中,直到用户注销为止。
登录DJI帐号需要连接互联网。
在中国境外,SDK会自动激活应用程序,无需用户登录。
另外,中国用户必须将飞机绑定到DJI官方app中的用户帐户。这仅需要一次。如果未激活应用程序,未绑定飞机(如果需要)或使用旧版SDK(<4.1),则会禁用相机视频流,并且飞行限制在直径100m和高度30m的区域中,以确保飞机停留在视线范围内。
2
为应用程序创建UI编写MApplication、ReceiverApplication和RegistrationActivity文件(此处粘贴部分代码)。
public class MApplication extends MultiDexApplication {
private ReceiverApplication receiverApplication;
@Override
protected void attachBaseContext(Context paramContext) {
super.attachBaseContext(paramContext);
CrashHandler.getInstance().init(this);
Helper.install(MApplication.this);
if (receiverApplication == null) {
receiverApplication = new ReceiverApplication();
receiverApplication.setContext(this);
}
}
@Override
public void onCreate() {
super.onCreate();
receiverApplication.onCreate();
}
}
上面的代码实现了绑定当前APP,将后续需要用到的类函数封装到ReceiverApplication 中,在ReceiverApplication 中也能够进行账户登录的操作。
public class ReceiverApplication extends MultiDexApplication {
public static final String FLAG_CONNECTION_CHANGE = "activation_connection_change";
private static BaseProduct mProduct;
public Handler mHandler;
private Application instance;
public void setContext(Application application) {
instance = application;
}
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
Helper.install(this);
}
@Override
public Context getApplicationContext() {
return instance;
}
public ReceiverApplication() {
}
/**
* This function is used to get the instance of DJIBaseProduct.
* If no product is connected, it returns null.
*/
public static synchronized BaseProduct getProductInstance() {
if (null == mProduct) {
mProduct = DJISDKManager.getInstance().getProduct();
}
return mProduct;
}
public static synchronized Aircraft getAircraftInstance() {
if (!isAircraftConnected()) return null;
return (Aircraft) getProductInstance();
}
public static synchronized Camera getCameraInstance() {
if (getProductInstance() == null) return null;
Camera camera = null;
if (getProductInstance() instanceof Aircraft){
camera = ((Aircraft) getProductInstance()).getCamera();
} else if (getProductInstance() instanceof HandHeld) {
camera = ((HandHeld) getProductInstance()).getCamera();
}
return camera;
}
public static boolean isAircraftConnected() {
return getProductInstance() != null && getProductInstance() instanceof Aircraft;
}
public static boolean isHandHeldConnected() {
return getProductInstance() != null && getProductInstance() instanceof HandHeld;
}
public static boolean isProductModuleAvailable() {
return (null != ReceiverApplication.getProductInstance());
}
public static boolean isCameraModuleAvailable() {
return isProductModuleAvailable() &&
(null != ReceiverApplication.getProductInstance().getCamera());
}
public static boolean isPlaybackAvailable() {
return isCameraModuleAvailable() &&
(null != ReceiverApplication.getProductInstance().getCamera().getPlaybackManager());
}
@Override
public void onCreate() {
super.onCreate();
mHandler = new Handler(Looper.getMainLooper());
/**
* When starting SDK services, an instance of interface DJISDKManager.DJISDKManagerCallback will be used to listen to
* the SDK Registration result and the product changing.
*/
//Listens to the SDK registration result
DJISDKManager.SDKManagerCallback mDJISDKManagerCallback = new DJISDKManager.SDKManagerCallback() {
//Listens to the SDK registration result
@Override
public void onRegister(DJIError error) {
if (error == DJISDKError.REGISTRATION_SUCCESS) {
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
@Override
public void run() {
// ToastUtils.showToast(getApplicationContext(), "注册成功");
// Toast.makeText(getApplicationContext(), "注册成功", Toast.LENGTH_LONG).show();
// loginAccount();
}
});
DJISDKManager.getInstance().startConnectionToProduct();
} else {
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
@Override
public void run() {
// ToastUtils.showToast(getApplicationContext(), "注册sdk失败,请检查网络是否可用");
// Toast.makeText(getApplicationContext(), "注册sdk失败,请检查网络是否可用", Toast.LENGTH_LONG).show();
}
});
}
Log.e("TAG", error.toString());
}
@Override
public void onProductDisconnect() {
Log.d("TAG", "设备连接");
notifyStatusChange();
}
@Override
public void onProductConnect(BaseProduct baseProduct) {
Log.d("TAG", String.format("新设备连接:%s", baseProduct));
notifyStatusChange();
}
@Override
public void onProductChanged(BaseProduct baseProduct) {
}
@Override
public void onComponentChange(BaseProduct.ComponentKey componentKey, BaseComponent oldComponent,
BaseComponent newComponent) {
if (newComponent != null) {
newComponent.setComponentListener(new BaseComponent.ComponentListener() {
@Override
public void onConnectivityChange(boolean isConnected) {
Log.d("TAG", "设备连接已更改: " + isConnected);
notifyStatusChange();
}
});
}
Log.d("TAG",
String.format("设备改变 key:%s, 旧设备:%s, 新设备:%s",
componentKey,
oldComponent,
newComponent));
}
@Override
public void onInitProcess(DJISDKInitEvent djisdkInitEvent, int i) {
}
@Override
public void onDatabaseDownloadProgress(long l, long l1) {
}
};
//Check the permissions before registering the application for android system 6.0 above.
int permissionCheck = ContextCompat.checkSelfPermission(getApplicationContext(), android.Manifest.permission.WRITE_EXTERNAL_STORAGE);
int permissionCheck2 = ContextCompat.checkSelfPermission(getApplicationContext(), android.Manifest.permission.READ_PHONE_STATE);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M || (permissionCheck == 0 && permissionCheck2 == 0)) {
//This is used to start SDK services and initiate SDK.
DJISDKManager.getInstance().registerApp(getApplicationContext(), mDJISDKManagerCallback);
// ToastUtils.showToast(getApplicationContext(), "正在注册,请等待...");
// Toast.makeText(getApplicationContext(), "正在注册,请等待...", Toast.LENGTH_LONG).show();
} else {
// ToastUtils.showToast(getApplicationContext(), "请检查是否授予了权限");
// Toast.makeText(getApplicationContext(), "请检查是否授予了权限。", Toast.LENGTH_LONG).show();
}
}
private void notifyStatusChange() {
mHandler.removeCallbacks(updateRunnable);
mHandler.postDelayed(updateRunnable, 500);
}
private Runnable updateRunnable = new Runnable() {
@Override
public void run() {
Intent intent = new Intent(FLAG_CONNECTION_CHANGE);
getApplicationContext().sendBroadcast(intent);
}
};
}
上面的代码是对BaseProduct、Aircraft和Camera类进行实例化,在后续使用中不用再去进行重复的实例化工作,减少内存的消耗。
@Layout(R.layout.activity_registration)
public class RegistrationActivity extends BaseActivity implements View.OnClickListener{
private static final String TAG = RegistrationActivity.class.getName();
private AtomicBoolean isRegistrationInProgress = new AtomicBoolean(false);
private static final String[] permissions = new String[]{
Manifest.permission.BLUETOOTH,
Manifest.permission.BLUETOOTH_ADMIN,
Manifest.permission.VIBRATE,
Manifest.permission.INTERNET,
Manifest.permission.ACCESS_WIFI_STATE,
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.ACCESS_NETWORK_STATE,
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.CHANGE_WIFI_STATE,
Manifest.permission.RECORD_AUDIO,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.READ_PHONE_STATE,
};
@Override
public void initViews() {
isPermission();
IntentFilter filter = new IntentFilter();
filter.addAction(ReceiverApplication.FLAG_CONNECTION_CHANGE);
registerReceiver(mReceiver, filter);
}
@Override
public void initDatas() {
startSDKRegistration();
}
@Override
protected void requestData() {
}
@Override
protected void onResume() {
super.onResume();
}
private void isPermission() {
requestRunTimePermission(permissions, new IPermission() {
@Override
public void onGranted() {
}
@Override
public void onDenied(List<String> deniedPermissions) {
}
});
}
//无人机首次注册
private void startSDKRegistration() {
if (isRegistrationInProgress.compareAndSet(false, true)) {
AsyncTask.execute(new Runnable() {
@Override
public void run() {
// showToasts("注册中,请等待...");
DJISDKManager.getInstance().registerApp(getApplicationContext(), new DJISDKManager.SDKManagerCallback() {
@Override
public void onRegister(DJIError djiError) {
if (djiError == DJISDKError.REGISTRATION_SUCCESS) {
DJILog.e("App 注册", DJISDKError.REGISTRATION_SUCCESS.getDescription());
DJISDKManager.getInstance().startConnectionToProduct();
// showToasts("注册成功");
loginAccount();
} else {
showToasts("注册sdk失败,请检查网络是否可用");
}
Log.v(TAG, djiError.getDescription());
}
@Override
public void onProductDisconnect() {
Log.d(TAG, "产品断开连接");
// showToasts("产品断开连接");
}
@Override
public void onProductConnect(BaseProduct baseProduct) {
Log.d(TAG, String.format("新产品连接:%s", baseProduct));
// showToasts("产品连接");
}
@Override
public void onProductChanged(BaseProduct baseProduct) {
}
@Override
public void onComponentChange(BaseProduct.ComponentKey componentKey, BaseComponent oldComponent,
BaseComponent newComponent) {
if (newComponent != null) {
newComponent.setComponentListener(new BaseComponent.ComponentListener() {
@Override
public void onConnectivityChange(boolean isConnected) {
Log.d(TAG, "组件连接已更改: " + isConnected);
}
});
}
Log.d(TAG, String.format("改变设备Key:%s, " + "旧设备:%s, " + "新设备:%s",
componentKey, oldComponent, newComponent));
}
@Override
public void onInitProcess(DJISDKInitEvent djisdkInitEvent, int i) {
}
@Override
public void onDatabaseDownloadProgress(long l, long l1) {
}
});
}
});
}
}
protected BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
refreshSDKRelativeUI();
}
};
private void refreshSDKRelativeUI() {
BaseProduct mProduct = ReceiverApplication.getProductInstance();
if (null != mProduct && mProduct.isConnected()) {
Log.v(TAG, "刷新SDK: True");
mButtonFlightTask.setEnabled(true);
mButtonSettingRoute.setEnabled(true);
mButtonFileManagement.setEnabled(true);
} else {
Log.v(TAG, "刷新SDK: False");
// mButtonOpen.setEnabled(false);
// mButtonSettingRoute.setEnabled(false);
// mButtonFileManagement.setEnabled(false);
// startSDKRegistration();
}
}
protected long exitTime; //记录第一次点击时的时间
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK
&& event.getAction() == KeyEvent.ACTION_DOWN) {
if ((System.currentTimeMillis() - exitTime) > 2000) {
showToast("再按一次退出程序");
exitTime = System.currentTimeMillis();
} else {
RegistrationActivity.this.finish();
System.exit(0);
}
return true;
}
return super.onKeyDown(keyCode, event);
}
private void loginAccount() {
UserAccountManager.getInstance().logIntoDJIUserAccount(this, new CommonCallbacks.CompletionCallbackWith<UserAccountState>() {
@Override
public void onSuccess(UserAccountState userAccountState) {
runOnUiThread(new Runnable() {
@Override
public void run() {
mButtonFlightTask.setEnabled(true);
mButtonSettingRoute.setEnabled(true);
mButtonFileManagement.setEnabled(true);
}
});
}
@Override
public void onFailure(DJIError djiError) {
}
});
}
}
上面的代码就要进行第一次注册登录了,当然你不需要自己去设计登录注册页面,大疆会调取自己的登录注册页面供你使用。
安装提示注册登录即可。
上面的这些做完后,恭喜你!现在,您的移动应用程序和飞机可以在中国使用而没有任何问题。换句话说,您的应用程序现在可以看到飞机的视频流,并且飞行将不仅限于直径为100m和高度为30m的圆柱体区域。
3
飞行界面使用虽然说可以正常飞行了,但是飞行需要设计飞行界面。那么创建一下飞行界面的UI及逻辑处理文件。逻辑处理文件中包含了获取飞机的实时姿态信息,代码中有注释内容,描述的内容就不多说了。
导入UX SDK依赖
上一节有说过集成部分,其中内容有导入UxSDk 的操作,这里再顺便提一下。再build.gradle文件中加入implementation "com.dji:dji-uxsdk:4.16"依赖,等待安装即可。
设计界面UI
创建MainActivity文件及activity_main.xml。
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:custom="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/background_blue"
android:id="@+id/root_view"
tools:context=".ui.MainActivity">
<!-- Widget to see first person view (FPV) -->
<RelativeLayout
android:id="@+id/fpv_container"
android:layout_width="match_parent"
android:layout_height="match_parent">
<dji.ux.widget.FPVWidget
android:id="@+id/fpv_widget"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerInParent="true"
custom:sourceCameraNameVisibility="false" />
</RelativeLayout>
<dji.ux.widget.FPVOverlayWidget
android:id="@+id/fpv_overlay_widget"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="40dp"
android:layout_toRightOf="@+id/TakeOffReturnPanel"
android:layout_toLeftOf="@+id/CameraCapturePanel"
android:layout_below="@+id/camera"
tools:ignore="RtlHardcoded">
<dji.ux.widget.RadarWidget
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"/>
</RelativeLayout>
<!--Take off and return home buttons on left -->
<LinearLayout
android:id="@+id/TakeOffReturnPanel"
android:layout_width="40dp"
android:layout_height="wrap_content"
android:layout_marginLeft="12dp"
android:layout_marginBottom="4dp"
android:layout_marginTop="50dp"
android:orientation="vertical"
android:gravity="center">
<ImageView
android:id="@+id/img_show_back"
android:layout_width="match_parent"
android:layout_height="38dp"
android:src="@mipmap/ic_back_36dp"
android:layout_marginBottom="10dp"></ImageView>
<dji.ux.widget.TakeOffWidget
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginBottom="5dp" />
<dji.ux.widget.ReturnHomeWidget
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp"/>
<ImageView
android:id="@+id/img_live"
android:layout_width="35dp"
android:layout_height="35dp"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp"
android:src="@mipmap/ic_live_write_36dp"></ImageView>
</LinearLayout>
<FrameLayout
android:layout_width="150dp"
android:layout_height="100dp"
android:id="@+id/secondary_video_view"
android:layout_marginLeft="12dp"
android:layout_marginBottom="7dp"
android:layout_marginTop="50dp"
android:layout_alignParentLeft="true"
android:layout_below="@+id/TakeOffReturnPanel"
android:background="@color/black">
<dji.ux.widget.FPVWidget
android:id="@+id/secondary_fpv_widget"
android:layout_width="match_parent"
android:layout_height="match_parent"
custom:sourceCameraNameVisibility="false"
custom:videoSource="secondary"/>
</FrameLayout>
<dji.ux.workflow.CompassCalibratingWorkFlow
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<dji.ux.workflow.CameraSensorCleaningWorkFlow
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<dji.ux.widget.RemainingFlightTimeWidget
android:layout_alignParentTop="true"
android:layout_marginTop="18dp"
android:layout_width="match_parent"
android:id="@+id/remaining_flight_time"
android:background="@color/transparent"
android:layout_height="20dp"/>
<LinearLayout
android:id="@+id/camera"
android:layout_alignParentRight="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/signal"
android:layout_marginTop="15dp"
android:background="@color/dark_gray"
android:orientation="horizontal">
<dji.ux.widget.config.CameraConfigISOAndEIWidget
android:layout_width="50dp"
android:layout_height="25dp"/>
<dji.ux.widget.config.CameraConfigShutterWidget
android:layout_width="50dp"
android:layout_height="25dp"/>
<dji.ux.widget.config.CameraConfigApertureWidget
android:layout_width="50dp"
android:layout_height="25dp"/>
<dji.ux.widget.config.CameraConfigEVWidget
android:layout_width="50dp"
android:layout_height="25dp"/>
<dji.ux.widget.config.CameraConfigWBWidget
android:layout_width="60dp"
android:layout_height="25dp"/>
<dji.ux.widget.config.CameraConfigStorageWidget
android:layout_width="108dp"
android:layout_height="25dp"/>
<dji.ux.widget.config.CameraConfigSSDWidget
android:layout_width="125dp"
android:layout_height="25dp"/>
</LinearLayout>
<LinearLayout
android:id="@+id/camera2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:layout_below="@id/camera"
android:layout_toLeftOf="@+id/CameraCapturePanel"
android:background="@color/dark_gray"
android:orientation="horizontal">
<dji.ux.widget.SpeakerWidget
android:layout_width="35dp"
android:layout_height="35dp"/>
<dji.ux.widget.AutoExposureLockWidget
android:layout_width="35dp"
android:layout_height="35dp"/>
<dji.ux.widget.FocusModeWidget
android:layout_width="35dp"
android:layout_height="35dp"/>
<dji.ux.widget.FocusExposureSwitchWidget
android:layout_width="35dp"
android:layout_height="35dp"/>
<dji.ux.widget.BeaconWidget
android:layout_width="35dp"
android:layout_height="35dp"/>
<dji.ux.widget.SpotlightWidget
android:layout_width="35dp"
android:layout_height="35dp"/>
<dji.ux.widget.AccessLockerWidget
android:layout_width="35dp"
android:layout_height="35dp"/>
</LinearLayout>
<dji.ux.widget.ManualFocusWidget
android:layout_alignTop="@+id/camera2"
android:layout_toLeftOf="@+id/camera2"
android:layout_width="50dp"
android:layout_height="210dp"
tools:ignore="RtlHardcoded"/>
<dji.ux.widget.MapWidget
android:id="@+id/map_widget"
android:layout_width="150dp"
android:layout_height="100dp"
android:layout_marginRight="12dp"
android:layout_marginBottom="12dp"
android:layout_alignParentRight="true"
android:layout_alignParentBottom="true"/>
<!-- Everything below this line will appear on top of the full-screen map widget -->
<dji.ux.widget.controls.CameraControlsWidget
android:id="@+id/CameraCapturePanel"
android:layout_alignParentRight="true"
android:layout_below="@id/camera"
android:layout_width="50dp"
android:layout_height="213dp"
android:layout_marginTop="5dp"
tools:ignore="RtlHardcoded"/>
<!-- Widgets in top status bar -->
<LinearLayout
android:id="@+id/signal"
android:layout_width="match_parent"
android:layout_height="25dp"
android:background="@color/dark_gray"
android:orientation="horizontal">
<dji.ux.widget.PreFlightStatusWidget
android:layout_width="180dp"
android:layout_height="25dp"/>
<dji.ux.widget.FlightModeWidget
android:layout_width="103dp"
android:layout_height="22dp"/>
<dji.ux.widget.GPSSignalWidget
android:layout_width="44dp"
android:layout_height="22dp"/>
<dji.ux.widget.VisionWidget
android:layout_width="22dp"
android:layout_height="22dp"/>
<dji.ux.widget.RemoteControlSignalWidget
android:layout_width="38dp"
android:layout_height="22dp"/>
<dji.ux.widget.VideoSignalWidget
android:layout_width="38dp"
android:layout_height="22dp"/>
<dji.ux.widget.WiFiSignalWidget
android:layout_width="32dp"
android:layout_height="25dp"/>
<dji.ux.widget.BatteryWidget
android:layout_width="96dp"
android:layout_height="22dp"
custom:excludeView="singleVoltage"/>
<dji.ux.widget.ConnectionWidget
android:layout_marginTop="3dp"
android:layout_width="18dp"
android:layout_height="18dp"/>
</LinearLayout>
<LinearLayout
android:id="@+id/dashboard_widget"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:orientation="horizontal"
android:padding="12dp">
<dji.ux.widget.dashboard.DashboardWidget
android:id="@+id/Compass"
android:layout_width="405dp"
android:layout_height="91dp"
android:layout_marginRight="12dp"
tools:ignore="RtlHardcoded" />
</LinearLayout>
<!-- Panels -->
<dji.ux.widget.HistogramWidget
android:layout_width="150dp"
android:layout_height="75dp"
android:layout_centerVertical="true"
android:layout_toRightOf="@+id/TakeOffReturnPanel"
tools:ignore="RtlHardcoded" />
<dji.ux.panel.CameraSettingExposurePanel
android:layout_width="180dp"
android:layout_below="@id/camera"
android:layout_toLeftOf="@+id/CameraCapturePanel"
android:gravity="center"
android:layout_height="263dp"
android:visibility="gone"
tools:ignore="RtlHardcoded"/>
<dji.ux.panel.CameraSettingAdvancedPanel
android:layout_width="180dp"
android:layout_height="263dp"
android:layout_below="@id/camera"
android:layout_toLeftOf="@+id/CameraCapturePanel"
android:gravity="center"
android:visibility="gone"
tools:ignore="RtlHardcoded"/>
<dji.ux.panel.RTKStatusPanel
android:id="@+id/rtk_panel"
android:layout_width="500dp"
android:layout_height="350dp"
android:layout_below="@id/signal"
android:gravity="center"
android:layout_centerInParent="true"
android:visibility="gone"/>
<dji.ux.widget.ColorWaveformWidget
android:layout_width="394dp"
android:layout_height="300dp"
android:layout_below="@+id/camera"
android:gravity="center"
android:layout_centerInParent="true"
android:visibility="gone"/>
<!-- Pre-flight checklist panel -->
<dji.ux.panel.PreFlightCheckListPanel
android:id="@+id/pre_flight_check_list"
android:layout_width="400dp"
android:layout_height="wrap_content"
android:layout_below="@id/signal"
custom:excludeItem="ESCStatus"
android:visibility="gone"/>
<dji.ux.panel.SpotlightPanel
android:id="@+id/spotlight_panel"
android:layout_width="300dp"
android:layout_height="wrap_content"
android:layout_below="@id/camera2"
android:layout_alignRight="@+id/camera2"
android:visibility="gone"
android:gravity="center" />
<dji.ux.panel.SpeakerPanel
android:id="@+id/speaker_panel"
android:layout_width="300dp"
android:layout_height="match_parent"
android:layout_alignParentLeft="true"
android:layout_below="@+id/signal"
android:visibility="gone"
android:gravity="center" />
</RelativeLayout>
@Layout(R.layout.activity_main)
public class MainActivity extends BaseActivity implements View.OnClickListener {
@BindView(R.id.img_live)
ImageView mImageViewLive;
private MapWidget mapWidget;
private DJIMap aMap;
private ViewGroup parentView;
private FPVWidget fpvWidget;
private FPVWidget secondaryFPVWidget;
private RelativeLayout primaryVideoView;
private FrameLayout secondaryVideoView;
private boolean isMapMini = true;
private String liveShowUrl = "";
private int height;
private int width;
private int margin;
private int deviceWidth;
private int deviceHeight;
private SharedPreUtils mSharedPreUtils;
//unix时间戳
private String dateStr = "";
//飞行器管理器
private FlightController controller;
//经纬度
private double lat = 0, lon = 0;
//高度
private float high = 0;
//飞机的姿态
private Attitude attitude;
//俯仰角、滚转、偏航值
private double pitch = 0, roll = 0, yaw = 0;
//飞机的速度
private float velocity_X = 0, velocity_Y = 0, velocity_Z = 0;
//飞机/控制器电池管理器
private Battery battery;
//电池电量、温度
private int power = 0;
private float temperature = 0;
//云台管理器
private Gimbal gimbal;
//云台的姿态
private dji.common.gimbal.Attitude g_attitude;
//俯仰角、滚转、偏航值
private double g_pitch = 0, g_roll = 0, g_yaw = 0;
private Camera camera;
private List<Lens> lens = new ArrayList<>();
private List<DJILatLng> djiList = new ArrayList<>();
//手柄控制器
private HandheldController handheldController;
//手柄电量
private int h_power = 0;
private static List<DeviceInfo> list = new ArrayList<>();
private static List<String> getList = new ArrayList<>();
private MediaManager mMediaManager;
private MediaManager.FileListState currentFileListState = MediaManager.FileListState.UNKNOWN;
private List<MediaFile> arrayList = new ArrayList<>();
private List<String> startList = new ArrayList<>();
private List<String> endList = new ArrayList<>();
private boolean isStartLive = false;
private boolean isFlying = false;
private boolean start = false;
private BaseProduct mProduct;
private String posName = "";
//webSocket
private JWebSocketClient client;
private Map<String,String> params = new HashMap<>();
Map<String,String> mapData = new HashMap<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
height = ToolKit.dip2px(this, 100);
width = ToolKit.dip2px(this, 150);
margin = ToolKit.dip2px(this, 12);
WindowManager windowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
final Display display = windowManager.getDefaultDisplay();
Point outPoint = new Point();
display.getRealSize(outPoint);
deviceHeight = outPoint.y;
deviceWidth = outPoint.x;
parentView = (ViewGroup) findViewById(R.id.root_view);
fpvWidget = findViewById(R.id.fpv_widget);
fpvWidget.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
onViewClick(fpvWidget);
}
});
primaryVideoView = (RelativeLayout) findViewById(R.id.fpv_container);
secondaryVideoView = (FrameLayout) findViewById(R.id.secondary_video_view);
secondaryFPVWidget = findViewById(R.id.secondary_fpv_widget);
secondaryFPVWidget.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
swapVideoSource();
}
});
if (VideoFeeder.getInstance() != null) {
//If secondary video feed is already initialized, get video source
updateSecondaryVideoVisibility(VideoFeeder.getInstance().getSecondaryVideoFeed().getVideoSource() != PhysicalSource.UNKNOWN);
//If secondary video feed is not yet initialized, wait for active status
VideoFeeder.getInstance().getSecondaryVideoFeed()
.addVideoActiveStatusListener(isActive ->
runOnUiThread(() -> updateSecondaryVideoVisibility(isActive)));
}
mSharedPreUtils = SharedPreUtils.getInStance(this);
this.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
mapWidget = findViewById(R.id.map_widget);
mapWidget.setFlightPathColor(Color.parseColor("#2fa8e7"));
mapWidget.setFlightPathWidth(15);
mapWidget.setDirectionToHomeVisible(false);
mapWidget.initAMap(new MapWidget.OnMapReadyListener() {
@Override
public void onMapReady(@NonNull DJIMap djiMap) {
djiMap.setOnMapClickListener(new DJIMap.OnMapClickListener() {
@Override
public void onMapClick(DJILatLng latLng) {
onViewClick(mapWidget);
}
});
djiMap.getUiSettings().setZoomControlsEnabled(false);
}
});
if (aMap == null) {
aMap = mapWidget.getMap();
}
mapWidget.onCreate(savedInstanceState);
mProduct = ReceiverApplication.getProductInstance();
if (null != mProduct && mProduct.isConnected()) {
flyInformation(mProduct);
batteryInformation(mProduct);
cameraInformation(mProduct);
camera(mProduct);
}
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
Message msg = new Message();
if (isFlying && !start) {
start = true;
}
if (!isFlying && start) {
start = false;
}
if (isFlying && high >= 0) {
msg.what = 1;
}
mHandler.sendMessage(msg);
}
}, 200, 200);
}
Handler mHandler = new Handler() {
@RequiresApi(api = Build.VERSION_CODES.O)
@Override
public void handleMessage(@NonNull Message msg) {
switch (msg.what) {
case 1:
Long time = System.currentTimeMillis();
// MyLog.d("时间:"+time);
RecordModule module = new RecordModule(String.valueOf(projectId), String.valueOf(planeId),
trajectoryId, time, String.valueOf(lon), String.valueOf(lat),
String.valueOf(high), String.valueOf(yaw), String.valueOf(pitch), String.valueOf(roll),
String.valueOf(""), String.valueOf(velocity_X), String.valueOf(velocity_Y),
String.valueOf(velocity_Z), String.valueOf(g_yaw), String.valueOf(g_roll), String.valueOf(g_pitch));
http.getHttp(INSERT_DATA, GsonUtil.GsonString(module));
break;
case 2:
MyLog.d("飞机移动的数据:"+msg.obj.toString());
ControlModule control = GsonUtil.GsonToBean(msg.obj.toString(),ControlModule.class);
if (controller!=null&&isFlying){
if (control.getContent().isBack()){
controller.sendVirtualStickFlightControlData(new FlightControlData(-10,0,0,0),null);
}
if (control.getContent().isFront()){
controller.sendVirtualStickFlightControlData(new FlightControlData(10,0,0,0),null);
}
if (control.getContent().isDown()){
controller.sendVirtualStickFlightControlData(new FlightControlData(0,0,0,-4),null);
}
if (control.getContent().isUp()){
controller.sendVirtualStickFlightControlData(new FlightControlData(0,0,0,4),null);
}
if (control.getContent().isLeft()){
controller.sendVirtualStickFlightControlData(new FlightControlData(0,-10,0,0),null);
}
if (control.getContent().isRight()){
controller.sendVirtualStickFlightControlData(new FlightControlData(0,10,0,0),null);
}
}else {
MyLog.d("controller控制器为空");
}
break;
}
}
};
@Override
public void initViews() {
mMediaManager = ReceiverApplication.getCameraInstance().getMediaManager();
getFileList("start");
}
@Override
public void onComplete(String url, String jsonStr) {
super.onComplete(url, jsonStr);
}
@Override
public void initDatas() {
}
private void onViewClick(View view) {
if (view == fpvWidget && !isMapMini) {
resizeFPVWidget(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT, 0, 0);
reorderCameraCapturePanel();
ResizeAnimation mapViewAnimation = new ResizeAnimation(mapWidget, deviceWidth, deviceHeight, width, height, margin);
mapWidget.startAnimation(mapViewAnimation);
isMapMini = true;
} else if (view == mapWidget && isMapMini) {
hidePanels();
resizeFPVWidget(width, height, margin, 12);
reorderCameraCapturePanel();
ResizeAnimation mapViewAnimation = new ResizeAnimation(mapWidget, width, height, deviceWidth, deviceHeight, 0);
mapWidget.startAnimation(mapViewAnimation);
isMapMini = false;
}
}
private void resizeFPVWidget(int width, int height, int margin, int fpvInsertPosition) {
RelativeLayout.LayoutParams fpvParams = (RelativeLayout.LayoutParams) primaryVideoView.getLayoutParams();
fpvParams.height = height;
fpvParams.width = width;
fpvParams.rightMargin = margin;
fpvParams.bottomMargin = margin;
if (isMapMini) {
fpvParams.addRule(RelativeLayout.CENTER_IN_PARENT, 0);
fpvParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT, RelativeLayout.TRUE);
fpvParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, RelativeLayout.TRUE);
} else {
fpvParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT, 0);
fpvParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, 0);
fpvParams.addRule(RelativeLayout.CENTER_IN_PARENT, RelativeLayout.TRUE);
}
primaryVideoView.setLayoutParams(fpvParams);
parentView.removeView(primaryVideoView);
parentView.addView(primaryVideoView, fpvInsertPosition);
}
private void reorderCameraCapturePanel() {
View cameraCapturePanel = findViewById(R.id.CameraCapturePanel);
parentView.removeView(cameraCapturePanel);
parentView.addView(cameraCapturePanel, isMapMini ? 9 : 13);
}
private void swapVideoSource() {
if (secondaryFPVWidget.getVideoSource() == FPVWidget.VideoSource.SECONDARY) {
fpvWidget.setVideoSource(FPVWidget.VideoSource.SECONDARY);
secondaryFPVWidget.setVideoSource(FPVWidget.VideoSource.PRIMARY);
} else {
fpvWidget.setVideoSource(FPVWidget.VideoSource.PRIMARY);
secondaryFPVWidget.setVideoSource(FPVWidget.VideoSource.SECONDARY);
}
}
private void updateSecondaryVideoVisibility(boolean isActive) {
if (isActive) {
secondaryVideoView.setVisibility(View.VISIBLE);
} else {
secondaryVideoView.setVisibility(View.GONE);
}
}
private void hidePanels() {
//These panels appear based on keys from the drone itself.
if (KeyManager.getInstance() != null) {
KeyManager.getInstance().setValue(CameraKey.create(CameraKey.HISTOGRAM_ENABLED), false, null);
KeyManager.getInstance().setValue(CameraKey.create(CameraKey.COLOR_WAVEFORM_ENABLED), false, null);
}
//These panels have buttons that toggle them, so call the methods to make sure the button state is correct.
CameraControlsWidget controlsWidget = findViewById(R.id.CameraCapturePanel);
controlsWidget.setAdvancedPanelVisibility(false);
controlsWidget.setExposurePanelVisibility(false);
//These panels don't have a button state, so we can just hide them.
findViewById(R.id.pre_flight_check_list).setVisibility(View.GONE);
findViewById(R.id.rtk_panel).setVisibility(View.GONE);
findViewById(R.id.spotlight_panel).setVisibility(View.GONE);
findViewById(R.id.speaker_panel).setVisibility(View.GONE);
}
@Override
protected void onResume() {
super.onResume();
// Hide both the navigation bar and the status bar.
View decorView = getWindow().getDecorView();
decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
mapWidget.onResume();
if (client == null) {
MyLog.e("``````````````````````onResume");
// initWebSocket();
} else if (!client.isOpen()) {
reconnectWs();//进入页面发现断开开启重连
}
}
@Override
protected void onStop() {
super.onStop();
MyLog.e("``````````````````````````````onStop");
}
@Override
protected void onPause() {
mapWidget.onPause();
super.onPause();
}
@Override
protected void onDestroy() {
mapWidget.onDestroy();
super.onDestroy();
MyLog.e( "`````````````````````````onDestroy");
closeConnect();
}
@Override
protected void requestData() {
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
mapWidget.onSaveInstanceState(outState);
}
@Override
public void onLowMemory() {
super.onLowMemory();
mapWidget.onLowMemory();
}
private class ResizeAnimation extends Animation {
private View mView;
private int mToHeight;
private int mFromHeight;
private int mToWidth;
private int mFromWidth;
private int mMargin;
private ResizeAnimation(View v, int fromWidth, int fromHeight, int toWidth, int toHeight, int margin) {
mToHeight = toHeight;
mToWidth = toWidth;
mFromHeight = fromHeight;
mFromWidth = fromWidth;
mView = v;
mMargin = margin;
setDuration(300);
}
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
float height = (mToHeight - mFromHeight) * interpolatedTime + mFromHeight;
float width = (mToWidth - mFromWidth) * interpolatedTime + mFromWidth;
RelativeLayout.LayoutParams p = (RelativeLayout.LayoutParams) mView.getLayoutParams();
p.height = (int) height;
p.width = (int) width;
p.rightMargin = mMargin;
p.bottomMargin = mMargin;
mView.requestLayout();
}
}
//直播流推送
@RequiresApi(api = Build.VERSION_CODES.O)
@OnClick({R.id.img_live, R.id.img_show_back})
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.img_live:
params.clear();
mapData.clear();
if (!isStartLive) {
if (!TextUtils.isEmpty(mSharedPreUtils.getStringSharePre("rtmp_url"))) {
liveShowUrl = mSharedPreUtils.getStringSharePre("rtmp_url") + trajectoryId;
// LiveModule module = new LiveModule("liveStreamStateChanged","plane",planeId,true,trajectoryId+"");
MyLog.d("地址:"+liveShowUrl);
startLiveShow();
isStartLive = true;
showToast("开始推流");
} else {
showToast("请先进行系统设置(RTMP)。");
}
} else {
stopLiveShow();
isStartLive = false;
}
break;
case R.id.img_show_back:
// controller = null;
closeConnect();
MainActivity.this.finish();
break;
}
}
private boolean isLiveStreamManagerOn() {
if (DJISDKManager.getInstance().getLiveStreamManager() == null) {
return false;
}
return true;
}
private void startLiveShow() {
if (!isLiveStreamManagerOn()) {
return;
}
if (DJISDKManager.getInstance().getLiveStreamManager().isStreaming()) {
return;
}
new Thread() {
@Override
public void run() {
DJISDKManager.getInstance().getLiveStreamManager().setLiveUrl(liveShowUrl);
DJISDKManager.getInstance().getLiveStreamManager().setAudioStreamingEnabled(true);
int result = DJISDKManager.getInstance().getLiveStreamManager().startStream();
DJISDKManager.getInstance().getLiveStreamManager().setStartTime();
}
}.start();
}
private void stopLiveShow() {
AlertDialog.Builder Builder = new AlertDialog.Builder(MainActivity.this);
Builder.setTitle("提示");
Builder.setMessage("是否结束推流?");
Builder.setIcon(android.R.drawable.ic_dialog_alert);
Builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
if (!isLiveStreamManagerOn()) {
return;
}
DJISDKManager.getInstance().getLiveStreamManager().stopStream();
showToast("结束推流");
}
});
Builder.setNegativeButton("取消", null);
Builder.show();
}
//获取飞机信息、云台信息
protected BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
BaseProduct mProduct = ReceiverApplication.getProductInstance();
if (null != mProduct && mProduct.isConnected()) {
flyInformation(mProduct);
batteryInformation(mProduct);
cameraInformation(mProduct);
camera(mProduct);
// MobileRemote(mProduct);
}
}
};
// private void MobileRemote(BaseProduct mProduct) {
// if (null != mProduct && mProduct.isConnected()) {
// mobileController = ((Aircraft) mProduct).getMobileRemoteController();
// }
// }
//获取飞机信息
private void flyInformation(BaseProduct mProduct) {
if (null != mProduct && mProduct.isConnected()) {
controller = ((Aircraft) mProduct).getFlightController();
}
if (controller != null) {
controller.setStateCallback(new FlightControllerState.Callback() {
@RequiresApi(api = Build.VERSION_CODES.O)
@Override
public void onUpdate(@NonNull FlightControllerState flightControllerState) {
//纬度、经度、高度、俯仰角、滚转、偏航值、速度
lat = flightControllerState.getAircraftLocation().getLatitude();
lon = flightControllerState.getAircraftLocation().getLongitude();
high = flightControllerState.getAircraftLocation().getAltitude();
attitude = flightControllerState.getAttitude();
pitch = attitude.pitch;
roll = attitude.roll;
yaw = attitude.yaw;
velocity_X = flightControllerState.getVelocityX();
velocity_Y = flightControllerState.getVelocityY();
velocity_Z = flightControllerState.getVelocityZ();
isFlying = flightControllerState.isFlying();
// MyLog.d("经度:" + lat + ",纬度:" + lon + ",高度:" + high + ",角度:" + pitch + ",速度:" + velocity_X + "," + velocity_Y + "," + velocity_Z);
}
});
controller.setVirtualStickAdvancedModeEnabled(true);
controller.setRollPitchCoordinateSystem(FlightCoordinateSystem.BODY);
controller.setVerticalControlMode(VerticalControlMode.VELOCITY);
controller.setRollPitchControlMode(RollPitchControlMode.VELOCITY);
controller.setYawControlMode(YawControlMode.ANGULAR_VELOCITY);
// controller.setTerrainFollowModeEnabled(false, new CommonCallbacks.CompletionCallback() {
// @Override
// public void onResult(DJIError djiError) {
// MyLog.d(djiError.getDescription());
// }
// });
// controller.setTripodModeEnabled(false, new CommonCallbacks.CompletionCallback() {
// @Override
// public void onResult(DJIError djiError) {
// MyLog.d(djiError.getDescription());
// }
// });
// controller.setFlightOrientationMode(FlightOrientationMode.AIRCRAFT_HEADING, new CommonCallbacks.CompletionCallback() {
// @Override
// public void onResult(DJIError djiError) {
// MyLog.d(djiError.getDescription());
// if (djiError==null){
// if (controller.isVirtualStickControlModeAvailable()){
//
// }else {
// MyLog.d("虚拟摇杆模式不可用");
// }
// }
// }
// });
}
}
//电池信息
private void batteryInformation(BaseProduct mProduct) {
if (null != mProduct && mProduct.isConnected()) {
battery = ((Aircraft) mProduct).getBattery();
}
if (battery != null) {
battery.setStateCallback(new BatteryState.Callback() {
@Override
public void onUpdate(BatteryState batteryState) {
//电池电量
power = batteryState.getChargeRemainingInPercent();
//电池温度
temperature = batteryState.getTemperature();
}
});
}
}
//云台信息
private void cameraInformation(BaseProduct mProduct) {
if (null != mProduct && mProduct.isConnected()) {
gimbal = ((Aircraft) mProduct).getGimbal();
}
if (gimbal != null) {
gimbal.setMode(GimbalMode.YAW_FOLLOW, null);
gimbal.setStateCallback(new GimbalState.Callback() {
@Override
public void onUpdate(@NonNull GimbalState gimbalState) {
//俯仰角、滚转、偏航值
g_attitude = gimbalState.getAttitudeInDegrees();
g_pitch = g_attitude.getPitch();
g_roll = g_attitude.getRoll();
g_yaw = g_attitude.getYaw();
}
});
}
}
private void camera(BaseProduct mProduct) {
if (null != mProduct && mProduct.isConnected()) {
camera = ((Aircraft) mProduct).getCamera();
}
if (camera != null) {
// camera.setVideoCaptionEnabled(true, new CommonCallbacks.CompletionCallback() {
// @Override
// public void onResult(DJIError djiError) {
// MyLog.d("VideoCaptionEnabled"+djiError.toString());
// }
// });
// camera.setMediaFileCustomInformation(projectId +","+trajectoryId, new CommonCallbacks.CompletionCallback() {
// @Override
// public void onResult(DJIError djiError) {
// MyLog.d("自定义信息:"+djiError.toString());
// }
// });
camera.setSystemStateCallback(new SystemState.Callback() {
@RequiresApi(api = Build.VERSION_CODES.O)
@Override
public void onUpdate(@NonNull SystemState systemState) {
if (systemState.getMode().equals(SettingsDefinitions.CameraMode.SHOOT_PHOTO)) {
if (systemState.isStoringPhoto()) {
dateStr = Long.toString(System.currentTimeMillis());
list.add(new DeviceInfo(dateStr, lat, lon, high, pitch, roll, yaw, velocity_X, velocity_Y, velocity_Z, g_yaw, g_roll, g_pitch));
CsvWriter.getInstance(",", "UTF-8").writeDataToFile(list, FileUtil.checkDirPath(FLY_FILE_PATH + "/照片数据") + "/" + DateUtils.getCurrentDates() + ".csv");
list.clear();
return;
}
} else if (systemState.getMode().equals(SettingsDefinitions.CameraMode.RECORD_VIDEO)) {
if (systemState.isRecording()) {
try {
dateStr = Long.toString(System.currentTimeMillis());
list.add(new DeviceInfo(dateStr, lat, lon, high, pitch, roll, yaw, velocity_X, velocity_Y, velocity_Z, g_yaw, g_roll, g_pitch));
getList.add(dateStr);
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
if (list.size() > 1) {
posName = DateUtils.getCurrentDates() + ".csv";
CsvWriter.getInstance(",", "UTF-8").writeDataToFile(list, FileUtil.checkDirPath(FLY_FILE_PATH + "/视频数据") + "/" + posName);
list.clear();
runOnUiThread(new Runnable() {
@Override
public void run() {
getFileList("end");
}
});
}
}
}
}
});
}
}
//遥控器信息
private void handheldInforamation(BaseProduct mProduct) {
if (null != mProduct && mProduct.isConnected()) {
handheldController = ((HandHeld) mProduct).getHandHeldController();
}
if (handheldController != null) {
handheldController.setPowerModeCallback(new PowerMode.Callback() {
@Override
public void onUpdate(PowerMode powerMode) {
switch (powerMode) {
case ON:
Battery battery = ((HandHeld) mProduct).getBattery();
battery.setStateCallback(new BatteryState.Callback() {
@Override
public void onUpdate(BatteryState batteryState) {
h_power = batteryState.getChargeRemainingInPercent();
}
});
break;
}
}
});
}
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK
&& event.getAction() == KeyEvent.ACTION_DOWN) {
// closeConnect();
MainActivity.this.finish();
}
return super.onKeyDown(keyCode, event);
}
}
完成后界面如下所示:
上面的工作完成后就可以在无人且宽阔的地方进行无人机飞行了。
4
多媒体资源的操作多媒体文件操作,主要为多媒体文件的获取、查看、删除、下载的操作 同样创建多媒体功能文件FileManagementActivity及activity_file_management.xml
activity_file_management.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:custom="http://schemas.android.com/apk/res-auto"
tools:context=".ui.FileManagementActivity"
android:orientation="vertical"
android:background="@drawable/shape_corner_eight">
<include layout="@layout/activity_toolbar"
android:id="@+id/layout_file"></include>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<LinearLayout
android:layout_width="250dp"
android:layout_height="match_parent"
android:orientation="vertical"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp">
<RadioGroup
android:id="@+id/rg_file_management"
android:layout_width="match_parent"
android:layout_height="40dp"
android:orientation="horizontal"
android:background="#2B3141"
android:gravity="center">
<RadioButton
android:id="@+id/rb_file_all"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:button="@null"
android:checked="true"
android:gravity="center"
android:text="全部"
android:textColor="@drawable/nav_item_color_selector"
android:textSize="18sp"
tools:ignore="TouchTargetSizeCheck"></RadioButton>
<RadioButton
android:id="@+id/rb_file_photo"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:button="@null"
android:gravity="center"
android:text="照片"
android:textColor="@drawable/nav_item_color_selector"
android:textSize="18sp"
tools:ignore="TouchTargetSizeCheck"></RadioButton>
<RadioButton
android:id="@+id/rb_file_video"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:button="@null"
android:gravity="center"
android:text="视频"
android:textColor="@drawable/nav_item_color_selector"
android:textSize="18sp"
tools:ignore="TouchTargetSizeCheck"></RadioButton>
</RadioGroup>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_file_management"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:layout_marginTop="10dp"></androidx.recyclerview.widget.RecyclerView>
</LinearLayout>
<RelativeLayout
android:layout_width="0dp"
android:layout_weight="2"
android:layout_height="match_parent">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<dji.ux.widget.FPVWidget
android:id="@+id/FPVWidget"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerInParent="true"
custom:sourceCameraNameVisibility="false" />
</RelativeLayout>
<ImageView
android:id="@+id/img_show"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="fitXY"
android:visibility="invisible"></ImageView>
<LinearLayout
android:id="@+id/ll_video_btn"
android:layout_width="match_parent"
android:layout_height="50dp"
android:orientation="horizontal"
android:gravity="center"
android:layout_marginBottom="15dp"
android:layout_alignParentBottom="true"
android:visibility="gone">
<ImageView
android:id="@+id/img_video_pause"
android:layout_width="35dp"
android:layout_height="35dp"
android:src="@drawable/background_stop_selector"></ImageView>
<ImageView
android:id="@+id/img_video_play"
android:layout_width="45dp"
android:layout_height="45dp"
android:layout_marginLeft="20dp"
android:src="@drawable/background_palyer_selector"></ImageView>
<ImageView
android:id="@+id/img_video_stop"
android:layout_width="35dp"
android:layout_height="35dp"
android:layout_marginLeft="20dp"
android:src="@mipmap/ic_reset_36dp"></ImageView>
</LinearLayout>
</RelativeLayout>
</LinearLayout>
</LinearLayout>
FileManagementActivity
@Layout(R.layout.activity_file_management)
public class FileManagementActivity extends BaseActivity implements View.OnClickListener {
private static final String TAG = FileManagementActivity.class.getName();
@BindView(R.id.layout_file)
View mViewLayoutToolbar;
@BindView(R.id.tv_toolbar_title)
TextView mTextViewToolbarTitle;
@BindView(R.id.ll_file)
LinearLayout mLinearLayout;
@BindView(R.id.rg_file_management)
RadioGroup mRadioGroup;
@BindView(R.id.rv_file_management)
RecyclerView mRecyclerView;
@BindView(R.id.img_show)
ImageView mImageView;
@BindView(R.id.ll_video_btn)
LinearLayout mLinearLayoutVideo;
@BindView(R.id.img_video_play)
ImageView mImageViewVideoPlay;
@BindView(R.id.img_video_pause)
ImageView mImageViewVideoPause;
private FileListAdapter mListAdapter;
private List<MediaFile> List = new ArrayList<MediaFile>();
private List<MediaFile> mediaFileList = new ArrayList<MediaFile>();
private MediaManager mMediaManager;
private MediaManager.FileListState currentFileListState = MediaManager.FileListState.UNKNOWN;
private MediaManager.VideoPlaybackState state;
private ProgressDialog mLoadingDialog;
private ProgressDialog mDownloadDialog;
private FetchMediaTaskScheduler scheduler;
private int lastClickViewIndex = -1;
private int currentProgress = -1;
private String SavePath = "";
private View lastClickView;
private boolean isResume = false;
private SFTPUtils sftp;
private SettingsDefinitions.StorageLocation storageLocation;
@Override
public void initViews() {
mLinearLayout.setVisibility(View.VISIBLE);
mTextViewToolbarTitle.setText("文件管理");
mImageViewVideoPlay.setEnabled(true);
mImageViewVideoPause.setEnabled(false);
mRadioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
List.clear();
mediaFileList.clear();
switch (checkedId) {
case R.id.rb_file_all:
getFileList(0);
mListAdapter.notifyDataSetChanged();
break;
case R.id.rb_file_photo:
getFileList(1);
mListAdapter.notifyDataSetChanged();
break;
case R.id.rb_file_video:
getFileList(2);
mListAdapter.notifyDataSetChanged();
break;
}
}
});
LinearLayoutManager layoutManager = new LinearLayoutManager(FileManagementActivity.this, RecyclerView.VERTICAL, false);
mRecyclerView.setLayoutManager(layoutManager);
//Init FileListAdapter
mListAdapter = new FileListAdapter();
mRecyclerView.setAdapter(mListAdapter);
//Init Loading Dialog
mLoadingDialog = new ProgressDialog(FileManagementActivity.this);
mLoadingDialog.setMessage("请等待...");
mLoadingDialog.setCanceledOnTouchOutside(false);
mLoadingDialog.setCancelable(false);
//Init Download Dialog
mDownloadDialog = new ProgressDialog(FileManagementActivity.this);
mDownloadDialog.setTitle("下载中...");
mDownloadDialog.setIcon(android.R.drawable.ic_dialog_info);
mDownloadDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
mDownloadDialog.setCanceledOnTouchOutside(false);
mDownloadDialog.setCancelable(true);
mDownloadDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
if (mMediaManager != null) {
mMediaManager.exitMediaDownloading();
}
}
});
sftp = new SFTPUtils("49.4.79.249","uav","uavHHch@YREC.cn");
ReceiverApplication.getAircraftInstance().getCamera().setStorageStateCallBack(new StorageState.Callback() {
@Override
public void onUpdate(@NonNull @NotNull StorageState storageState) {
if(storageState.isInserted()) {
storageLocation = SettingsDefinitions.StorageLocation.SDCARD;
ReceiverApplication.getAircraftInstance().getCamera().setStorageLocation(SettingsDefinitions.StorageLocation.SDCARD, new CommonCallbacks.CompletionCallback() {
@Override
public void onResult(DJIError djiError) {
}
});
} else {
storageLocation = SettingsDefinitions.StorageLocation.INTERNAL_STORAGE;
ReceiverApplication.getAircraftInstance().getCamera().setStorageLocation(SettingsDefinitions.StorageLocation.INTERNAL_STORAGE, new CommonCallbacks.CompletionCallback() {
@Override
public void onResult(DJIError djiError) {
}
});
}
}
});
}
@Override
public void initDatas() {
}
@Override
protected void requestData() {
}
@Override
public void onComplete(String url, String jsonStr) {
super.onComplete(url, jsonStr);
switch (url){
case POST_VIDEO_INFO:
break;
default:
getVideoJson(jsonStr);
break;
}
}
private void getVideoJson(String jsonStr) {
VideoModule module = GsonUtil.GsonToBean(jsonStr,VideoModule.class);
if (module.getCode() == 200 && module.getRows().size() == 1){
runOnUiThread(new Runnable() {
@Override
public void run() {
UpdateFileModule fileModule = new UpdateFileModule(module.getRows().get(0).getId(),"/mnt/uavFtpFolder/"+module.getRows().get(0).getFileName());
http.getHttp(POST_VIDEO_INFO,"PUT",GsonUtil.GsonString(fileModule));
}
});
}
}
@Override
protected void onResume() {
super.onResume();
initMediaManager();
}
@Override
protected void onPause() {
super.onPause();
}
@Override
protected void onStop() {
super.onStop();
}
@Override
protected void onDestroy() {
lastClickView = null;
if (mMediaManager != null) {
mMediaManager.stop(null);
mMediaManager.removeFileListStateCallback(this.updateFileListStateListener);
mMediaManager.exitMediaDownloading();
if (scheduler != null) {
scheduler.removeAllTasks();
}
}
if (isMavicAir2() || isM300()) {
if (ReceiverApplication.getCameraInstance() != null) {
ReceiverApplication.getCameraInstance().exitPlayback(djiError -> {
if (djiError != null) {
ReceiverApplication.getCameraInstance().setFlatMode(SettingsDefinitions.FlatCameraMode.PHOTO_SINGLE, djiError1 -> {
if (djiError1 != null) {
showToasts("设置单张拍照模式失败. " + djiError1.getDescription());
}
});
}
});
} else {
ReceiverApplication.getCameraInstance().setMode(SettingsDefinitions.CameraMode.SHOOT_PHOTO, djiError -> {
if (djiError != null) {
showToasts("设置拍照模式失败. " + djiError.getDescription());
}
});
}
}
if (mediaFileList != null) {
// List.clear();
mediaFileList.clear();
}
super.onDestroy();
}
private void showProgressDialogs() {
runOnUiThread(new Runnable() {
public void run() {
if (mLoadingDialog != null) {
mLoadingDialog.show();
}
}
});
}
private void hideProgressDialog() {
runOnUiThread(new Runnable() {
public void run() {
if (null != mLoadingDialog && mLoadingDialog.isShowing()) {
mLoadingDialog.dismiss();
}
}
});
}
private void ShowDownloadProgressDialog() {
if (mDownloadDialog != null) {
runOnUiThread(new Runnable() {
public void run() {
mDownloadDialog.incrementProgressBy(-mDownloadDialog.getProgress());
mDownloadDialog.show();
}
});
}
}
private void HideDownloadProgressDialog() {
if (null != mDownloadDialog && mDownloadDialog.isShowing()) {
runOnUiThread(new Runnable() {
public void run() {
mDownloadDialog.dismiss();
}
});
}
}
private void initMediaManager() {
if (ReceiverApplication.getProductInstance() == null) {
mediaFileList.clear();
mListAdapter.notifyDataSetChanged();
DJILog.e(TAG, "设备已断开");
return;
} else {
if (null != ReceiverApplication.getCameraInstance() && ReceiverApplication.getCameraInstance().isMediaDownloadModeSupported()) {
mMediaManager = ReceiverApplication.getCameraInstance().getMediaManager();
if (null != mMediaManager) {
mMediaManager.addUpdateFileListStateListener(this.updateFileListStateListener);
mMediaManager.addMediaUpdatedVideoPlaybackStateListener(new MediaManager.VideoPlaybackStateListener() {
@Override
public void onUpdate(MediaManager.VideoPlaybackState videoPlaybackState) {
state = videoPlaybackState;
if (videoPlaybackState.getPlaybackStatus() == MediaFile.VideoPlaybackStatus.STOPPED){
runOnUiThread(new Runnable() {
@Override
public void run() {
// mImageViewVideoPlay.setEnabled(true);
// mImageViewVideoPause.setEnabled(false);
}
});
}
}
});
if (isMavicAir2() || isM300()) {
ReceiverApplication.getCameraInstance().enterPlayback(djiError -> {
if (djiError == null) {
DJILog.e(TAG, "设置cameraMode成功");
showProgressDialogs();
getFileList(0);
} else {
showToasts("设置cameraMode失败");
}
});
} else {
ReceiverApplication.getCameraInstance().setMode(SettingsDefinitions.CameraMode.MEDIA_DOWNLOAD, error -> {
if (error == null) {
DJILog.e(TAG, "设置cameraMode成功");
showProgressDialogs();
getFileList(0);
} else {
showToasts("设置cameraMode失败");
}
});
}
if (mMediaManager.isVideoPlaybackSupported()) {
DJILog.e(TAG, "摄像头支持视频播放!");
} else {
showToasts("摄像头不支持视频播放!");
}
scheduler = mMediaManager.getScheduler();
}
} else if (null != ReceiverApplication.getCameraInstance()
&& !ReceiverApplication.getCameraInstance().isMediaDownloadModeSupported()) {
showToasts("不支持媒体下载模式");
}
}
return;
}
private void getFileList(int index) {
mMediaManager = ReceiverApplication.getCameraInstance().getMediaManager();
if (mMediaManager != null) {
if ((currentFileListState == MediaManager.FileListState.SYNCING) || (currentFileListState == MediaManager.FileListState.DELETING)) {
DJILog.e(TAG, "媒体管理器正忙.");
} else {
mMediaManager.refreshFileListOfStorageLocation(storageLocation, djiError -> {
// mMediaManager.refreshFileListOfStorageLocation(SettingsDefinitions.StorageLocation.SDCARD, djiError -> {
if (null == djiError) {
hideProgressDialog();
//Reset data
if (currentFileListState != MediaManager.FileListState.INCOMPLETE) {
List.clear();
mediaFileList.clear();
lastClickViewIndex = -1;
}
// List = mMediaManager.getSDCardFileListSnapshot();
// List = mMediaManager.getInternalStorageFileListSnapshot();
if (storageLocation == SettingsDefinitions.StorageLocation.SDCARD) {
List = mMediaManager.getSDCardFileListSnapshot();
} else {
List = mMediaManager.getInternalStorageFileListSnapshot();
}
switch (index) {
case 0:
for (int i = 0; i < List.size(); i++) {
mediaFileList.add(List.get(i));
}
break;
case 1:
for (int i = 0; i < List.size(); i++) {
if (List.get(i).getMediaType() == MediaFile.MediaType.JPEG) {
mediaFileList.add(List.get(i));
MyLog.d("图片名称:"+List.get(i).getFileName());
}
}
break;
case 2:
for (int i = 0; i < List.size(); i++) {
if ((List.get(i).getMediaType() == MediaFile.MediaType.MOV) || (List.get(i).getMediaType() == MediaFile.MediaType.MP4)) {
mediaFileList.add(List.get(i));
MyLog.d("视频名称:"+List.get(i).getFileName());
}
}
break;
}
if (mediaFileList != null) {
Collections.sort(mediaFileList, (lhs, rhs) -> {
if (lhs.getTimeCreated() < rhs.getTimeCreated()) {
return 1;
} else if (lhs.getTimeCreated() > rhs.getTimeCreated()) {
return -1;
}
return 0;
});
}
scheduler.resume(error -> {
if (error == null) {
getThumbnails();
}
});
} else {
hideProgressDialog();
showToasts("获取媒体文件列表失败:" + djiError.getDescription());
}
});
}
}
}
private void getThumbnails() {
if (mediaFileList.size() <= 0) {
showToasts("没有用于下载缩略图的文件信息");
return;
}
for (int i = 0; i < mediaFileList.size(); i++) {
getThumbnailByIndex(i);
}
}
private FetchMediaTask.Callback taskCallback = new FetchMediaTask.Callback() {
@Override
public void onUpdate(MediaFile file, FetchMediaTaskContent option, DJIError error) {
if (null == error) {
if (option == FetchMediaTaskContent.PREVIEW) {
runOnUiThread(new Runnable() {
public void run() {
mListAdapter.notifyDataSetChanged();
}
});
}
if (option == FetchMediaTaskContent.THUMBNAIL) {
runOnUiThread(new Runnable() {
public void run() {
mListAdapter.notifyDataSetChanged();
}
});
}
} else {
DJILog.e(TAG, "获取媒体任务失败" + error.getDescription());
}
}
};
private void getThumbnailByIndex(final int index) {
FetchMediaTask task = new FetchMediaTask(mediaFileList.get(index), FetchMediaTaskContent.THUMBNAIL, taskCallback);
scheduler.moveTaskToEnd(task);
}
class ItemHolder extends RecyclerView.ViewHolder {
ImageView thumbnail_img;
TextView file_name;
TextView file_type;
TextView file_size;
TextView file_time;
public ItemHolder(View itemView) {
super(itemView);
this.thumbnail_img = (ImageView) itemView.findViewById(R.id.filethumbnail);
this.file_name = (TextView) itemView.findViewById(R.id.filename);
this.file_type = (TextView) itemView.findViewById(R.id.filetype);
this.file_size = (TextView) itemView.findViewById(R.id.fileSize);
this.file_time = (TextView) itemView.findViewById(R.id.filetime);
}
}
private class FileListAdapter extends RecyclerView.Adapter<ItemHolder> {
@Override
public int getItemCount() {
if (mediaFileList != null) {
return mediaFileList.size();
}
return 0;
}
@Override
public ItemHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.media_info_item, parent, false);
return new ItemHolder(view);
}
@Override
public void onBindViewHolder(ItemHolder mItemHolder, final int index) {
final MediaFile mediaFile = mediaFileList.get(index);
if (mediaFile != null) {
if (mediaFile.getMediaType() != MediaFile.MediaType.MOV && mediaFile.getMediaType() != MediaFile.MediaType.MP4) {
mItemHolder.file_time.setVisibility(View.GONE);
} else {
mItemHolder.file_time.setVisibility(View.VISIBLE);
mItemHolder.file_time.setText(mediaFile.getDurationInSeconds() + " s");
}
mItemHolder.file_name.setText(mediaFile.getFileName());
mItemHolder.file_type.setText(mediaFile.getMediaType().name());
mItemHolder.file_size.setText(String.format("%.2f", (double) (mediaFile.getFileSize() / 1048576d)) + " MB");
mItemHolder.thumbnail_img.setImageBitmap(mediaFile.getThumbnail());
mItemHolder.thumbnail_img.setTag(mediaFile);
mItemHolder.itemView.setTag(index);
if (lastClickViewIndex == index) {
mItemHolder.itemView.setSelected(true);
} else {
mItemHolder.itemView.setSelected(false);
}
mItemHolder.itemView.setOnClickListener(itemViewOnClickListener);
}
}
}
private View.OnClickListener itemViewOnClickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
lastClickViewIndex = (int) (v.getTag());
if (lastClickView != null && lastClickView != v) {
lastClickView.setSelected(false);
}
v.setSelected(true);
lastClickView = v;
MediaFile selectedMedia = mediaFileList.get(lastClickViewIndex);
if (selectedMedia != null && mMediaManager != null) {
addMediaTask(selectedMedia);
}
}
};
private void addMediaTask(final MediaFile mediaFile) {
final FetchMediaTaskScheduler scheduler = mMediaManager.getScheduler();
final FetchMediaTask task =
new FetchMediaTask(mediaFile, FetchMediaTaskContent.PREVIEW, new FetchMediaTask.Callback() {
@Override
public void onUpdate(final MediaFile mediaFile, FetchMediaTaskContent fetchMediaTaskContent, DJIError error) {
if (null == error) {
if (mediaFile.getPreview() != null) {
runOnUiThread(new Runnable() {
@Override
public void run() {
final Bitmap previewBitmap = mediaFile.getPreview();
mImageView.setVisibility(View.VISIBLE);
mImageView.setImageBitmap(previewBitmap);
if (mediaFile.getMediaType() == MediaFile.MediaType.MP4){
mLinearLayoutVideo.setVisibility(View.VISIBLE);
}else {
mLinearLayoutVideo.setVisibility(View.GONE);
}
}
});
} else {
showToasts("没有图像bitmap!");
}
} else {
showToasts("查找图像内容失败: " + error.getDescription());
}
}
});
scheduler.resume(error -> {
if (error == null) {
scheduler.moveTaskToNext(task);
} else {
showToasts("恢复计划程序失败: " + error.getDescription());
}
});
}
//Listeners
private MediaManager.FileListStateListener updateFileListStateListener = state -> currentFileListState = state;
private void deleteFileByIndex(final int index) {
ArrayList<MediaFile> fileToDelete = new ArrayList<MediaFile>();
if (mediaFileList.size() > index) {
fileToDelete.add(mediaFileList.get(index));
mMediaManager.deleteFiles(fileToDelete, new CommonCallbacks.CompletionCallbackWithTwoParam<List<MediaFile>, DJICameraError>() {
@Override
public void onSuccess(List<MediaFile> x, DJICameraError y) {
DJILog.e(TAG, "Delete file success");
runOnUiThread(new Runnable() {
public void run() {
mediaFileList.remove(index);
//Reset select view
lastClickViewIndex = -1;
lastClickView = null;
//Update recyclerView
mListAdapter.notifyDataSetChanged();
}
});
}
@Override
public void onFailure(DJIError error) {
showToasts("删除失败");
}
});
}
}
private void downloadFileByIndex(final int index) {
if ((mediaFileList.get(index).getMediaType() == MediaFile.MediaType.PANORAMA)
|| (mediaFileList.get(index).getMediaType() == MediaFile.MediaType.SHALLOW_FOCUS)) {
return;
}
if ((mediaFileList.get(index).getMediaType() == MediaFile.MediaType.MOV) || (mediaFileList.get(index).getMediaType() == MediaFile.MediaType.MP4)) {
SavePath = MyStatic.FLY_FILE_VIDEO;
} else if (mediaFileList.get(index).getMediaType() == MediaFile.MediaType.JPEG) {
SavePath = MyStatic.FLY_FILE_PHOTO;
}
File destDir = new File(FileUtil.checkDirPath(SavePath));
mediaFileList.get(index).fetchFileData(destDir,null, new DownloadListener<String>() {
@Override
public void onFailure(DJIError error) {
HideDownloadProgressDialog();
showToasts("下载失败" + error.getDescription());
currentProgress = -1;
}
@Override
public void onProgress(long total, long current) {
}
@Override
public void onRateUpdate(long total, long current, long persize) {
int tmpProgress = (int) (1.0 * current / total * 100);
if (tmpProgress != currentProgress) {
mDownloadDialog.setProgress(tmpProgress);
currentProgress = tmpProgress;
}
}
@Override
public void onRealtimeDataUpdate(byte[] bytes, long l, boolean b) {
}
@Override
public void onStart() {
currentProgress = -1;
ShowDownloadProgressDialog();
}
@Override
public void onSuccess(String filePath) {
HideDownloadProgressDialog();
showToasts("下载成功" + ":" + filePath);
currentProgress = -1;
}
});
// mediaFileList.get(index).fetchFileByteData(0, new DownloadListener<String>() {
// @Override
// public void onStart() {
// currentProgress = -1;
// ShowDownloadProgressDialog();
// }
//
// @Override
// public void onRateUpdate(long total, long current, long persize) {
// int tmpProgress = (int) (1.0 * current / total * 100);
// if (tmpProgress != currentProgress) {
// mDownloadDialog.setProgress(tmpProgress);
// currentProgress = tmpProgress;
// }
// }
//
// @Override
// public void onRealtimeDataUpdate(byte[] bytes, long l, boolean b) {
// byteToFile(bytes, FileUtil.checkDirPath(SavePath)+mediaFileList.get(index).getFileName());
// }
//
// @Override
// public void onProgress(long l, long l1) {
//
// }
//
// @Override
// public void onSuccess(String s) {
// HideDownloadProgressDialog();
// showToasts("下载成功" + ":" + s);
// currentProgress = -1;
// }
//
// @Override
// public void onFailure(DJIError djiError) {
//
// }
// });
}
public static void byteToFile(byte[] bytes, String path)
{
try
{
// 根据绝对路径初始化文件
File localFile = new File(path);
if (!localFile.exists())
{
localFile.createNewFile();
}
// 输出流
OutputStream os = new FileOutputStream(localFile);
os.write(bytes);
os.close();
}
catch (Exception e)
{
e.printStackTrace();
}
}
private void playVideo() {
mImageView.setVisibility(View.INVISIBLE);
MediaFile selectedMediaFile = mediaFileList.get(lastClickViewIndex);
if ((selectedMediaFile.getMediaType() == MediaFile.MediaType.MOV) || (selectedMediaFile.getMediaType() == MediaFile.MediaType.MP4)) {
mMediaManager.playVideoMediaFile(selectedMediaFile, error -> {
if (null != error) {
showToasts("播放失败 " + error.getDescription());
} else {
DJILog.e(TAG, "播放成功");
runOnUiThread(new Runnable() {
@Override
public void run() {
mImageViewVideoPlay.setEnabled(false);
mImageViewVideoPause.setEnabled(true);
}
});
}
});
}
}
@OnClick({R.id.img_back, R.id.img_delete, R.id.img_download, R.id.img_upload, R.id.img_video_play,
R.id.img_video_pause, R.id.img_video_stop})
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.img_back:
FileManagementActivity.this.finish();
break;
case R.id.img_delete:
if (lastClickViewIndex >= 0) {
deleteFileByIndex(lastClickViewIndex);
} else {
showToasts("请先选择文件。");
}
break;
case R.id.img_download:
if (lastClickViewIndex >= 0) {
downloadFileByIndex(lastClickViewIndex);
} else {
showToasts("请先选择文件。");
}
break;
case R.id.img_upload:
if (lastClickViewIndex >= 0) {
uploadFileByIndex(lastClickViewIndex);
} else {
showToasts("请先选择文件。");
}
break;
case R.id.img_video_play:
if (state.getPlaybackStatus() == MediaFile.VideoPlaybackStatus.STOPPED){
playVideo();
}else if (state.getPlaybackStatus() == MediaFile.VideoPlaybackStatus.PAUSED){
mMediaManager.resume(error -> {
if (null != error) {
showToasts("继续播放失败:" + error.getDescription());
} else {
DJILog.e(TAG, "继续播放成功");
runOnUiThread(new Runnable() {
@Override
public void run() {
mImageViewVideoPlay.setEnabled(false);
mImageViewVideoPause.setEnabled(true);
}
});
}
});
}
break;
case R.id.img_video_pause:
mMediaManager.pause(error -> {
if (null != error) {
showToasts("暂停播放失败:" + error.getDescription());
} else {
DJILog.e(TAG, "暂停播放成功");
runOnUiThread(new Runnable() {
@Override
public void run() {
mImageViewVideoPlay.setEnabled(true);
mImageViewVideoPause.setEnabled(false);
}
});
}
});
break;
case R.id.img_video_stop:
mMediaManager.stop(error -> {
if (null != error) {
showToasts("停止播放失败:" + error.getDescription());
} else {
DJILog.e(TAG, "停止播放成功");
}
});
break;
}
}
private void uploadFileByIndex(int index) {
if ((mediaFileList.get(index).getMediaType() == MediaFile.MediaType.MOV) || (mediaFileList.get(index).getMediaType() == MediaFile.MediaType.MP4)) {
showProgressDialog("正在上传");
new Thread(new Runnable() {
@Override
public void run() {
boolean isConnect = sftp.connect().isConnected();
if (isConnect){
boolean isUpdate = sftp.uploadFile("/mnt/uavFtpFolder/",mediaFileList.get(index).getFileName(), FLY_FILE_VIDEO, mediaFileList.get(index).getFileName());
if (isUpdate){
runOnUiThread(new Runnable() {
@Override
public void run() {
removeProgressDialog();
http.getHttp(GET_VIDEO_INFO+"?fileName="+mediaFileList.get(index).getFileName(),"GET");
}
});
sftp.disconnect();
}else {
runOnUiThread(new Runnable() {
@Override
public void run() {
showErrorTip("上传失败");
removeProgressDialog();
}
});
}
}else {
runOnUiThread(new Runnable() {
@Override
public void run() {
showErrorTip("服务器连接失败");
removeProgressDialog();
}
});
}
}
}).start();
}else {
showToasts("当前仅支持视频上传,请选择视频文件!");
}
}
private boolean isMavicAir2() {
BaseProduct baseProduct = ReceiverApplication.getProductInstance();
if (baseProduct != null) {
return baseProduct.getModel() == Model.MAVIC_AIR_2;
}
return false;
}
private boolean isM300() {
BaseProduct baseProduct = ReceiverApplication.getProductInstance();
if (baseProduct != null) {
return baseProduct.getModel() == Model.MATRICE_300_RTK;
}
return false;
}
}
运行后界面如下:
*博客内容为网友个人发布,仅代表博主个人观点,如有侵权请联系工作人员删除。