0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

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

jf_Vqngj70R 来源:美男子玩编程 2023-06-09 11:33 次阅读

上一篇文章(基于Mobile SDK V4版固件开发大疆无人机手机端遥控器(1))因为时间原因介绍了一部分内容,如果已经完成上一篇内容的操作就可以进行下面功能方面的制作了。自己开发的APP功能不是很多,但是已经将大疆无人机的常用功能进行了结合,同大家一起进行学习~

1应用程序激活与绑定

如果在中国使用DJI飞行器固件,则需要使用该用户的DJI帐户激活控制DJI飞行器的移动应用程序。这将确保大疆能根据飞行器的地理位置和用户个人资料,为飞行器配置正确的地理空间信息和飞行功能集。激活系统的主要是:

中国用户必须在每三个月至少登录一次DJI帐户以遍激活应用程序。

激活信息将存储在应用程序中,直到用户注销为止。

登录DJI帐号需要连接互联网。

在中国境外,SDK会自动激活应用程序,无需用户登录。

另外,中国用户必须将飞机绑定到DJI官方app中的用户帐户。这仅需要一次。如果未激活应用程序,未绑定飞机(如果需要)或使用旧版SDK(<4.1),则会禁用相机视频流,并且飞行限制在直径100m和高度30m的区域中,以确保飞机停留在视线范围内。

2为应用程序创建UI

编写MApplication、ReceiverApplication和RegistrationActivity文件(此处粘贴部分代码)。

publicclassMApplicationextendsMultiDexApplication{
privateReceiverApplicationreceiverApplication;

@Override
protectedvoidattachBaseContext(ContextparamContext){
super.attachBaseContext(paramContext);
CrashHandler.getInstance().init(this);
Helper.install(MApplication.this);
if(receiverApplication==null){
receiverApplication=newReceiverApplication();
receiverApplication.setContext(this);
}
}

@Override
publicvoidonCreate(){
super.onCreate();
receiverApplication.onCreate();
}
}

上面的代码实现了绑定当前APP,将后续需要用到的类函数封装到ReceiverApplication 中,在ReceiverApplication 中也能够进行账户登录的操作。

publicclassReceiverApplicationextendsMultiDexApplication{
publicstaticfinalStringFLAG_CONNECTION_CHANGE="activation_connection_change";

privatestaticBaseProductmProduct;
publicHandlermHandler;

privateApplicationinstance;

publicvoidsetContext(Applicationapplication){
instance=application;
}

@Override
protectedvoidattachBaseContext(Contextbase){
super.attachBaseContext(base);
Helper.install(this);
}

@Override
publicContextgetApplicationContext(){
returninstance;
}

publicReceiverApplication(){

}

/**
*ThisfunctionisusedtogettheinstanceofDJIBaseProduct.
*Ifnoproductisconnected,itreturnsnull.
*/
publicstaticsynchronizedBaseProductgetProductInstance(){
if(null==mProduct){
mProduct=DJISDKManager.getInstance().getProduct();
}
returnmProduct;
}

publicstaticsynchronizedAircraftgetAircraftInstance(){
if(!isAircraftConnected())returnnull;
return(Aircraft)getProductInstance();
}

publicstaticsynchronizedCameragetCameraInstance(){

if(getProductInstance()==null)returnnull;

Cameracamera=null;

if(getProductInstance()instanceofAircraft){
camera=((Aircraft)getProductInstance()).getCamera();

}elseif(getProductInstance()instanceofHandHeld){
camera=((HandHeld)getProductInstance()).getCamera();
}

returncamera;
}

publicstaticbooleanisAircraftConnected(){
returngetProductInstance()!=null&&getProductInstance()instanceofAircraft;
}

publicstaticbooleanisHandHeldConnected(){
returngetProductInstance()!=null&&getProductInstance()instanceofHandHeld;
}

publicstaticbooleanisProductModuleAvailable(){
return(null!=ReceiverApplication.getProductInstance());
}

publicstaticbooleanisCameraModuleAvailable(){
returnisProductModuleAvailable()&&
(null!=ReceiverApplication.getProductInstance().getCamera());
}

publicstaticbooleanisPlaybackAvailable(){
returnisCameraModuleAvailable()&&
(null!=ReceiverApplication.getProductInstance().getCamera().getPlaybackManager());
}

@Override
publicvoidonCreate(){
super.onCreate();
mHandler=newHandler(Looper.getMainLooper());

/**
*WhenstartingSDKservices,aninstanceofinterfaceDJISDKManager.DJISDKManagerCallbackwillbeusedtolistento
*theSDKRegistrationresultandtheproductchanging.
*/
//ListenstotheSDKregistrationresult
DJISDKManager.SDKManagerCallbackmDJISDKManagerCallback=newDJISDKManager.SDKManagerCallback(){

//ListenstotheSDKregistrationresult
@Override
publicvoidonRegister(DJIErrorerror){

if(error==DJISDKError.REGISTRATION_SUCCESS){

Handlerhandler=newHandler(Looper.getMainLooper());
handler.post(newRunnable(){
@Override
publicvoidrun(){
//ToastUtils.showToast(getApplicationContext(),"注册成功");
//Toast.makeText(getApplicationContext(),"注册成功",Toast.LENGTH_LONG).show();
//loginAccount();
}
});

DJISDKManager.getInstance().startConnectionToProduct();

}else{

Handlerhandler=newHandler(Looper.getMainLooper());
handler.post(newRunnable(){

@Override
publicvoidrun(){
//ToastUtils.showToast(getApplicationContext(),"注册sdk失败,请检查网络是否可用");
//Toast.makeText(getApplicationContext(),"注册sdk失败,请检查网络是否可用",Toast.LENGTH_LONG).show();
}
});

}
Log.e("TAG",error.toString());
}

@Override
publicvoidonProductDisconnect(){
Log.d("TAG","设备连接");
notifyStatusChange();
}

@Override
publicvoidonProductConnect(BaseProductbaseProduct){
Log.d("TAG",String.format("新设备连接:%s",baseProduct));
notifyStatusChange();
}

@Override
publicvoidonProductChanged(BaseProductbaseProduct){

}

@Override
publicvoidonComponentChange(BaseProduct.ComponentKeycomponentKey,BaseComponentoldComponent,
BaseComponentnewComponent){
if(newComponent!=null){
newComponent.setComponentListener(newBaseComponent.ComponentListener(){

@Override
publicvoidonConnectivityChange(booleanisConnected){
Log.d("TAG","设备连接已更改:"+isConnected);
notifyStatusChange();
}
});
}

Log.d("TAG",
String.format("设备改变key:%s,旧设备:%s,新设备:%s",
componentKey,
oldComponent,
newComponent));

}

@Override
publicvoidonInitProcess(DJISDKInitEventdjisdkInitEvent,inti){

}

@Override
publicvoidonDatabaseDownloadProgress(longl,longl1){

}
};
//Checkthepermissionsbeforeregisteringtheapplicationforandroidsystem6.0above.
intpermissionCheck=ContextCompat.checkSelfPermission(getApplicationContext(),android.Manifest.permission.WRITE_EXTERNAL_STORAGE);
intpermissionCheck2=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)
publicclassRegistrationActivityextendsBaseActivityimplementsView.OnClickListener{

privatestaticfinalStringTAG=RegistrationActivity.class.getName();
privateAtomicBooleanisRegistrationInProgress=newAtomicBoolean(false);

privatestaticfinalString[]permissions=newString[]{
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
publicvoidinitViews(){
isPermission();
IntentFilterfilter=newIntentFilter();
filter.addAction(ReceiverApplication.FLAG_CONNECTION_CHANGE);
registerReceiver(mReceiver,filter);
}

@Override
publicvoidinitDatas(){
startSDKRegistration();
}

@Override
protectedvoidrequestData(){

}


@Override
protectedvoidonResume(){
super.onResume();
}



privatevoidisPermission(){
requestRunTimePermission(permissions,newIPermission(){
@Override
publicvoidonGranted(){
}

@Override
publicvoidonDenied(ListdeniedPermissions){

}
});
}



//无人机首次注册
privatevoidstartSDKRegistration(){
if(isRegistrationInProgress.compareAndSet(false,true)){
AsyncTask.execute(newRunnable(){
@Override
publicvoidrun(){
//showToasts("注册中,请等待...");
DJISDKManager.getInstance().registerApp(getApplicationContext(),newDJISDKManager.SDKManagerCallback(){
@Override
publicvoidonRegister(DJIErrordjiError){
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
publicvoidonProductDisconnect(){
Log.d(TAG,"产品断开连接");
//showToasts("产品断开连接");

}

@Override
publicvoidonProductConnect(BaseProductbaseProduct){
Log.d(TAG,String.format("新产品连接:%s",baseProduct));
//showToasts("产品连接");

}

@Override
publicvoidonProductChanged(BaseProductbaseProduct){

}

@Override
publicvoidonComponentChange(BaseProduct.ComponentKeycomponentKey,BaseComponentoldComponent,
BaseComponentnewComponent){
if(newComponent!=null){
newComponent.setComponentListener(newBaseComponent.ComponentListener(){

@Override
publicvoidonConnectivityChange(booleanisConnected){
Log.d(TAG,"组件连接已更改:"+isConnected);
}
});
}
Log.d(TAG,String.format("改变设备Key:%s,"+"旧设备:%s,"+"新设备:%s",
componentKey,oldComponent,newComponent));
}

@Override
publicvoidonInitProcess(DJISDKInitEventdjisdkInitEvent,inti){

}

@Override
publicvoidonDatabaseDownloadProgress(longl,longl1){

}
});
}
});
}
}

protectedBroadcastReceivermReceiver=newBroadcastReceiver(){
@Override
publicvoidonReceive(Contextcontext,Intentintent){
refreshSDKRelativeUI();
}
};

privatevoidrefreshSDKRelativeUI(){
BaseProductmProduct=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();
}
}

protectedlongexitTime;//记录第一次点击时的时间

@Override
publicbooleanonKeyDown(intkeyCode,KeyEventevent){
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);
}
returntrue;
}
returnsuper.onKeyDown(keyCode,event);
}


