1
电子说
上一篇文章(基于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(ListdeniedPermissions) { } }); } //无人机首次注册 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 () { @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.dji4.16"依赖,等待安装即可。
设计界面UI
创建MainActivity文件及activity_main.xml。
@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 Listlens = new ArrayList<>(); private List djiList = new ArrayList<>(); //手柄控制器 private HandheldController handheldController; //手柄电量 private int h_power = 0; private static List list = new ArrayList<>(); private static List getList = new ArrayList<>(); private MediaManager mMediaManager; private MediaManager.FileListState currentFileListState = MediaManager.FileListState.UNKNOWN; private List arrayList = new ArrayList<>(); private List startList = new ArrayList<>(); private List 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 params = new HashMap<>(); Map 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
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 ListList = new ArrayList (); private List mediaFileList = new ArrayList (); 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 { @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 fileToDelete = new ArrayList (); if (mediaFileList.size() > index) { fileToDelete.add(mediaFileList.get(index)); mMediaManager.deleteFiles(fileToDelete, new CommonCallbacks.CompletionCallbackWithTwoParam , DJICameraError>() { @Override public void onSuccess(List
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 () { @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 () { // @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; } }
运行后界面如下:
审核编辑:汤梓红
全部0条评论
快来发表一下你的评论吧 !