RM新时代网站-首页

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

基于Mobile SDK V4版固件開發(fā)大疆無人機手機端遙控器(2)

jf_Vqngj70R ? 來源:美男子玩編程 ? 2023-06-09 11:33 ? 次閱讀

上一篇文章(基于Mobile SDK V4版固件開發(fā)大疆無人機手機端遙控器(1))因為時間原因介紹了一部分內(nèi)容,如果已經(jīng)完成上一篇內(nèi)容的操作就可以進行下面功能方面的制作了。自己開發(fā)的APP功能不是很多,但是已經(jīng)將大疆無人機的常用功能進行了結(jié)合,同大家一起進行學(xué)習(xí)~

1應(yīng)用程序激活與綁定

如果在中國使用DJI飛行器固件,則需要使用該用戶的DJI帳戶激活控制DJI飛行器的移動應(yīng)用程序。這將確保大疆能根據(jù)飛行器的地理位置和用戶個人資料,為飛行器配置正確的地理空間信息和飛行功能集。激活系統(tǒng)的主要是:

中國用戶必須在每三個月至少登錄一次DJI帳戶以遍激活應(yīng)用程序。

激活信息將存儲在應(yīng)用程序中,直到用戶注銷為止。

登錄DJI帳號需要連接互聯(lián)網(wǎng)。

在中國境外,SDK會自動激活應(yīng)用程序,無需用戶登錄。

另外,中國用戶必須將飛機綁定到DJI官方app中的用戶帳戶。這僅需要一次。如果未激活應(yīng)用程序,未綁定飛機(如果需要)或使用舊版SDK(<4.1),則會禁用相機視頻流,并且飛行限制在直徑100m和高度30m的區(qū)域中,以確保飛機停留在視線范圍內(nèi)。

2為應(yīng)用程序創(chuàng)建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();
}
}

上面的代碼實現(xiàn)了綁定當(dāng)前APP,將后續(xù)需要用到的類函數(shù)封裝到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失敗,請檢查網(wǎng)絡(luò)是否可用");
//Toast.makeText(getApplicationContext(),"注冊sdk失敗,請檢查網(wǎng)絡(luò)是否可用",Toast.LENGTH_LONG).show();
}
});

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

@Override
publicvoidonProductDisconnect(){
Log.d("TAG","設(shè)備連接");
notifyStatusChange();
}

@Override
publicvoidonProductConnect(BaseProductbaseProduct){
Log.d("TAG",String.format("新設(shè)備連接:%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","設(shè)備連接已更改:"+isConnected);
notifyStatusChange();
}
});
}

Log.d("TAG",
String.format("設(shè)備改變key:%s,舊設(shè)備:%s,新設(shè)備:%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

上面的代碼是對BaseProduct、Aircraft和Camera類進行實例化,在后續(xù)使用中不用再去進行重復(fù)的實例化工作,減少內(nèi)存的消耗。

@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失敗,請檢查網(wǎng)絡(luò)是否可用");
}
Log.v(TAG,djiError.getDescription());
}

@Override
publicvoidonProductDisconnect(){
Log.d(TAG,"產(chǎn)品斷開連接");
//showToasts("產(chǎn)品斷開連接");

}

@Override
publicvoidonProductConnect(BaseProductbaseProduct){
Log.d(TAG,String.format("新產(chǎn)品連接:%s",baseProduct));
//showToasts("產(chǎn)品連接");

}

@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("改變設(shè)備Key:%s,"+"舊設(shè)備:%s,"+"新設(shè)備:%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){

}
});
}

}

上面的代碼就要進行第一次注冊登錄了,當(dāng)然你不需要自己去設(shè)計登錄注冊頁面,大疆會調(diào)取自己的登錄注冊頁面供你使用。

952b64b6-05ed-11ee-962d-dac502259ad0.png安裝提示注冊登錄即可。

上面的這些做完后,恭喜你!現(xiàn)在,您的移動應(yīng)用程序和飛機可以在中國使用而沒有任何問題。換句話說,您的應(yīng)用程序現(xiàn)在可以看到飛機的視頻流,并且飛行將不僅限于直徑為100m和高度為30m的圓柱體區(qū)域。

3飛行界面使用

雖然說可以正常飛行了,但是飛行需要設(shè)計飛行界面。那么創(chuàng)建一下飛行界面的UI及邏輯處理文件。邏輯處理文件中包含了獲取飛機的實時姿態(tài)信息,代碼中有注釋內(nèi)容,描述的內(nèi)容就不多說了。

導(dǎo)入UX SDK依賴

上一節(jié)有說過集成部分,其中內(nèi)容有導(dǎo)入UxSDk 的操作,這里再順便提一下。再build.gradle文件中加入implementation "com.dji4.16"依賴,等待安裝即可。

設(shè)計界面UI