privatevoidloginAccount(){
UserAccountManager.getInstance().logIntoDJIUserAccount(this,newCommonCallbacks.CompletionCallbackWith(){
@Override
publicvoidonSuccess(UserAccountStateuserAccountState){
runOnUiThread(newRunnable(){
@Override
publicvoidrun(){
mButtonFlightTask.setEnabled(true);
mButtonSettingRoute.setEnabled(true);
mButtonFileManagement.setEnabled(true);
}
});
}

@Override
publicvoidonFailure(DJIErrordjiError){

}
});
}

}

上面的代码就要进行第一次注册登录了,当然你不需要自己去设计登录注册页面,大疆会调取自己的登录注册页面供你使用。

952b64b6-05ed-11ee-962d-dac502259ad0.png安装提示注册登录即可。

上面的这些做完后,恭喜你!现在,您的移动应用程序和飞机可以在中国使用而没有任何问题。换句话说,您的应用程序现在可以看到飞机的视频流,并且飞行将不仅限于直径为100m和高度为30m的圆柱体区域。

3飞行界面使用

虽然说可以正常飞行了,但是飞行需要设计飞行界面。那么创建一下飞行界面的UI及逻辑处理文件。逻辑处理文件中包含了获取飞机的实时姿态信息,代码中有注释内容,描述的内容就不多说了。

导入UX SDK依赖

上一节有说过集成部分,其中内容有导入UxSDk 的操作,这里再顺便提一下。再build.gradle文件中加入implementation "com.dji4.16"依赖,等待安装即可。

设计界面UI

创建MainActivity文件及activity_main.xml。




 














 
















































 



 






























 










 







