上一篇文章(基于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)取自己的登錄注冊頁面供你使用。
安裝提示注冊登錄即可。
上面的這些做完后,恭喜你!現(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<>(); privateList djiList=newArrayList<>(); //手柄控制器 privateHandheldControllerhandheldController; //手柄電量 privateinth_power=0; privatestaticList list=newArrayList<>(); privatestaticList getList=newArrayList<>(); privateMediaManagermMediaManager; privateMediaManager.FileListStatecurrentFileListState=MediaManager.FileListState.UNKNOWN; privateList arrayList=newArrayList<>(); privateList startList=newArrayList<>(); privateList endList=newArrayList<>(); privatebooleanisStartLive=false; privatebooleanisFlying=false; privatebooleanstart=false; privateBaseProductmProduct; privateStringposName=""; //webSocket privateJWebSocketClientclient; privateMap params=newHashMap<>(); Map mapData=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); } }
完成后界面如下所示:
上面的工作完成后就可以在無人且寬闊的地方進行無人機飛行了。
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 (); privateList mediaFileList=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){ ArrayList fileToDelete=newArrayList (); if(mediaFileList.size()>index){ fileToDelete.add(mediaFileList.get(index)); mMediaManager.deleteFiles(fileToDelete,newCommonCallbacks.CompletionCallbackWithTwoParam ,DJICameraError>(){ @Override publicvoidonSuccess(List
x,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; } }
運行后界面如下:
審核編輯:湯梓紅
-
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
+關(guān)注
關(guān)注
3文章
1035瀏覽量
45899
原文標(biāo)題:基于Mobile SDK V4版固件開發(fā)大疆無人機手機端遙控器(2)
文章出處:【微信號:美男子玩編程,微信公眾號:美男子玩編程】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論