創(chuàng)建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;
//經(jīng)緯度
privatedoublelat=0,lon=0;
//高度
privatefloathigh=0;
//飛機的姿態(tài)
privateAttitudeattitude;
//俯仰角、滾轉(zhuǎn)、偏航值
privatedoublepitch=0,roll=0,yaw=0;
//飛機的速度
privatefloatvelocity_X=0,velocity_Y=0,velocity_Z=0;
//飛機/控制器電池管理器
privateBatterybattery;
//電池電量、溫度
privateintpower=0;
privatefloattemperature=0;
//云臺管理器
privateGimbalgimbal;
//云臺的姿態(tài)
privatedji.common.gimbal.Attitudeg_attitude;
//俯仰角、滾轉(zhuǎn)、偏航值
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("飛機移動的數(shù)據(jù):"+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();//進入頁面發(fā)現(xiàn)斷開開啟重連
}
}

@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("請先進行系統(tǒng)設(shè)置(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("是否結(jié)束推流?");
Builder.setIcon(android.R.drawable.ic_dialog_alert);
Builder.setPositiveButton("確定",newDialogInterface.OnClickListener(){
@Override
publicvoidonClick(DialogInterfacedialog,intwhich){
if(!isLiveStreamManagerOn()){
return;
}
DJISDKManager.getInstance().getLiveStreamManager().stopStream();

showToast("結(jié)束推流");
}
});
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){
//緯度、經(jīng)度、高度、俯仰角、滾轉(zhuǎn)、偏航值、速度
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("經(jīng)度:"+ 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){
//俯仰角、滾轉(zhuǎn)、偏航值
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+"/照片數(shù)據(jù)")+"/"+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+"/視頻數(shù)據(jù)")+"/"+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

多媒體資源的操作

多媒體文件操作,主要為多媒體文件的獲取、查看、刪除、下載的操作同樣創(chuàng)建多媒體功能文件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("設(shè)置單張拍照模式失敗."+djiError1.getDescription());
}
});
}
});
}else{
ReceiverApplication.getCameraInstance().setMode(SettingsDefinitions.CameraMode.SHOOT_PHOTO,djiError->{
if(djiError!=null){
showToasts("設(shè)置拍照模式失敗."+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,"設(shè)備已斷開");
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,"設(shè)置cameraMode成功");
showProgressDialogs();
getFileList(0);
}else{
showToasts("設(shè)置cameraMode失敗");
}
});
}else{
ReceiverApplication.getCameraInstance().setMode(SettingsDefinitions.CameraMode.MEDIA_DOWNLOAD,error->{
if(error==null){
DJILog.e(TAG,"設(shè)置cameraMode成功");
showProgressDialogs();
getFileList(0);
}else{
showToasts("設(shè)置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{
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?{
@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("查找圖像內(nèi)容失敗:"+error.getDescription());
}
}
});

scheduler.resume(error->{
if(error==null){
scheduler.moveTaskToNext(task);
}else{
showToasts("恢復(fù)計劃程序失敗:"+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
{
//根據(jù)絕對路徑初始化文件
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("繼續(xù)播放失?。?+error.getDescription());
}else{
DJILog.e(TAG,"繼續(xù)播放成功");
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("服務(wù)器連接失敗");
removeProgressDialog();
}
});
}
}
}).start();
}else{
showToasts("當(dāng)前僅支持視頻上傳,請選擇視頻文件!");
}
}

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

審核編輯:湯梓紅

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • Mobile
    +關(guān)注

    關(guān)注

    0

    文章

    518

    瀏覽量

    26483
  • 遙控器
    +關(guān)注

    關(guān)注

    18

    文章

    836

    瀏覽量

    66056
  • 應(yīng)用程序
    +關(guān)注

    關(guān)注

    37

    文章

    3265

    瀏覽量

    57677
  • 無人機
    +關(guān)注

    關(guān)注

    229

    文章

    10420

    瀏覽量

    180117
  • SDK
    SDK
    +關(guān)注

    關(guān)注

    3

    文章

    1035

    瀏覽量

    45899

原文標(biāo)題:基于Mobile SDK V4版固件開發(fā)大疆無人機手機端遙控器(2)