@Layout(R.layout.activity_main)
publicclassMainActivityextendsBaseActivityimplementsView.OnClickListener{

@BindView(R.id.img_live)
ImageViewmImageViewLive;

privateMapWidgetmapWidget;
privateDJIMapaMap;
privateViewGroupparentView;
privateFPVWidgetfpvWidget;
privateFPVWidgetsecondaryFPVWidget;
privateRelativeLayoutprimaryVideoView;
privateFrameLayoutsecondaryVideoView;
privatebooleanisMapMini=true;
privateStringliveShowUrl="";

privateintheight;
privateintwidth;
privateintmargin;
privateintdeviceWidth;
privateintdeviceHeight;

privateSharedPreUtilsmSharedPreUtils;
//unix时间戳
privateStringdateStr="";
//飞行器管理器
privateFlightControllercontroller;
//经纬度
privatedoublelat=0,lon=0;
//高度
privatefloathigh=0;
//飞机的姿态
privateAttitudeattitude;
//俯仰角、滚转、偏航值
privatedoublepitch=0,roll=0,yaw=0;
//飞机的速度
privatefloatvelocity_X=0,velocity_Y=0,velocity_Z=0;
//飞机/控制器电池管理器
privateBatterybattery;
//电池电量、温度
privateintpower=0;
privatefloattemperature=0;
//云台管理器
privateGimbalgimbal;
//云台的姿态
privatedji.common.gimbal.Attitudeg_attitude;
//俯仰角、滚转、偏航值
privatedoubleg_pitch=0,g_roll=0,g_yaw=0;

privateCameracamera;
privateListlens=newArrayList<>();

privateListdjiList=newArrayList<>();

//手柄控制器
privateHandheldControllerhandheldController;
//手柄电量
privateinth_power=0;

privatestaticListlist=newArrayList<>();

privatestaticListgetList=newArrayList<>();

privateMediaManagermMediaManager;

privateMediaManager.FileListStatecurrentFileListState=MediaManager.FileListState.UNKNOWN;

privateListarrayList=newArrayList<>();

privateListstartList=newArrayList<>();

privateListendList=newArrayList<>();

privatebooleanisStartLive=false;

privatebooleanisFlying=false;

privatebooleanstart=false;

privateBaseProductmProduct;

privateStringposName="";

//webSocket
privateJWebSocketClientclient;
privateMapparams=newHashMap<>();
MapmapData=newHashMap<>();

@Override
protectedvoidonCreate(BundlesavedInstanceState){
super.onCreate(savedInstanceState);
height=ToolKit.dip2px(this,100);
width=ToolKit.dip2px(this,150);
margin=ToolKit.dip2px(this,12);

WindowManagerwindowManager=(WindowManager)getSystemService(Context.WINDOW_SERVICE);
finalDisplaydisplay=windowManager.getDefaultDisplay();
PointoutPoint=newPoint();
display.getRealSize(outPoint);
deviceHeight=outPoint.y;
deviceWidth=outPoint.x;
parentView=(ViewGroup)findViewById(R.id.root_view);
fpvWidget=findViewById(R.id.fpv_widget);
fpvWidget.setOnClickListener(newView.OnClickListener(){
@Override
publicvoidonClick(Viewview){
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(newView.OnClickListener(){
@Override
publicvoidonClick(Viewview){
swapVideoSource();
}
});
if(VideoFeeder.getInstance()!=null){
//Ifsecondaryvideofeedisalreadyinitialized,getvideosource
updateSecondaryVideoVisibility(VideoFeeder.getInstance().getSecondaryVideoFeed().getVideoSource()!=PhysicalSource.UNKNOWN);
//Ifsecondaryvideofeedisnotyetinitialized,waitforactivestatus
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(newMapWidget.OnMapReadyListener(){
@Override
publicvoidonMapReady(@NonNullDJIMapdjiMap){
djiMap.setOnMapClickListener(newDJIMap.OnMapClickListener(){
@Override
publicvoidonMapClick(DJILatLnglatLng){
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);
}

Timertimer=newTimer();
timer.schedule(newTimerTask(){
@Override
publicvoidrun(){
Messagemsg=newMessage();
if(isFlying&&!start){
start=true;


}
if(!isFlying&&start){
start=false;

}
if(isFlying&&high>=0){
msg.what=1;
}
mHandler.sendMessage(msg);
}
},200,200);
}

HandlermHandler=newHandler(){
@RequiresApi(api=Build.VERSION_CODES.O)
@Override
publicvoidhandleMessage(@NonNullMessagemsg){
switch(msg.what){
case1:
Longtime=System.currentTimeMillis();
// MyLog.d("时间:"+time);
RecordModulemodule=newRecordModule(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;
case2:
MyLog.d("飞机移动的数据:"+msg.obj.toString());
ControlModulecontrol=GsonUtil.GsonToBean(msg.obj.toString(),ControlModule.class);
if(controller!=null&&isFlying){
if(control.getContent().isBack()){
controller.sendVirtualStickFlightControlData(newFlightControlData(-10,0,0,0),null);
}
if(control.getContent().isFront()){
controller.sendVirtualStickFlightControlData(newFlightControlData(10,0,0,0),null);
}
if(control.getContent().isDown()){
controller.sendVirtualStickFlightControlData(newFlightControlData(0,0,0,-4),null);
}
if(control.getContent().isUp()){
controller.sendVirtualStickFlightControlData(newFlightControlData(0,0,0,4),null);
}
if(control.getContent().isLeft()){
controller.sendVirtualStickFlightControlData(newFlightControlData(0,-10,0,0),null);
}
if(control.getContent().isRight()){
controller.sendVirtualStickFlightControlData(newFlightControlData(0,10,0,0),null);
}
}else{
MyLog.d("controller控制器为空");
}
break;
}
}
};

@Override
publicvoidinitViews(){
mMediaManager=ReceiverApplication.getCameraInstance().getMediaManager();
getFileList("start");
}

@Override
publicvoidonComplete(Stringurl,StringjsonStr){
super.onComplete(url,jsonStr);

}
@Override
publicvoidinitDatas(){

}

privatevoidonViewClick(Viewview){
if(view==fpvWidget&&!isMapMini){
resizeFPVWidget(RelativeLayout.LayoutParams.MATCH_PARENT,RelativeLayout.LayoutParams.MATCH_PARENT,0,0);
reorderCameraCapturePanel();
ResizeAnimationmapViewAnimation=newResizeAnimation(mapWidget,deviceWidth,deviceHeight,width,height,margin);
mapWidget.startAnimation(mapViewAnimation);
isMapMini=true;
}elseif(view==mapWidget&&isMapMini){
hidePanels();
resizeFPVWidget(width,height,margin,12);
reorderCameraCapturePanel();
ResizeAnimationmapViewAnimation=newResizeAnimation(mapWidget,width,height,deviceWidth,deviceHeight,0);
mapWidget.startAnimation(mapViewAnimation);
isMapMini=false;
}
}

privatevoidresizeFPVWidget(intwidth,intheight,intmargin,intfpvInsertPosition){
RelativeLayout.LayoutParamsfpvParams=(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);
}

privatevoidreorderCameraCapturePanel(){
ViewcameraCapturePanel=findViewById(R.id.CameraCapturePanel);
parentView.removeView(cameraCapturePanel);
parentView.addView(cameraCapturePanel,isMapMini?9:13);
}

privatevoidswapVideoSource(){
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);
}
}

privatevoidupdateSecondaryVideoVisibility(booleanisActive){
if(isActive){
secondaryVideoView.setVisibility(View.VISIBLE);
}else{
secondaryVideoView.setVisibility(View.GONE);
}
}

privatevoidhidePanels(){
//Thesepanelsappearbasedonkeysfromthedroneitself.
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);
}

//Thesepanelshavebuttonsthattogglethem,socallthemethodstomakesurethebuttonstateiscorrect.
CameraControlsWidgetcontrolsWidget=findViewById(R.id.CameraCapturePanel);
controlsWidget.setAdvancedPanelVisibility(false);
controlsWidget.setExposurePanelVisibility(false);

//Thesepanelsdon'thaveabuttonstate,sowecanjusthidethem.
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
protectedvoidonResume(){
super.onResume();
//Hideboththenavigationbarandthestatusbar.
ViewdecorView=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();
}elseif(!client.isOpen()){
reconnectWs();//进入页面发现断开开启重连
}
}

@Override
protectedvoidonStop(){
super.onStop();
MyLog.e("``````````````````````````````onStop");
}

@Override
protectedvoidonPause(){
mapWidget.onPause();
super.onPause();
}

@Override
protectedvoidonDestroy(){
mapWidget.onDestroy();
super.onDestroy();
MyLog.e("`````````````````````````onDestroy");
closeConnect();
}

@Override
protectedvoidrequestData(){

}

@Override
protectedvoidonSaveInstanceState(BundleoutState){
super.onSaveInstanceState(outState);
mapWidget.onSaveInstanceState(outState);
}

@Override
publicvoidonLowMemory(){
super.onLowMemory();
mapWidget.onLowMemory();
}

privateclassResizeAnimationextendsAnimation{

privateViewmView;
privateintmToHeight;
privateintmFromHeight;

privateintmToWidth;
privateintmFromWidth;
privateintmMargin;

privateResizeAnimation(Viewv,intfromWidth,intfromHeight,inttoWidth,inttoHeight,intmargin){
mToHeight=toHeight;
mToWidth=toWidth;
mFromHeight=fromHeight;
mFromWidth=fromWidth;
mView=v;
mMargin=margin;
setDuration(300);
}

@Override
protectedvoidapplyTransformation(floatinterpolatedTime,Transformationt){
floatheight=(mToHeight-mFromHeight)*interpolatedTime+mFromHeight;
floatwidth=(mToWidth-mFromWidth)*interpolatedTime+mFromWidth;
RelativeLayout.LayoutParamsp=(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
publicvoidonClick(Viewv){
switch(v.getId()){
caseR.id.img_live:
params.clear();
mapData.clear();
if(!isStartLive){
if(!TextUtils.isEmpty(mSharedPreUtils.getStringSharePre("rtmp_url"))){
liveShowUrl=mSharedPreUtils.getStringSharePre("rtmp_url")+trajectoryId;
//LiveModulemodule=newLiveModule("liveStreamStateChanged","plane",planeId,true,trajectoryId+"");
MyLog.d("地址:"+liveShowUrl);
startLiveShow();
isStartLive=true;
showToast("开始推流");
}else{
showToast("请先进行系统设置(RTMP)。");
}
}else{
stopLiveShow();
isStartLive=false;
}
break;
caseR.id.img_show_back:
//controller=null;
closeConnect();
MainActivity.this.finish();
break;
}
}

privatebooleanisLiveStreamManagerOn(){
if(DJISDKManager.getInstance().getLiveStreamManager()==null){
returnfalse;
}
returntrue;
}

privatevoidstartLiveShow(){
if(!isLiveStreamManagerOn()){
return;
}
if(DJISDKManager.getInstance().getLiveStreamManager().isStreaming()){
return;
}
newThread(){
@Override
publicvoidrun(){
DJISDKManager.getInstance().getLiveStreamManager().setLiveUrl(liveShowUrl);
DJISDKManager.getInstance().getLiveStreamManager().setAudioStreamingEnabled(true);
intresult=DJISDKManager.getInstance().getLiveStreamManager().startStream();
DJISDKManager.getInstance().getLiveStreamManager().setStartTime();
}
}.start();
}

privatevoidstopLiveShow(){
AlertDialog.BuilderBuilder=newAlertDialog.Builder(MainActivity.this);
Builder.setTitle("提示");
Builder.setMessage("是否结束推流?");
Builder.setIcon(android.R.drawable.ic_dialog_alert);
Builder.setPositiveButton("确定",newDialogInterface.OnClickListener(){
@Override
publicvoidonClick(DialogInterfacedialog,intwhich){
if(!isLiveStreamManagerOn()){
return;
}
DJISDKManager.getInstance().getLiveStreamManager().stopStream();

showToast("结束推流");
}
});
Builder.setNegativeButton("取消",null);
Builder.show();
}


//获取飞机信息、云台信息
protectedBroadcastReceivermReceiver=newBroadcastReceiver(){
@Override
publicvoidonReceive(Contextcontext,Intentintent){
BaseProductmProduct=ReceiverApplication.getProductInstance();
if(null!=mProduct&&mProduct.isConnected()){
flyInformation(mProduct);
batteryInformation(mProduct);
cameraInformation(mProduct);
camera(mProduct);
//MobileRemote(mProduct);
}
}
};

//privatevoidMobileRemote(BaseProductmProduct){
//if(null!=mProduct&&mProduct.isConnected()){
//mobileController=((Aircraft)mProduct).getMobileRemoteController();
//}
//}

//获取飞机信息
privatevoidflyInformation(BaseProductmProduct){
if(null!=mProduct&&mProduct.isConnected()){
controller=((Aircraft)mProduct).getFlightController();
}
if(controller!=null){
controller.setStateCallback(newFlightControllerState.Callback(){
@RequiresApi(api=Build.VERSION_CODES.O)
@Override
publicvoidonUpdate(@NonNullFlightControllerStateflightControllerState){
//纬度、经度、高度、俯仰角、滚转、偏航值、速度
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,newCommonCallbacks.CompletionCallback(){
//@Override
//publicvoidonResult(DJIErrordjiError){
//MyLog.d(djiError.getDescription());
//}
//});
//controller.setTripodModeEnabled(false,newCommonCallbacks.CompletionCallback(){
//@Override
//publicvoidonResult(DJIErrordjiError){
//MyLog.d(djiError.getDescription());
//}
//});
//controller.setFlightOrientationMode(FlightOrientationMode.AIRCRAFT_HEADING,newCommonCallbacks.CompletionCallback(){
//@Override
//publicvoidonResult(DJIErrordjiError){
//MyLog.d(djiError.getDescription());
//if(djiError==null){
//if(controller.isVirtualStickControlModeAvailable()){
//
//}else{
//MyLog.d("虚拟摇杆模式不可用");
//}
//}
//}
//});

}
}

//电池信息
privatevoidbatteryInformation(BaseProductmProduct){
if(null!=mProduct&&mProduct.isConnected()){
battery=((Aircraft)mProduct).getBattery();
}
if(battery!=null){
battery.setStateCallback(newBatteryState.Callback(){
@Override
publicvoidonUpdate(BatteryStatebatteryState){
//电池电量
power=batteryState.getChargeRemainingInPercent();
//电池温度
temperature=batteryState.getTemperature();
}
});
}
}

//云台信息
privatevoidcameraInformation(BaseProductmProduct){
if(null!=mProduct&&mProduct.isConnected()){
gimbal=((Aircraft)mProduct).getGimbal();
}
if(gimbal!=null){
gimbal.setMode(GimbalMode.YAW_FOLLOW,null);
gimbal.setStateCallback(newGimbalState.Callback(){
@Override
publicvoidonUpdate(@NonNullGimbalStategimbalState){
//俯仰角、滚转、偏航值
g_attitude=gimbalState.getAttitudeInDegrees();
g_pitch=g_attitude.getPitch();
g_roll=g_attitude.getRoll();
g_yaw=g_attitude.getYaw();
}
});
}
}

privatevoidcamera(BaseProductmProduct){
if(null!=mProduct&&mProduct.isConnected()){
camera=((Aircraft)mProduct).getCamera();
}
if(camera!=null){
//camera.setVideoCaptionEnabled(true,newCommonCallbacks.CompletionCallback(){
//@Override
//publicvoidonResult(DJIErrordjiError){
//MyLog.d("VideoCaptionEnabled"+djiError.toString());
//}
//});
//camera.setMediaFileCustomInformation(projectId+","+trajectoryId,newCommonCallbacks.CompletionCallback(){
//@Override
//publicvoidonResult(DJIErrordjiError){
// MyLog.d("自定义信息:"+djiError.toString());
//}
//});
camera.setSystemStateCallback(newSystemState.Callback(){
@RequiresApi(api=Build.VERSION_CODES.O)
@Override
publicvoidonUpdate(@NonNullSystemStatesystemState){
if(systemState.getMode().equals(SettingsDefinitions.CameraMode.SHOOT_PHOTO)){
if(systemState.isStoringPhoto()){
dateStr=Long.toString(System.currentTimeMillis());
list.add(newDeviceInfo(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;
}
}elseif(systemState.getMode().equals(SettingsDefinitions.CameraMode.RECORD_VIDEO)){
if(systemState.isRecording()){
try{
dateStr=Long.toString(System.currentTimeMillis());
list.add(newDeviceInfo(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(InterruptedExceptione){
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(newRunnable(){
@Override
publicvoidrun(){
getFileList("end");
}
});
}
}
}
}
});
}
}

//遥控器信息
privatevoidhandheldInforamation(BaseProductmProduct){
if(null!=mProduct&&mProduct.isConnected()){
handheldController=((HandHeld)mProduct).getHandHeldController();
}
if(handheldController!=null){
handheldController.setPowerModeCallback(newPowerMode.Callback(){
@Override
publicvoidonUpdate(PowerModepowerMode){
switch(powerMode){
caseON:
Batterybattery=((HandHeld)mProduct).getBattery();
battery.setStateCallback(newBatteryState.Callback(){
@Override
publicvoidonUpdate(BatteryStatebatteryState){
h_power=batteryState.getChargeRemainingInPercent();
}
});
break;
}
}
});
}
}


@Override
publicbooleanonKeyDown(intkeyCode,KeyEventevent){
if(keyCode==KeyEvent.KEYCODE_BACK
&&event.getAction()==KeyEvent.ACTION_DOWN){
//closeConnect();
MainActivity.this.finish();
}
returnsuper.onKeyDown(keyCode,event);
}

}

完成后界面如下所示:95543fb2-05ed-11ee-962d-dac502259ad0.jpg

上面的工作完成后就可以在无人且宽阔的地方进行无人机飞行了。

4

多媒体资源的操作

多媒体文件操作,主要为多媒体文件的获取、查看、删除、下载的操作同样创建多媒体功能文件FileManagementActivity及activity_file_management.xml

activity_file_management.xml



































FileManagementActivity

@Layout(R.layout.activity_file_management)
publicclassFileManagementActivityextendsBaseActivityimplementsView.OnClickListener{

privatestaticfinalStringTAG=FileManagementActivity.class.getName();

@BindView(R.id.layout_file)
ViewmViewLayoutToolbar;
@BindView(R.id.tv_toolbar_title)
TextViewmTextViewToolbarTitle;
@BindView(R.id.ll_file)
LinearLayoutmLinearLayout;
@BindView(R.id.rg_file_management)
RadioGroupmRadioGroup;
@BindView(R.id.rv_file_management)
RecyclerViewmRecyclerView;
@BindView(R.id.img_show)
ImageViewmImageView;
@BindView(R.id.ll_video_btn)
LinearLayoutmLinearLayoutVideo;
@BindView(R.id.img_video_play)
ImageViewmImageViewVideoPlay;
@BindView(R.id.img_video_pause)
ImageViewmImageViewVideoPause;

privateFileListAdaptermListAdapter;
privateListList=newArrayList();
privateListmediaFileList=newArrayList();
privateMediaManagermMediaManager;
privateMediaManager.FileListStatecurrentFileListState=MediaManager.FileListState.UNKNOWN;
privateMediaManager.VideoPlaybackStatestate;
privateProgressDialogmLoadingDialog;
privateProgressDialogmDownloadDialog;
privateFetchMediaTaskSchedulerscheduler;
privateintlastClickViewIndex=-1;
privateintcurrentProgress=-1;
privateStringSavePath="";
privateViewlastClickView;
privatebooleanisResume=false;
privateSFTPUtilssftp;
privateSettingsDefinitions.StorageLocationstorageLocation;

@Override
publicvoidinitViews(){
mLinearLayout.setVisibility(View.VISIBLE);
mTextViewToolbarTitle.setText("文件管理");
mImageViewVideoPlay.setEnabled(true);
mImageViewVideoPause.setEnabled(false);
mRadioGroup.setOnCheckedChangeListener(newRadioGroup.OnCheckedChangeListener(){
@Override
publicvoidonCheckedChanged(RadioGroupgroup,intcheckedId){
List.clear();
mediaFileList.clear();
switch(checkedId){
caseR.id.rb_file_all:
getFileList(0);
mListAdapter.notifyDataSetChanged();
break;
caseR.id.rb_file_photo:
getFileList(1);
mListAdapter.notifyDataSetChanged();
break;
caseR.id.rb_file_video:
getFileList(2);
mListAdapter.notifyDataSetChanged();
break;
}
}
});

LinearLayoutManagerlayoutManager=newLinearLayoutManager(FileManagementActivity.this,RecyclerView.VERTICAL,false);
mRecyclerView.setLayoutManager(layoutManager);

//InitFileListAdapter
mListAdapter=newFileListAdapter();
mRecyclerView.setAdapter(mListAdapter);

//InitLoadingDialog
mLoadingDialog=newProgressDialog(FileManagementActivity.this);
mLoadingDialog.setMessage("请等待...");
mLoadingDialog.setCanceledOnTouchOutside(false);
mLoadingDialog.setCancelable(false);

//InitDownloadDialog
mDownloadDialog=newProgressDialog(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(newDialogInterface.OnCancelListener(){
@Override
publicvoidonCancel(DialogInterfacedialog){
if(mMediaManager!=null){
mMediaManager.exitMediaDownloading();
}
}
});
sftp=newSFTPUtils("49.4.79.249","uav","uavHHch@YREC.cn");
ReceiverApplication.getAircraftInstance().getCamera().setStorageStateCallBack(newStorageState.Callback(){
@Override
publicvoidonUpdate(@NonNull@NotNullStorageStatestorageState){
if(storageState.isInserted()){
storageLocation=SettingsDefinitions.StorageLocation.SDCARD;
ReceiverApplication.getAircraftInstance().getCamera().setStorageLocation(SettingsDefinitions.StorageLocation.SDCARD,newCommonCallbacks.CompletionCallback(){
@Override
publicvoidonResult(DJIErrordjiError){
}
});
}else{
storageLocation=SettingsDefinitions.StorageLocation.INTERNAL_STORAGE;
ReceiverApplication.getAircraftInstance().getCamera().setStorageLocation(SettingsDefinitions.StorageLocation.INTERNAL_STORAGE,newCommonCallbacks.CompletionCallback(){
@Override
publicvoidonResult(DJIErrordjiError){
}
});
}
}
});
}

@Override
publicvoidinitDatas(){

}

@Override
protectedvoidrequestData(){

}

@Override
publicvoidonComplete(Stringurl,StringjsonStr){
super.onComplete(url,jsonStr);
switch(url){
casePOST_VIDEO_INFO:
break;
default:
getVideoJson(jsonStr);
break;
}
}

privatevoidgetVideoJson(StringjsonStr){
VideoModulemodule=GsonUtil.GsonToBean(jsonStr,VideoModule.class);
if(module.getCode()==200&&module.getRows().size()==1){
runOnUiThread(newRunnable(){
@Override
publicvoidrun(){
UpdateFileModulefileModule=newUpdateFileModule(module.getRows().get(0).getId(),"/mnt/uavFtpFolder/"+module.getRows().get(0).getFileName());
http.getHttp(POST_VIDEO_INFO,"PUT",GsonUtil.GsonString(fileModule));
}
});
}
}

@Override
protectedvoidonResume(){
super.onResume();
initMediaManager();
}

@Override
protectedvoidonPause(){
super.onPause();
}

@Override
protectedvoidonStop(){
super.onStop();
}


@Override
protectedvoidonDestroy(){
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();
}

privatevoidshowProgressDialogs(){
runOnUiThread(newRunnable(){
publicvoidrun(){
if(mLoadingDialog!=null){
mLoadingDialog.show();
}
}
});
}

privatevoidhideProgressDialog(){
runOnUiThread(newRunnable(){
publicvoidrun(){
if(null!=mLoadingDialog&&mLoadingDialog.isShowing()){
mLoadingDialog.dismiss();
}
}
});
}

privatevoidShowDownloadProgressDialog(){
if(mDownloadDialog!=null){
runOnUiThread(newRunnable(){
publicvoidrun(){
mDownloadDialog.incrementProgressBy(-mDownloadDialog.getProgress());
mDownloadDialog.show();
}
});
}
}

privatevoidHideDownloadProgressDialog(){
if(null!=mDownloadDialog&&mDownloadDialog.isShowing()){
runOnUiThread(newRunnable(){
publicvoidrun(){
mDownloadDialog.dismiss();
}
});
}
}

privatevoidinitMediaManager(){
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(newMediaManager.VideoPlaybackStateListener(){
@Override
publicvoidonUpdate(MediaManager.VideoPlaybackStatevideoPlaybackState){
state=videoPlaybackState;
if(videoPlaybackState.getPlaybackStatus()==MediaFile.VideoPlaybackStatus.STOPPED){
runOnUiThread(newRunnable(){
@Override
publicvoidrun(){
//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();
}

}elseif(null!=ReceiverApplication.getCameraInstance()
&&!ReceiverApplication.getCameraInstance().isMediaDownloadModeSupported()){
showToasts("不支持媒体下载模式");
}
}
return;
}

privatevoidgetFileList(intindex){
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();
//Resetdata
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){
case0:
for(inti=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;
}
return0;
});
}
scheduler.resume(error->{
if(error==null){
getThumbnails();
}
});
}else{
hideProgressDialog();
showToasts("获取媒体文件列表失败:"+djiError.getDescription());
}
});
}
}
}

privatevoidgetThumbnails(){
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
publicintgetItemCount(){
if(mediaFileList!=null){
returnmediaFileList.size();
}
return0;
}

@Override
publicItemHolderonCreateViewHolder(ViewGroupparent,intviewType){
Viewview=LayoutInflater.from(parent.getContext()).inflate(R.layout.media_info_item,parent,false);
returnnewItemHolder(view);
}

@Override
publicvoidonBindViewHolder(ItemHoldermItemHolder,finalintindex){

finalMediaFilemediaFile=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);

}
}
}

privateView.OnClickListeneritemViewOnClickListener=newView.OnClickListener(){
@Override
publicvoidonClick(Viewv){
lastClickViewIndex=(int)(v.getTag());
if(lastClickView!=null&&lastClickView!=v){
lastClickView.setSelected(false);
}
v.setSelected(true);
lastClickView=v;
MediaFileselectedMedia=mediaFileList.get(lastClickViewIndex);
if(selectedMedia!=null&&mMediaManager!=null){
addMediaTask(selectedMedia);
}
}
};

privatevoidaddMediaTask(finalMediaFilemediaFile){
finalFetchMediaTaskSchedulerscheduler=mMediaManager.getScheduler();
finalFetchMediaTasktask=
newFetchMediaTask(mediaFile,FetchMediaTaskContent.PREVIEW,newFetchMediaTask.Callback(){
@Override
publicvoidonUpdate(finalMediaFilemediaFile,FetchMediaTaskContentfetchMediaTaskContent,DJIErrorerror){
if(null==error){
if(mediaFile.getPreview()!=null){
runOnUiThread(newRunnable(){
@Override
publicvoidrun(){
finalBitmappreviewBitmap=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
privateMediaManager.FileListStateListenerupdateFileListStateListener=state->currentFileListState=state;


privatevoiddeleteFileByIndex(finalintindex){
ArrayListfileToDelete=newArrayList();
if(mediaFileList.size()>index){
fileToDelete.add(mediaFileList.get(index));
mMediaManager.deleteFiles(fileToDelete,newCommonCallbacks.CompletionCallbackWithTwoParam,DJICameraError>(){
@Override
publicvoidonSuccess(Listx,DJICameraErrory){
DJILog.e(TAG,"Deletefilesuccess");
runOnUiThread(newRunnable(){
publicvoidrun(){
mediaFileList.remove(index);
//Resetselectview
lastClickViewIndex=-1;
lastClickView=null;
//UpdaterecyclerView
mListAdapter.notifyDataSetChanged();
}
});
}

@Override
publicvoidonFailure(DJIErrorerror){
showToasts("删除失败");
}
});
}
}

privatevoiddownloadFileByIndex(finalintindex){

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;
}elseif(mediaFileList.get(index).getMediaType()==MediaFile.MediaType.JPEG){
SavePath=MyStatic.FLY_FILE_PHOTO;
}
FiledestDir=newFile(FileUtil.checkDirPath(SavePath));
mediaFileList.get(index).fetchFileData(destDir,null,newDownloadListener(){
@Override
publicvoidonFailure(DJIErrorerror){
HideDownloadProgressDialog();
showToasts("下载失败"+error.getDescription());
currentProgress=-1;
}

@Override
publicvoidonProgress(longtotal,longcurrent){
}

@Override
publicvoidonRateUpdate(longtotal,longcurrent,longpersize){
inttmpProgress=(int)(1.0*current/total*100);
if(tmpProgress!=currentProgress){
mDownloadDialog.setProgress(tmpProgress);
currentProgress=tmpProgress;
}
}

@Override
publicvoidonRealtimeDataUpdate(byte[]bytes,longl,booleanb){

}

@Override
publicvoidonStart(){
currentProgress=-1;
ShowDownloadProgressDialog();
}

@Override
publicvoidonSuccess(StringfilePath){
HideDownloadProgressDialog();
showToasts("下载成功"+":"+filePath);
currentProgress=-1;
}
});
//mediaFileList.get(index).fetchFileByteData(0,newDownloadListener(){
//@Override
//publicvoidonStart(){
//currentProgress=-1;
//ShowDownloadProgressDialog();
//}
//
//@Override
//publicvoidonRateUpdate(longtotal,longcurrent,longpersize){
//inttmpProgress=(int)(1.0*current/total*100);
//if(tmpProgress!=currentProgress){
//mDownloadDialog.setProgress(tmpProgress);
//currentProgress=tmpProgress;
//}
//}
//
//@Override
//publicvoidonRealtimeDataUpdate(byte[]bytes,longl,booleanb){
//byteToFile(bytes,FileUtil.checkDirPath(SavePath)+mediaFileList.get(index).getFileName());
//}
//
//@Override
//publicvoidonProgress(longl,longl1){
//
//}
//
//@Override
//publicvoidonSuccess(Strings){
//HideDownloadProgressDialog();
//showToasts("下载成功"+":"+s);
//currentProgress=-1;
//}
//
//@Override
//publicvoidonFailure(DJIErrordjiError){
//
//}
//});
}

publicstaticvoidbyteToFile(byte[]bytes,Stringpath)
{
try
{
//根据绝对路径初始化文件
FilelocalFile=newFile(path);
if(!localFile.exists())
{
localFile.createNewFile();
}
//输出流
OutputStreamos=newFileOutputStream(localFile);
os.write(bytes);
os.close();
}
catch(Exceptione)
{
e.printStackTrace();
}
}

privatevoidplayVideo(){
mImageView.setVisibility(View.INVISIBLE);
MediaFileselectedMediaFile=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(newRunnable(){
@Override
publicvoidrun(){
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
publicvoidonClick(Viewv){
switch(v.getId()){
caseR.id.img_back:
FileManagementActivity.this.finish();
break;
caseR.id.img_delete:
if(lastClickViewIndex>=0){
deleteFileByIndex(lastClickViewIndex);
}else{
showToasts("请先选择文件。");
}
break;
caseR.id.img_download:
if(lastClickViewIndex>=0){
downloadFileByIndex(lastClickViewIndex);
}else{
showToasts("请先选择文件。");
}
break;
caseR.id.img_upload:
if(lastClickViewIndex>=0){
uploadFileByIndex(lastClickViewIndex);
}else{
showToasts("请先选择文件。");
}
break;
caseR.id.img_video_play:

if(state.getPlaybackStatus()==MediaFile.VideoPlaybackStatus.STOPPED){
playVideo();
}elseif(state.getPlaybackStatus()==MediaFile.VideoPlaybackStatus.PAUSED){
mMediaManager.resume(error->{
if(null!=error){
showToasts("继续播放失败:"+error.getDescription());
}else{
DJILog.e(TAG,"继续播放成功");
runOnUiThread(newRunnable(){
@Override
publicvoidrun(){
mImageViewVideoPlay.setEnabled(false);
mImageViewVideoPause.setEnabled(true);
}
});
}
});
}
break;
caseR.id.img_video_pause:
mMediaManager.pause(error->{
if(null!=error){
showToasts("暂停播放失败:"+error.getDescription());
}else{
DJILog.e(TAG,"暂停播放成功");
runOnUiThread(newRunnable(){
@Override
publicvoidrun(){
mImageViewVideoPlay.setEnabled(true);
mImageViewVideoPause.setEnabled(false);
}
});
}
});

break;
caseR.id.img_video_stop:
mMediaManager.stop(error->{
if(null!=error){
showToasts("停止播放失败:"+error.getDescription());
}else{
DJILog.e(TAG,"停止播放成功");
}
});
break;
}
}

privatevoiduploadFileByIndex(intindex){

if((mediaFileList.get(index).getMediaType()==MediaFile.MediaType.MOV)||(mediaFileList.get(index).getMediaType()==MediaFile.MediaType.MP4)){
showProgressDialog("正在上传");
newThread(newRunnable(){
@Override
publicvoidrun(){
booleanisConnect=sftp.connect().isConnected();
if(isConnect){
booleanisUpdate=sftp.uploadFile("/mnt/uavFtpFolder/",mediaFileList.get(index).getFileName(),FLY_FILE_VIDEO,mediaFileList.get(index).getFileName());
if(isUpdate){
runOnUiThread(newRunnable(){
@Override
publicvoidrun(){
removeProgressDialog();
http.getHttp(GET_VIDEO_INFO+"?fileName="+mediaFileList.get(index).getFileName(),"GET");
}
});
sftp.disconnect();
}else{
runOnUiThread(newRunnable(){
@Override
publicvoidrun(){
showErrorTip("上传失败");
removeProgressDialog();
}
});

}
}else{
runOnUiThread(newRunnable(){
@Override
publicvoidrun(){
showErrorTip("服务器连接失败");
removeProgressDialog();
}
});
}
}
}).start();
}else{
showToasts("当前仅支持视频上传,请选择视频文件!");
}
}

privatebooleanisMavicAir2(){
BaseProductbaseProduct=ReceiverApplication.getProductInstance();
if(baseProduct!=null){
returnbaseProduct.getModel()==Model.MAVIC_AIR_2;
}
returnfalse;
}

privatebooleanisM300(){
BaseProductbaseProduct=ReceiverApplication.getProductInstance();
if(baseProduct!=null){
returnbaseProduct.getModel()==Model.MATRICE_300_RTK;
}
returnfalse;
}
}

运行后界面如下:
9590b1cc-05ed-11ee-962d-dac502259ad0.jpg

审核编辑:汤梓红

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • Mobile
    +关注

    关注

    0

    文章

    515

    浏览量

    26342
  • 遥控器
    +关注

    关注

    18

    文章

    815

    浏览量

    64249
  • 应用程序
    +关注

    关注

    37

    文章

    3136

    浏览量

    56405
  • 无人机
    +关注

    关注

    224

    文章

    9887

    浏览量

    174826
  • SDK
    SDK
    +关注

    关注

    3

    文章

    966

    浏览量

    44718

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

文章出处:【微信号:美男子玩编程,微信公众号:美男子玩编程】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    【Aworks申请】开放式无人机地面基站

    申请理由:我们是在校大学生EDA兴趣团队,正在设计制作无人机项目。我们发现,现在无人机只能通过遥控器或者电脑上位机控制飞行。所以,我们试图开发一个通用式地面基站,开放API和视频数据流
    发表于 06-27 08:59

    【云智易申请】智能无人机通信

    申请理由:本次项目是基于STM32做无人机,主要用WiFi实现无人机遥控器之间通信,无人机的电机我们可以用云智易开发板上面的电机进行调试,
    发表于 08-07 11:02

    【MiCOKit申请】开放式无人机地面基站

    申请理由:我们是在校大学生EDA兴趣团队,正在设计制作无人机项目。我们发现,现在无人机只能通过遥控器或者电脑上位机控制飞行。所以,我们试图开发一个通用式地面基站,开放API和视频数据流
    发表于 08-10 13:04

    无人机遥控方向控制问题

    前段时间我弟弟买了个遥控无人机玩具,但是我发现一个问题。该无人机方向控制有问题,假设无人机有四个电机,分别为A,B,C,D,遥控器四个按键1
    发表于 05-10 11:26

    普宙GDU O2无人机2再战大

    遥控器方面也不是尽善尽美。而GDU O2能把遥控器无人机组合在一起,这也是GDU O2独有的亮点,把收纳便携几乎做到了极致。GDU O
    发表于 08-28 18:32

    无人机评测:普宙O2航拍无人机智能操作模式初体验

    的设计不容忽视。GDU O2给出的处理方案是云台上方带有精准的双目避障系统,在同类型的航拍无人机中只有大的Mavic Pro带有类似设计。O2在前飞遇到障碍物时会自动悬停,哪怕是
    发表于 08-28 18:38

    stm32四轴无人机遥控器资料

    stm32四轴无人机遥控器资料
    发表于 06-09 23:16

    无人机怎么悬停

    `  谁能阐述下大无人机怎么悬停?`
    发表于 08-27 15:13

    DJI大创新推出首款农业无人机

    全球飞行影像系统的开拓者和领导者DJI大创新今日宣布推出一款智能农业喷洒防治无人机——大MG-1农业植保机,标志着大创新正式进入农业无人机
    发表于 05-12 07:22

    【快速上手教程6】疯壳·开源编队无人机-遥控器固件烧写

    COCOFLY 教程——疯壳·无人机·系列遥控器固件烧写 图1 一、遥控器固件烧写 这里的固件
    发表于 05-25 11:49

    【快速上手教程6】疯壳·开源编队无人机-遥控器固件烧写

    COCOFLY 教程——疯壳·无人机·系列遥控器固件烧写 图1 一、遥控器固件烧写 这里的固件
    发表于 07-07 10:05

    【疯壳·无人机教程6】开源编队无人机-遥控器固件烧写

    COCOFLY 教程——疯壳·无人机·系列遥控器固件烧写图1 一、遥控器固件烧写 这里的固件
    发表于 08-23 17:49

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

    刚刚结束了项目交付,趁热打铁分享一下这次遇到的新东西。首先了解一下大疆的无人机,它大致可以分为三级。
    的头像 发表于 06-07 09:53 681次阅读
    基于<b class='flag-5'>Mobile</b> <b class='flag-5'>SDK</b> <b class='flag-5'>V4</b>版<b class='flag-5'>固件</b><b class='flag-5'>开发</b>大疆<b class='flag-5'>无人机手机</b>端<b class='flag-5'>遥控器</b>(1)

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

    第三篇文章准备单独拿出来写,因为在大疆为人机的所有功能中,航线规划的功能最为复杂,也相当的繁琐,这里需要说仔细一点,可能会将代码进行多步分解。
    的头像 发表于 06-15 12:22 905次阅读
    基于<b class='flag-5'>Mobile</b> <b class='flag-5'>SDK</b> <b class='flag-5'>V4</b>版<b class='flag-5'>固件</b><b class='flag-5'>开发</b>大疆<b class='flag-5'>无人机手机</b>端<b class='flag-5'>遥控器</b>(3)

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

    相较与V4版本开发,V5版本有了更方便简介的方式。V5不仅再功能上与V4增加更多的功能,而且在功能的使用及API的调用也做了优化。虽然V5现在很新也在不断地迭代,但是不免会出现对一些飞行或者
    的头像 发表于 06-25 12:24 1346次阅读
    基于<b class='flag-5'>Mobile</b> <b class='flag-5'>SDK</b> V5版<b class='flag-5'>固件</b><b class='flag-5'>开发</b>大疆<b class='flag-5'>无人机手机</b>端<b class='flag-5'>遥控器</b>(4)