文章出處:【微信號:美男子玩編程,微信公眾號:美男子玩編程】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦

    拆解大Mavic Air2無人機配套遙控器

    Mavic Air2遙控器內(nèi)部多使用螺絲或卡扣固定部件,伸縮式天線一體化手機支架將原來位于遙控器下方的手機移到了
    的頭像 發(fā)表于 07-21 13:37 ?2.8w次閱讀
    拆解大<b class='flag-5'>疆</b>Mavic Air<b class='flag-5'>2</b><b class='flag-5'>無人機</b>配套<b class='flag-5'>遙控器</b>

    無人機遙控方向控制問題

    前段時間我弟弟買了個遙控無人機玩具,但是我發(fā)現(xiàn)一個問題。該無人機方向控制有問題,假設(shè)無人機有四個電機,分別為A,B,C,D,遙控器四個按鍵1
    發(fā)表于 05-10 11:26

    普宙GDU O2無人機2再戰(zhàn)大

    遙控器方面也不是盡善盡美。而GDU O2能把遙控器無人機組合在一起,這也是GDU O2獨有的亮點,把收納便攜幾乎做到了極致。GDU O
    發(fā)表于 08-28 18:32

    stm32四軸無人機遙控器資料

    stm32四軸無人機遙控器資料
    發(fā)表于 06-09 23:16

    無人機怎么懸停

    `  誰能闡述下大無人機怎么懸停?`
    發(fā)表于 08-27 15:13

    【快速上手教程6】瘋殼·開源編隊無人機-遙控器固件燒寫

    COCOFLY 教程——瘋殼·無人機·系列遙控器固件燒寫 圖1 一、遙控器固件燒寫 這里的固件
    發(fā)表于 05-25 11:49

    【快速上手教程6】瘋殼·開源編隊無人機-遙控器固件燒寫

    COCOFLY 教程——瘋殼·無人機·系列遙控器固件燒寫 圖1 一、遙控器固件燒寫 這里的固件
    發(fā)表于 07-07 10:05

    【瘋殼·無人機教程6】開源編隊無人機-遙控器固件燒寫

    COCOFLY 教程——瘋殼·無人機·系列遙控器固件燒寫圖1 一、遙控器固件燒寫 這里的固件
    發(fā)表于 08-23 17:49

    CES 2019:大推出帶屏無人機遙控器 便攜式無線電源Yoolox亮相

    現(xiàn)如今航拍已成為年輕人的拍攝興趣,但智能手機好像并不是最理想控制航拍的遙控器。作為無人機生產(chǎn)廠家,大在今年的國際消費類電子產(chǎn)品展覽會上展出了專為Mavic
    的頭像 發(fā)表于 01-10 16:16 ?8036次閱讀

    發(fā)布沉浸式飛行無人機DJI FPV

    DJI 大創(chuàng)新正式發(fā)售沉浸式飛行無人機DJI FPV,并以套裝形式發(fā)售,其中包含飛行、遙控器、飛行眼鏡、1塊智能飛行電池、2對槳葉等配件
    的頭像 發(fā)表于 03-04 09:50 ?3840次閱讀

    音圈馬達裝置在大無人機的應(yīng)用

    音圈馬達助力的大將發(fā)布多款新品,大家都知道大是一家專業(yè)生產(chǎn)無人機的廠家,就在近日,大新公布的一份專利文件中,發(fā)現(xiàn)大已經(jīng)申請了一款新的
    發(fā)表于 08-31 15:55 ?731次閱讀

    基于Mobile SDK V4固件開發(fā)無人機手機遙控器(1)

    剛剛結(jié)束了項目交付,趁熱打鐵分享一下這次遇到的新東西。首先了解一下大無人機,它大致可以分為三級。
    的頭像 發(fā)表于 06-07 09:53 ?1148次閱讀
    基于<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'>開發(fā)</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固件開發(fā)無人機手機遙控器(3)

    第三篇文章準(zhǔn)備單獨拿出來寫,因為在大人機的所有功能中,航線規(guī)劃的功能最為復(fù)雜,也相當(dāng)?shù)姆爆崳@里需要說仔細(xì)一點,可能會將代碼進行多步分解。
    的頭像 發(fā)表于 06-15 12:22 ?1542次閱讀
    基于<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'>開發(fā)</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版固件開發(fā)無人機手機遙控器(4)

    相較與V4版本開發(fā),V5版本有了更方便簡介的方式。V5不僅再功能上與V4增加更多的功能,而且在功能的使用及API的調(diào)用也做了優(yōu)化。雖然
    的頭像 發(fā)表于 06-25 12:24 ?2574次閱讀
    基于<b class='flag-5'>Mobile</b> <b class='flag-5'>SDK</b> <b class='flag-5'>V</b>5版<b class='flag-5'>固件</b><b class='flag-5'>開發(fā)</b>大<b class='flag-5'>疆</b><b class='flag-5'>無人機手機</b><b class='flag-5'>端</b><b class='flag-5'>遙控器</b>(<b class='flag-5'>4</b>)

    基于Mobile SDK V5版固件開發(fā)無人機手機遙控器(5)

    v5.x版本的功能與v4.x基本相同,都是獲取飛機的姿態(tài)信息、獲取無人機多媒體文件、操作多媒體文件、航線規(guī)劃等。不過在上一章節(jié)中也大致說了一些兩個版本的中API的差別,下面是根據(jù)一些API使用所完成的一些功能,因為項目原因只能提
    的頭像 發(fā)表于 07-07 12:21 ?2302次閱讀
    基于<b class='flag-5'>Mobile</b> <b class='flag-5'>SDK</b> <b class='flag-5'>V</b>5版<b class='flag-5'>固件</b><b class='flag-5'>開發(fā)</b>大<b class='flag-5'>疆</b><b class='flag-5'>無人機手機</b><b class='flag-5'>端</b><b class='flag-5'>遙控器</b>(5)
    RM新时代网站-首页