上一篇文章(基于mobile sdk v4版固件开发大疆无人机手机端遥控器(1))因为时间原因介绍了一部分内容,如果已经完成上一篇内容的操作就可以进行下面功能方面的制作了。自己开发的app功能不是很多,但是已经将大疆无人机的常用功能进行了结合,同大家一起进行学习~
1应用程序激活与绑定
如果在中国使用dji飞行器固件,则需要使用该用户的dji帐户激活控制dji飞行器的移动应用程序。这将确保大疆能根据飞行器的地理位置和用户个人资料,为飞行器配置正确的地理空间信息和飞行功能集。激活系统的主要是:
中国用户必须在每三个月至少登录一次dji帐户以遍激活应用程序。
激活信息将存储在应用程序中,直到用户注销为止。
登录dji帐号需要连接互联网。
在中国境外,sdk会自动激活应用程序,无需用户登录。
另外,中国用户必须将飞机绑定到dji官方app中的用户帐户。这仅需要一次。如果未激活应用程序,未绑定飞机(如果需要)或使用旧版sdk(<4.1),则会禁用相机视频流,并且飞行限制在直径100m和高度30m的区域中,以确保飞机停留在视线范围内。
2为应用程序创建ui
编写mapplication、receiverapplication和registrationactivity文件(此处粘贴部分代码)。
public class mapplication extends multidexapplication { private receiverapplication receiverapplication; @override protected void attachbasecontext(context paramcontext) { super.attachbasecontext(paramcontext); crashhandler.getinstance().init(this); helper.install(mapplication.this); if (receiverapplication == null) { receiverapplication = new receiverapplication(); receiverapplication.setcontext(this); } } @override public void oncreate() { super.oncreate(); receiverapplication.oncreate(); }}
上面的代码实现了绑定当前app,将后续需要用到的类函数封装到receiverapplication 中,在receiverapplication 中也能够进行账户登录的操作。
public class receiverapplication extends multidexapplication { public static final string flag_connection_change = activation_connection_change; private static baseproduct mproduct; public handler mhandler; private application instance; public void setcontext(application application) { instance = application; } @override protected void attachbasecontext(context base) { super.attachbasecontext(base); helper.install(this); } @override public context getapplicationcontext() { return instance; } public receiverapplication() { } /** * this function is used to get the instance of djibaseproduct. * if no product is connected, it returns null. */ public static synchronized baseproduct getproductinstance() { if (null == mproduct) { mproduct = djisdkmanager.getinstance().getproduct(); } return mproduct; } public static synchronized aircraft getaircraftinstance() { if (!isaircraftconnected()) return null; return (aircraft) getproductinstance(); } public static synchronized camera getcamerainstance() { if (getproductinstance() == null) return null; camera camera = null; if (getproductinstance() instanceof aircraft){ camera = ((aircraft) getproductinstance()).getcamera(); } else if (getproductinstance() instanceof handheld) { camera = ((handheld) getproductinstance()).getcamera(); } return camera; } public static boolean isaircraftconnected() { return getproductinstance() != null && getproductinstance() instanceof aircraft; } public static boolean ishandheldconnected() { return getproductinstance() != null && getproductinstance() instanceof handheld; } public static boolean isproductmoduleavailable() { return (null != receiverapplication.getproductinstance()); } public static boolean iscameramoduleavailable() { return isproductmoduleavailable() && (null != receiverapplication.getproductinstance().getcamera()); } public static boolean isplaybackavailable() { return iscameramoduleavailable() && (null != receiverapplication.getproductinstance().getcamera().getplaybackmanager()); } @override public void oncreate() { super.oncreate(); mhandler = new handler(looper.getmainlooper()); /** * when starting sdk services, an instance of interface djisdkmanager.djisdkmanagercallback will be used to listen to * the sdk registration result and the product changing. */ //listens to the sdk registration result djisdkmanager.sdkmanagercallback mdjisdkmanagercallback = new djisdkmanager.sdkmanagercallback() { //listens to the sdk registration result @override public void onregister(djierror error) { if (error == djisdkerror.registration_success) { handler handler = new handler(looper.getmainlooper()); handler.post(new runnable() { @override public void run() {// toastutils.showtoast(getapplicationcontext(), 注册成功);// toast.maketext(getapplicationcontext(), 注册成功, toast.length_long).show();// loginaccount(); } }); djisdkmanager.getinstance().startconnectiontoproduct(); } else { handler handler = new handler(looper.getmainlooper()); handler.post(new runnable() { @override public void run() {// toastutils.showtoast(getapplicationcontext(), 注册sdk失败,请检查网络是否可用);// toast.maketext(getapplicationcontext(), 注册sdk失败,请检查网络是否可用, toast.length_long).show(); } }); } log.e(tag, error.tostring()); } @override public void onproductdisconnect() { log.d(tag, 设备连接); notifystatuschange(); } @override public void onproductconnect(baseproduct baseproduct) { log.d(tag, string.format(新设备连接:%s, baseproduct)); notifystatuschange(); } @override public void onproductchanged(baseproduct baseproduct) { } @override public void oncomponentchange(baseproduct.componentkey componentkey, basecomponent oldcomponent, basecomponent newcomponent) { if (newcomponent != null) { newcomponent.setcomponentlistener(new basecomponent.componentlistener() { @override public void onconnectivitychange(boolean isconnected) { log.d(tag, 设备连接已更改: + isconnected); notifystatuschange(); } }); } log.d(tag, string.format(设备改变 key:%s, 旧设备:%s, 新设备:%s, componentkey, oldcomponent, newcomponent)); } @override public void oninitprocess(djisdkinitevent djisdkinitevent, int i) { } @override public void ondatabasedownloadprogress(long l, long l1) { } }; //check the permissions before registering the application for android system 6.0 above. int permissioncheck = contextcompat.checkselfpermission(getapplicationcontext(), android.manifest.permission.write_external_storage); int permissioncheck2 = contextcompat.checkselfpermission(getapplicationcontext(), android.manifest.permission.read_phone_state); if (build.version.sdk_int 2000) { showtoast(再按一次退出程序); exittime = system.currenttimemillis(); } else { registrationactivity.this.finish(); system.exit(0); } return true; } return super.onkeydown(keycode, event); } private void loginaccount() { useraccountmanager.getinstance().logintodjiuseraccount(this, new commoncallbacks.completioncallbackwith() { @override public void onsuccess(useraccountstate useraccountstate) { runonuithread(new runnable() { @override public void run() { mbuttonflighttask.setenabled(true); mbuttonsettingroute.setenabled(true); mbuttonfilemanagement.setenabled(true); } }); } @override public void onfailure(djierror djierror) { } }); }}
上面的代码就要进行第一次注册登录了,当然你不需要自己去设计登录注册页面,大疆会调取自己的登录注册页面供你使用。
安装提示注册登录即可。
上面的这些做完后,恭喜你!现在,您的移动应用程序和飞机可以在中国使用而没有任何问题。换句话说,您的应用程序现在可以看到飞机的视频流,并且飞行将不仅限于直径为100m和高度为30m的圆柱体区域。
3飞行界面使用
虽然说可以正常飞行了,但是飞行需要设计飞行界面。那么创建一下飞行界面的ui及逻辑处理文件。逻辑处理文件中包含了获取飞机的实时姿态信息,代码中有注释内容,描述的内容就不多说了。
导入ux sdk依赖
上一节有说过集成部分,其中内容有导入uxsdk 的操作,这里再顺便提一下。再build.gradle文件中加入implementation com.dji4.16依赖,等待安装即可。
设计界面ui
创建mainactivity文件及activity_main.xml。
@layout(r.layout.activity_main)public class mainactivity extends baseactivity implements view.onclicklistener { @bindview(r.id.img_live) imageview mimageviewlive; private mapwidget mapwidget; private djimap amap; private viewgroup parentview; private fpvwidget fpvwidget; private fpvwidget secondaryfpvwidget; private relativelayout primaryvideoview; private framelayout secondaryvideoview; private boolean ismapmini = true; private string liveshowurl = ; private int height; private int width; private int margin; private int devicewidth; private int deviceheight; private sharedpreutils msharedpreutils; //unix时间戳 private string datestr = ; //飞行器管理器 private flightcontroller controller; //经纬度 private double lat = 0, lon = 0; //高度 private float high = 0; //飞机的姿态 private attitude attitude; //俯仰角、滚转、偏航值 private double pitch = 0, roll = 0, yaw = 0; //飞机的速度 private float velocity_x = 0, velocity_y = 0, velocity_z = 0; //飞机/控制器电池管理器 private battery battery; //电池电量、温度 private int power = 0; private float temperature = 0; //云台管理器 private gimbal gimbal; //云台的姿态 private dji.common.gimbal.attitude g_attitude; //俯仰角、滚转、偏航值 private double g_pitch = 0, g_roll = 0, g_yaw = 0; private camera camera; private list lens = new arraylist(); private list djilist = new arraylist(); //手柄控制器 private handheldcontroller handheldcontroller; //手柄电量 private int h_power = 0; private static list list = new arraylist(); private static list getlist = new arraylist(); private mediamanager mmediamanager; private mediamanager.fileliststate currentfileliststate = mediamanager.fileliststate.unknown; private list arraylist = new arraylist(); private list startlist = new arraylist(); private list endlist = new arraylist(); private boolean isstartlive = false; private boolean isflying = false; private boolean start = false; private baseproduct mproduct; private string posname = ; //websocket private jwebsocketclient client; private map params = new hashmap(); map mapdata = new hashmap(); @override protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); height = toolkit.dip2px(this, 100); width = toolkit.dip2px(this, 150); margin = toolkit.dip2px(this, 12); windowmanager windowmanager = (windowmanager) getsystemservice(context.window_service); final display display = windowmanager.getdefaultdisplay(); point outpoint = new point(); display.getrealsize(outpoint); deviceheight = outpoint.y; devicewidth = outpoint.x; parentview = (viewgroup) findviewbyid(r.id.root_view); fpvwidget = findviewbyid(r.id.fpv_widget); fpvwidget.setonclicklistener(new view.onclicklistener() { @override public void onclick(view view) { onviewclick(fpvwidget); } }); primaryvideoview = (relativelayout) findviewbyid(r.id.fpv_container); secondaryvideoview = (framelayout) findviewbyid(r.id.secondary_video_view); secondaryfpvwidget = findviewbyid(r.id.secondary_fpv_widget); secondaryfpvwidget.setonclicklistener(new view.onclicklistener() { @override public void onclick(view view) { swapvideosource(); } }); if (videofeeder.getinstance() != null) { //if secondary video feed is already initialized, get video source updatesecondaryvideovisibility(videofeeder.getinstance().getsecondaryvideofeed().getvideosource() != physicalsource.unknown); //if secondary video feed is not yet initialized, wait for active status videofeeder.getinstance().getsecondaryvideofeed() .addvideoactivestatuslistener(isactive -> runonuithread(() -> updatesecondaryvideovisibility(isactive))); } msharedpreutils = sharedpreutils.getinstance(this); this.getwindow().clearflags(windowmanager.layoutparams.flag_alt_focusable_im); mapwidget = findviewbyid(r.id.map_widget); mapwidget.setflightpathcolor(color.parsecolor(#2fa8e7)); mapwidget.setflightpathwidth(15); mapwidget.setdirectiontohomevisible(false); mapwidget.initamap(new mapwidget.onmapreadylistener() { @override public void onmapready(@nonnull djimap djimap) { djimap.setonmapclicklistener(new djimap.onmapclicklistener() { @override public void onmapclick(djilatlng latlng) { onviewclick(mapwidget); } }); djimap.getuisettings().setzoomcontrolsenabled(false); } }); if (amap == null) { amap = mapwidget.getmap(); } mapwidget.oncreate(savedinstancestate); mproduct = receiverapplication.getproductinstance(); if (null != mproduct && mproduct.isconnected()) { flyinformation(mproduct); batteryinformation(mproduct); camerainformation(mproduct); camera(mproduct); } timer timer = new timer(); timer.schedule(new timertask() { @override public void run() { message msg = new message(); if (isflying && !start) { start = true; } if (!isflying && start) { start = false; } if (isflying && high >= 0) { msg.what = 1; } mhandler.sendmessage(msg); } }, 200, 200); } handler mhandler = new handler() { @requiresapi(api = build.version_codes.o) @override public void handlemessage(@nonnull message msg) { switch (msg.what) { case 1: long time = system.currenttimemillis();// mylog.d(时间:+time); recordmodule module = new recordmodule(string.valueof(projectid), string.valueof(planeid), trajectoryid, time, string.valueof(lon), string.valueof(lat), string.valueof(high), string.valueof(yaw), string.valueof(pitch), string.valueof(roll), string.valueof(), string.valueof(velocity_x), string.valueof(velocity_y), string.valueof(velocity_z), string.valueof(g_yaw), string.valueof(g_roll), string.valueof(g_pitch)); http.gethttp(insert_data, gsonutil.gsonstring(module)); break; case 2: mylog.d(飞机移动的数据:+msg.obj.tostring()); controlmodule control = gsonutil.gsontobean(msg.obj.tostring(),controlmodule.class); if (controller!=null&&isflying){ if (control.getcontent().isback()){ controller.sendvirtualstickflightcontroldata(new flightcontroldata(-10,0,0,0),null); } if (control.getcontent().isfront()){ controller.sendvirtualstickflightcontroldata(new flightcontroldata(10,0,0,0),null); } if (control.getcontent().isdown()){ controller.sendvirtualstickflightcontroldata(new flightcontroldata(0,0,0,-4),null); } if (control.getcontent().isup()){ controller.sendvirtualstickflightcontroldata(new flightcontroldata(0,0,0,4),null); } if (control.getcontent().isleft()){ controller.sendvirtualstickflightcontroldata(new flightcontroldata(0,-10,0,0),null); } if (control.getcontent().isright()){ controller.sendvirtualstickflightcontroldata(new flightcontroldata(0,10,0,0),null); } }else { mylog.d(controller控制器为空); } break; } } }; @override public void initviews() { mmediamanager = receiverapplication.getcamerainstance().getmediamanager(); getfilelist(start); } @override public void oncomplete(string url, string jsonstr) { super.oncomplete(url, jsonstr); } @override public void initdatas() { } private void onviewclick(view view) { if (view == fpvwidget && !ismapmini) { resizefpvwidget(relativelayout.layoutparams.match_parent, relativelayout.layoutparams.match_parent, 0, 0); reordercameracapturepanel(); resizeanimation mapviewanimation = new resizeanimation(mapwidget, devicewidth, deviceheight, width, height, margin); mapwidget.startanimation(mapviewanimation); ismapmini = true; } else if (view == mapwidget && ismapmini) { hidepanels(); resizefpvwidget(width, height, margin, 12); reordercameracapturepanel(); resizeanimation mapviewanimation = new resizeanimation(mapwidget, width, height, devicewidth, deviceheight, 0); mapwidget.startanimation(mapviewanimation); ismapmini = false; } } private void resizefpvwidget(int width, int height, int margin, int fpvinsertposition) { relativelayout.layoutparams fpvparams = (relativelayout.layoutparams) primaryvideoview.getlayoutparams(); fpvparams.height = height; fpvparams.width = width; fpvparams.rightmargin = margin; fpvparams.bottommargin = margin; if (ismapmini) { fpvparams.addrule(relativelayout.center_in_parent, 0); fpvparams.addrule(relativelayout.align_parent_right, relativelayout.true); fpvparams.addrule(relativelayout.align_parent_bottom, relativelayout.true); } else { fpvparams.addrule(relativelayout.align_parent_right, 0); fpvparams.addrule(relativelayout.align_parent_bottom, 0); fpvparams.addrule(relativelayout.center_in_parent, relativelayout.true); } primaryvideoview.setlayoutparams(fpvparams); parentview.removeview(primaryvideoview); parentview.addview(primaryvideoview, fpvinsertposition); } private void reordercameracapturepanel() { view cameracapturepanel = findviewbyid(r.id.cameracapturepanel); parentview.removeview(cameracapturepanel); parentview.addview(cameracapturepanel, ismapmini ? 9 : 13); } private void swapvideosource() { if (secondaryfpvwidget.getvideosource() == fpvwidget.videosource.secondary) { fpvwidget.setvideosource(fpvwidget.videosource.secondary); secondaryfpvwidget.setvideosource(fpvwidget.videosource.primary); } else { fpvwidget.setvideosource(fpvwidget.videosource.primary); secondaryfpvwidget.setvideosource(fpvwidget.videosource.secondary); } } private void updatesecondaryvideovisibility(boolean isactive) { if (isactive) { secondaryvideoview.setvisibility(view.visible); } else { secondaryvideoview.setvisibility(view.gone); } } private void hidepanels() { //these panels appear based on keys from the drone itself. if (keymanager.getinstance() != null) { keymanager.getinstance().setvalue(camerakey.create(camerakey.histogram_enabled), false, null); keymanager.getinstance().setvalue(camerakey.create(camerakey.color_waveform_enabled), false, null); } //these panels have buttons that toggle them, so call the methods to make sure the button state is correct. cameracontrolswidget controlswidget = findviewbyid(r.id.cameracapturepanel); controlswidget.setadvancedpanelvisibility(false); controlswidget.setexposurepanelvisibility(false); //these panels don't have a button state, so we can just hide them. findviewbyid(r.id.pre_flight_check_list).setvisibility(view.gone); findviewbyid(r.id.rtk_panel).setvisibility(view.gone); findviewbyid(r.id.spotlight_panel).setvisibility(view.gone); findviewbyid(r.id.speaker_panel).setvisibility(view.gone); } @override protected void onresume() { super.onresume(); // hide both the navigation bar and the status bar. view decorview = getwindow().getdecorview(); decorview.setsystemuivisibility(view.system_ui_flag_layout_stable | view.system_ui_flag_layout_hide_navigation | view.system_ui_flag_layout_fullscreen | view.system_ui_flag_hide_navigation | view.system_ui_flag_fullscreen | view.system_ui_flag_immersive_sticky); mapwidget.onresume(); if (client == null) { mylog.e(``````````````````````onresume);// initwebsocket(); } else if (!client.isopen()) { reconnectws();//进入页面发现断开开启重连 } } @override protected void onstop() { super.onstop(); mylog.e(``````````````````````````````onstop); } @override protected void onpause() { mapwidget.onpause(); super.onpause(); } @override protected void ondestroy() { mapwidget.ondestroy(); super.ondestroy(); mylog.e( `````````````````````````ondestroy); closeconnect(); } @override protected void requestdata() { } @override protected void onsaveinstancestate(bundle outstate) { super.onsaveinstancestate(outstate); mapwidget.onsaveinstancestate(outstate); } @override public void onlowmemory() { super.onlowmemory(); mapwidget.onlowmemory(); } private class resizeanimation extends animation { private view mview; private int mtoheight; private int mfromheight; private int mtowidth; private int mfromwidth; private int mmargin; private resizeanimation(view v, int fromwidth, int fromheight, int towidth, int toheight, int margin) { mtoheight = toheight; mtowidth = towidth; mfromheight = fromheight; mfromwidth = fromwidth; mview = v; mmargin = margin; setduration(300); } @override protected void applytransformation(float interpolatedtime, transformation t) { float height = (mtoheight - mfromheight) * interpolatedtime + mfromheight; float width = (mtowidth - mfromwidth) * interpolatedtime + mfromwidth; relativelayout.layoutparams p = (relativelayout.layoutparams) mview.getlayoutparams(); p.height = (int) height; p.width = (int) width; p.rightmargin = mmargin; p.bottommargin = mmargin; mview.requestlayout(); } } //直播流推送 @requiresapi(api = build.version_codes.o) @onclick({r.id.img_live, r.id.img_show_back}) @override public void onclick(view v) { switch (v.getid()) { case r.id.img_live: params.clear(); mapdata.clear(); if (!isstartlive) { if (!textutils.isempty(msharedpreutils.getstringsharepre(rtmp_url))) { liveshowurl = msharedpreutils.getstringsharepre(rtmp_url) + trajectoryid;// livemodule module = new livemodule(livestreamstatechanged,plane,planeid,true,trajectoryid+); mylog.d(地址:+liveshowurl); startliveshow(); isstartlive = true; showtoast(开始推流); } else { showtoast(请先进行系统设置(rtmp)。); } } else { stopliveshow(); isstartlive = false; } break; case r.id.img_show_back:// controller = null; closeconnect(); mainactivity.this.finish(); break; } } private boolean islivestreammanageron() { if (djisdkmanager.getinstance().getlivestreammanager() == null) { return false; } return true; } private void startliveshow() { if (!islivestreammanageron()) { return; } if (djisdkmanager.getinstance().getlivestreammanager().isstreaming()) { return; } new thread() { @override public void run() { djisdkmanager.getinstance().getlivestreammanager().setliveurl(liveshowurl); djisdkmanager.getinstance().getlivestreammanager().setaudiostreamingenabled(true); int result = djisdkmanager.getinstance().getlivestreammanager().startstream(); djisdkmanager.getinstance().getlivestreammanager().setstarttime(); } }.start(); } private void stopliveshow() { alertdialog.builder builder = new alertdialog.builder(mainactivity.this); builder.settitle(提示); builder.setmessage(是否结束推流?); builder.seticon(android.r.drawable.ic_dialog_alert); builder.setpositivebutton(确定, new dialoginterface.onclicklistener() { @override public void onclick(dialoginterface dialog, int which) { if (!islivestreammanageron()) { return; } djisdkmanager.getinstance().getlivestreammanager().stopstream(); showtoast(结束推流); } }); builder.setnegativebutton(取消, null); builder.show(); } //获取飞机信息、云台信息 protected broadcastreceiver mreceiver = new broadcastreceiver() { @override public void onreceive(context context, intent intent) { baseproduct mproduct = receiverapplication.getproductinstance(); if (null != mproduct && mproduct.isconnected()) { flyinformation(mproduct); batteryinformation(mproduct); camerainformation(mproduct); camera(mproduct);// mobileremote(mproduct); } } };// private void mobileremote(baseproduct mproduct) {// if (null != mproduct && mproduct.isconnected()) {// mobilecontroller = ((aircraft) mproduct).getmobileremotecontroller();// }// } //获取飞机信息 private void flyinformation(baseproduct mproduct) { if (null != mproduct && mproduct.isconnected()) { controller = ((aircraft) mproduct).getflightcontroller(); } if (controller != null) { controller.setstatecallback(new flightcontrollerstate.callback() { @requiresapi(api = build.version_codes.o) @override public void onupdate(@nonnull flightcontrollerstate flightcontrollerstate) { //纬度、经度、高度、俯仰角、滚转、偏航值、速度 lat = flightcontrollerstate.getaircraftlocation().getlatitude(); lon = flightcontrollerstate.getaircraftlocation().getlongitude(); high = flightcontrollerstate.getaircraftlocation().getaltitude(); attitude = flightcontrollerstate.getattitude(); pitch = attitude.pitch; roll = attitude.roll; yaw = attitude.yaw; velocity_x = flightcontrollerstate.getvelocityx(); velocity_y = flightcontrollerstate.getvelocityy(); velocity_z = flightcontrollerstate.getvelocityz(); isflying = flightcontrollerstate.isflying(); // mylog.d(经度: + lat + ,纬度: + lon + ,高度: + high + ,角度: + pitch + ,速度: + velocity_x + , + velocity_y + , + velocity_z); } }); controller.setvirtualstickadvancedmodeenabled(true); controller.setrollpitchcoordinatesystem(flightcoordinatesystem.body); controller.setverticalcontrolmode(verticalcontrolmode.velocity); controller.setrollpitchcontrolmode(rollpitchcontrolmode.velocity); controller.setyawcontrolmode(yawcontrolmode.angular_velocity);// controller.setterrainfollowmodeenabled(false, new commoncallbacks.completioncallback() {// @override// public void onresult(djierror djierror) {// mylog.d(djierror.getdescription());// }// });// controller.settripodmodeenabled(false, new commoncallbacks.completioncallback() {// @override// public void onresult(djierror djierror) {// mylog.d(djierror.getdescription());// }// });// controller.setflightorientationmode(flightorientationmode.aircraft_heading, new commoncallbacks.completioncallback() {// @override// public void onresult(djierror djierror) {// mylog.d(djierror.getdescription());// if (djierror==null){// if (controller.isvirtualstickcontrolmodeavailable()){//// }else {// mylog.d(虚拟摇杆模式不可用);// }// }// }// }); } } //电池信息 private void batteryinformation(baseproduct mproduct) { if (null != mproduct && mproduct.isconnected()) { battery = ((aircraft) mproduct).getbattery(); } if (battery != null) { battery.setstatecallback(new batterystate.callback() { @override public void onupdate(batterystate batterystate) { //电池电量 power = batterystate.getchargeremaininginpercent(); //电池温度 temperature = batterystate.gettemperature(); } }); } } //云台信息 private void camerainformation(baseproduct mproduct) { if (null != mproduct && mproduct.isconnected()) { gimbal = ((aircraft) mproduct).getgimbal(); } if (gimbal != null) { gimbal.setmode(gimbalmode.yaw_follow, null); gimbal.setstatecallback(new gimbalstate.callback() { @override public void onupdate(@nonnull gimbalstate gimbalstate) { //俯仰角、滚转、偏航值 g_attitude = gimbalstate.getattitudeindegrees(); g_pitch = g_attitude.getpitch(); g_roll = g_attitude.getroll(); g_yaw = g_attitude.getyaw(); } }); } } private void camera(baseproduct mproduct) { if (null != mproduct && mproduct.isconnected()) { camera = ((aircraft) mproduct).getcamera(); } if (camera != null) { // camera.setvideocaptionenabled(true, new commoncallbacks.completioncallback() { // @override // public void onresult(djierror djierror) { // mylog.d(videocaptionenabled+djierror.tostring()); // } // }); // camera.setmediafilecustominformation(projectid +,+trajectoryid, new commoncallbacks.completioncallback() { // @override // public void onresult(djierror djierror) { // mylog.d(自定义信息:+djierror.tostring()); // } // }); camera.setsystemstatecallback(new systemstate.callback() { @requiresapi(api = build.version_codes.o) @override public void onupdate(@nonnull systemstate systemstate) { if (systemstate.getmode().equals(settingsdefinitions.cameramode.shoot_photo)) { if (systemstate.isstoringphoto()) { datestr = long.tostring(system.currenttimemillis()); list.add(new deviceinfo(datestr, lat, lon, high, pitch, roll, yaw, velocity_x, velocity_y, velocity_z, g_yaw, g_roll, g_pitch)); csvwriter.getinstance(,, utf-8).writedatatofile(list, fileutil.checkdirpath(fly_file_path + /照片数据) + / + dateutils.getcurrentdates() + .csv); list.clear(); return; } } else if (systemstate.getmode().equals(settingsdefinitions.cameramode.record_video)) { if (systemstate.isrecording()) { try { datestr = long.tostring(system.currenttimemillis()); list.add(new deviceinfo(datestr, lat, lon, high, pitch, roll, yaw, velocity_x, velocity_y, velocity_z, g_yaw, g_roll, g_pitch)); getlist.add(datestr); thread.sleep(100); } catch (interruptedexception e) { e.printstacktrace(); } } else { if (list.size() > 1) { posname = dateutils.getcurrentdates() + .csv; csvwriter.getinstance(,, utf-8).writedatatofile(list, fileutil.checkdirpath(fly_file_path + /视频数据) + / + posname); list.clear(); runonuithread(new runnable() { @override public void run() { getfilelist(end); } }); } } } } }); } } //遥控器信息 private void handheldinforamation(baseproduct mproduct) { if (null != mproduct && mproduct.isconnected()) { handheldcontroller = ((handheld) mproduct).gethandheldcontroller(); } if (handheldcontroller != null) { handheldcontroller.setpowermodecallback(new powermode.callback() { @override public void onupdate(powermode powermode) { switch (powermode) { case on: battery battery = ((handheld) mproduct).getbattery(); battery.setstatecallback(new batterystate.callback() { @override public void onupdate(batterystate batterystate) { h_power = batterystate.getchargeremaininginpercent(); } }); break; } } }); } } @override public boolean onkeydown(int keycode, keyevent event) { if (keycode == keyevent.keycode_back && event.getaction() == keyevent.action_down) {// closeconnect(); mainactivity.this.finish(); } return super.onkeydown(keycode, event); }}
完成后界面如下所示:
上面的工作完成后就可以在无人且宽阔的地方进行无人机飞行了。
4
多媒体资源的操作
多媒体文件操作,主要为多媒体文件的获取、查看、删除、下载的操作同样创建多媒体功能文件filemanagementactivity及activity_file_management.xml
activity_file_management.xml
filemanagementactivity
@layout(r.layout.activity_file_management)public class filemanagementactivity extends baseactivity implements view.onclicklistener { private static final string tag = filemanagementactivity.class.getname(); @bindview(r.id.layout_file) view mviewlayouttoolbar; @bindview(r.id.tv_toolbar_title) textview mtextviewtoolbartitle; @bindview(r.id.ll_file) linearlayout mlinearlayout; @bindview(r.id.rg_file_management) radiogroup mradiogroup; @bindview(r.id.rv_file_management) recyclerview mrecyclerview; @bindview(r.id.img_show) imageview mimageview; @bindview(r.id.ll_video_btn) linearlayout mlinearlayoutvideo; @bindview(r.id.img_video_play) imageview mimageviewvideoplay; @bindview(r.id.img_video_pause) imageview mimageviewvideopause; private filelistadapter mlistadapter; private list list = new arraylist(); private list mediafilelist = new arraylist(); private mediamanager mmediamanager; private mediamanager.fileliststate currentfileliststate = mediamanager.fileliststate.unknown; private mediamanager.videoplaybackstate state; private progressdialog mloadingdialog; private progressdialog mdownloaddialog; private fetchmediataskscheduler scheduler; private int lastclickviewindex = -1; private int currentprogress = -1; private string savepath = ; private view lastclickview; private boolean isresume = false; private sftputils sftp; private settingsdefinitions.storagelocation storagelocation; @override public void initviews() { mlinearlayout.setvisibility(view.visible); mtextviewtoolbartitle.settext(文件管理); mimageviewvideoplay.setenabled(true); mimageviewvideopause.setenabled(false); mradiogroup.setoncheckedchangelistener(new radiogroup.oncheckedchangelistener() { @override public void oncheckedchanged(radiogroup group, int checkedid) { list.clear(); mediafilelist.clear(); switch (checkedid) { case r.id.rb_file_all: getfilelist(0); mlistadapter.notifydatasetchanged(); break; case r.id.rb_file_photo: getfilelist(1); mlistadapter.notifydatasetchanged(); break; case r.id.rb_file_video: getfilelist(2); mlistadapter.notifydatasetchanged(); break; } } }); linearlayoutmanager layoutmanager = new linearlayoutmanager(filemanagementactivity.this, recyclerview.vertical, false); mrecyclerview.setlayoutmanager(layoutmanager); //init filelistadapter mlistadapter = new filelistadapter(); mrecyclerview.setadapter(mlistadapter); //init loading dialog mloadingdialog = new progressdialog(filemanagementactivity.this); mloadingdialog.setmessage(请等待...); mloadingdialog.setcanceledontouchoutside(false); mloadingdialog.setcancelable(false); //init download dialog mdownloaddialog = new progressdialog(filemanagementactivity.this); mdownloaddialog.settitle(下载中...); mdownloaddialog.seticon(android.r.drawable.ic_dialog_info); mdownloaddialog.setprogressstyle(progressdialog.style_horizontal); mdownloaddialog.setcanceledontouchoutside(false); mdownloaddialog.setcancelable(true); mdownloaddialog.setoncancellistener(new dialoginterface.oncancellistener() { @override public void oncancel(dialoginterface dialog) { if (mmediamanager != null) { mmediamanager.exitmediadownloading(); } } }); sftp = new sftputils(49.4.79.249,uav,uavhhch@yrec.cn); receiverapplication.getaircraftinstance().getcamera().setstoragestatecallback(new storagestate.callback() { @override public void onupdate(@nonnull @notnull storagestate storagestate) { if(storagestate.isinserted()) { storagelocation = settingsdefinitions.storagelocation.sdcard; receiverapplication.getaircraftinstance().getcamera().setstoragelocation(settingsdefinitions.storagelocation.sdcard, new commoncallbacks.completioncallback() { @override public void onresult(djierror djierror) { } }); } else { storagelocation = settingsdefinitions.storagelocation.internal_storage; receiverapplication.getaircraftinstance().getcamera().setstoragelocation(settingsdefinitions.storagelocation.internal_storage, new commoncallbacks.completioncallback() { @override public void onresult(djierror djierror) { } }); } } }); } @override public void initdatas() { } @override protected void requestdata() { } @override public void oncomplete(string url, string jsonstr) { super.oncomplete(url, jsonstr); switch (url){ case post_video_info: break; default: getvideojson(jsonstr); break; } } private void getvideojson(string jsonstr) { videomodule module = gsonutil.gsontobean(jsonstr,videomodule.class); if (module.getcode() == 200 && module.getrows().size() == 1){ runonuithread(new runnable() { @override public void run() { updatefilemodule filemodule = new updatefilemodule(module.getrows().get(0).getid(),/mnt/uavftpfolder/+module.getrows().get(0).getfilename()); http.gethttp(post_video_info,put,gsonutil.gsonstring(filemodule)); } }); } } @override protected void onresume() { super.onresume(); initmediamanager(); } @override protected void onpause() { super.onpause(); } @override protected void onstop() { super.onstop(); } @override protected void ondestroy() { lastclickview = null; if (mmediamanager != null) { mmediamanager.stop(null); mmediamanager.removefileliststatecallback(this.updatefileliststatelistener); mmediamanager.exitmediadownloading(); if (scheduler != null) { scheduler.removealltasks(); } } if (ismavicair2() || ism300()) { if (receiverapplication.getcamerainstance() != null) { receiverapplication.getcamerainstance().exitplayback(djierror -> { if (djierror != null) { receiverapplication.getcamerainstance().setflatmode(settingsdefinitions.flatcameramode.photo_single, djierror1 -> { if (djierror1 != null) { showtoasts(设置单张拍照模式失败. + djierror1.getdescription()); } }); } }); } else { receiverapplication.getcamerainstance().setmode(settingsdefinitions.cameramode.shoot_photo, djierror -> { if (djierror != null) { showtoasts(设置拍照模式失败. + djierror.getdescription()); } }); } } if (mediafilelist != null) { // list.clear(); mediafilelist.clear(); } super.ondestroy(); } private void showprogressdialogs() { runonuithread(new runnable() { public void run() { if (mloadingdialog != null) { mloadingdialog.show(); } } }); } private void hideprogressdialog() { runonuithread(new runnable() { public void run() { if (null != mloadingdialog && mloadingdialog.isshowing()) { mloadingdialog.dismiss(); } } }); } private void showdownloadprogressdialog() { if (mdownloaddialog != null) { runonuithread(new runnable() { public void run() { mdownloaddialog.incrementprogressby(-mdownloaddialog.getprogress()); mdownloaddialog.show(); } }); } } private void hidedownloadprogressdialog() { if (null != mdownloaddialog && mdownloaddialog.isshowing()) { runonuithread(new runnable() { public void run() { mdownloaddialog.dismiss(); } }); } } private void initmediamanager() { if (receiverapplication.getproductinstance() == null) { mediafilelist.clear(); mlistadapter.notifydatasetchanged(); djilog.e(tag, 设备已断开); return; } else { if (null != receiverapplication.getcamerainstance() && receiverapplication.getcamerainstance().ismediadownloadmodesupported()) { mmediamanager = receiverapplication.getcamerainstance().getmediamanager(); if (null != mmediamanager) { mmediamanager.addupdatefileliststatelistener(this.updatefileliststatelistener); mmediamanager.addmediaupdatedvideoplaybackstatelistener(new mediamanager.videoplaybackstatelistener() { @override public void onupdate(mediamanager.videoplaybackstate videoplaybackstate) { state = videoplaybackstate; if (videoplaybackstate.getplaybackstatus() == mediafile.videoplaybackstatus.stopped){ runonuithread(new runnable() { @override public void run() {// mimageviewvideoplay.setenabled(true);// mimageviewvideopause.setenabled(false); } }); } } }); if (ismavicair2() || ism300()) { receiverapplication.getcamerainstance().enterplayback(djierror -> { if (djierror == null) { djilog.e(tag, 设置cameramode成功); showprogressdialogs(); getfilelist(0); } else { showtoasts(设置cameramode失败); } }); } else { receiverapplication.getcamerainstance().setmode(settingsdefinitions.cameramode.media_download, error -> { if (error == null) { djilog.e(tag, 设置cameramode成功); showprogressdialogs(); getfilelist(0); } else { showtoasts(设置cameramode失败); } }); } if (mmediamanager.isvideoplaybacksupported()) { djilog.e(tag, 摄像头支持视频播放!); } else { showtoasts(摄像头不支持视频播放!); } scheduler = mmediamanager.getscheduler(); } } else if (null != receiverapplication.getcamerainstance() && !receiverapplication.getcamerainstance().ismediadownloadmodesupported()) { showtoasts(不支持媒体下载模式); } } return; } private void getfilelist(int index) { mmediamanager = receiverapplication.getcamerainstance().getmediamanager(); if (mmediamanager != null) { if ((currentfileliststate == mediamanager.fileliststate.syncing) || (currentfileliststate == mediamanager.fileliststate.deleting)) { djilog.e(tag, 媒体管理器正忙.); } else { mmediamanager.refreshfilelistofstoragelocation(storagelocation, djierror -> {// mmediamanager.refreshfilelistofstoragelocation(settingsdefinitions.storagelocation.sdcard, djierror -> { if (null == djierror) { hideprogressdialog(); //reset data if (currentfileliststate != mediamanager.fileliststate.incomplete) { list.clear(); mediafilelist.clear(); lastclickviewindex = -1; }// list = mmediamanager.getsdcardfilelistsnapshot();// list = mmediamanager.getinternalstoragefilelistsnapshot(); if (storagelocation == settingsdefinitions.storagelocation.sdcard) { list = mmediamanager.getsdcardfilelistsnapshot(); } else { list = mmediamanager.getinternalstoragefilelistsnapshot(); } switch (index) { case 0: for (int i = 0; i < list.size(); i++) { mediafilelist.add(list.get(i)); } break; case 1: for (int i = 0; i { if (error == null) { getthumbnails(); } }); } else { hideprogressdialog(); showtoasts(获取媒体文件列表失败: + djierror.getdescription()); } }); } } } private void getthumbnails() { if (mediafilelist.size() <= 0) { showtoasts(没有用于下载缩略图的文件信息); return; } for (int i = 0; i { if (error == null) { scheduler.movetasktonext(task); } else { showtoasts(恢复计划程序失败: + error.getdescription()); } }); } //listeners private mediamanager.fileliststatelistener updatefileliststatelistener = state -> currentfileliststate = state; private void deletefilebyindex(final int index) { arraylist filetodelete = new arraylist(); if (mediafilelist.size() > index) { filetodelete.add(mediafilelist.get(index)); mmediamanager.deletefiles(filetodelete, new commoncallbacks.completioncallbackwithtwoparam() { @override public void onsuccess(list x, djicameraerror y) { djilog.e(tag, delete file success); runonuithread(new runnable() { public void run() { mediafilelist.remove(index); //reset select view lastclickviewindex = -1; lastclickview = null; //update recyclerview mlistadapter.notifydatasetchanged(); } }); } @override public void onfailure(djierror error) { showtoasts(删除失败); } }); } } private void downloadfilebyindex(final int index) { if ((mediafilelist.get(index).getmediatype() == mediafile.mediatype.panorama) || (mediafilelist.get(index).getmediatype() == mediafile.mediatype.shallow_focus)) { return; } if ((mediafilelist.get(index).getmediatype() == mediafile.mediatype.mov) || (mediafilelist.get(index).getmediatype() == mediafile.mediatype.mp4)) { savepath = mystatic.fly_file_video; } else if (mediafilelist.get(index).getmediatype() == mediafile.mediatype.jpeg) { savepath = mystatic.fly_file_photo; } file destdir = new file(fileutil.checkdirpath(savepath)); mediafilelist.get(index).fetchfiledata(destdir,null, new downloadlistener() { @override public void onfailure(djierror error) { hidedownloadprogressdialog(); showtoasts(下载失败 + error.getdescription()); currentprogress = -1; } @override public void onprogress(long total, long current) { } @override public void onrateupdate(long total, long current, long persize) { int tmpprogress = (int) (1.0 * current / total * 100); if (tmpprogress != currentprogress) { mdownloaddialog.setprogress(tmpprogress); currentprogress = tmpprogress; } } @override public void onrealtimedataupdate(byte[] bytes, long l, boolean b) { } @override public void onstart() { currentprogress = -1; showdownloadprogressdialog(); } @override public void onsuccess(string filepath) { hidedownloadprogressdialog(); showtoasts(下载成功 + : + filepath); currentprogress = -1; } });// mediafilelist.get(index).fetchfilebytedata(0, new downloadlistener() {// @override// public void onstart() {// currentprogress = -1;// showdownloadprogressdialog();// }//// @override// public void onrateupdate(long total, long current, long persize) {// int tmpprogress = (int) (1.0 * current / total * 100);// if (tmpprogress != currentprogress) {// mdownloaddialog.setprogress(tmpprogress);// currentprogress = tmpprogress;// }// }//// @override// public void onrealtimedataupdate(byte[] bytes, long l, boolean b) {// bytetofile(bytes, fileutil.checkdirpath(savepath)+mediafilelist.get(index).getfilename());// }//// @override// public void onprogress(long l, long l1) {//// }//// @override// public void onsuccess(string s) {// hidedownloadprogressdialog();// showtoasts(下载成功 + : + s);// currentprogress = -1;// }//// @override// public void onfailure(djierror djierror) {//// }// }); } public static void bytetofile(byte[] bytes, string path) { try { // 根据绝对路径初始化文件 file localfile = new file(path); if (!localfile.exists()) { localfile.createnewfile(); } // 输出流 outputstream os = new fileoutputstream(localfile); os.write(bytes); os.close(); } catch (exception e) { e.printstacktrace(); } } private void playvideo() { mimageview.setvisibility(view.invisible); mediafile selectedmediafile = mediafilelist.get(lastclickviewindex); if ((selectedmediafile.getmediatype() == mediafile.mediatype.mov) || (selectedmediafile.getmediatype() == mediafile.mediatype.mp4)) { mmediamanager.playvideomediafile(selectedmediafile, error -> { if (null != error) { showtoasts(播放失败 + error.getdescription()); } else { djilog.e(tag, 播放成功); runonuithread(new runnable() { @override public void run() { mimageviewvideoplay.setenabled(false); mimageviewvideopause.setenabled(true); } }); } }); } } @onclick({r.id.img_back, r.id.img_delete, r.id.img_download, r.id.img_upload, r.id.img_video_play, r.id.img_video_pause, r.id.img_video_stop}) @override public void onclick(view v) { switch (v.getid()) { case r.id.img_back: filemanagementactivity.this.finish(); break; case r.id.img_delete: if (lastclickviewindex >= 0) { deletefilebyindex(lastclickviewindex); } else { showtoasts(请先选择文件。); } break; case r.id.img_download: if (lastclickviewindex >= 0) { downloadfilebyindex(lastclickviewindex); } else { showtoasts(请先选择文件。); } break; case r.id.img_upload: if (lastclickviewindex >= 0) { uploadfilebyindex(lastclickviewindex); } else { showtoasts(请先选择文件。); } break; case r.id.img_video_play: if (state.getplaybackstatus() == mediafile.videoplaybackstatus.stopped){ playvideo(); }else if (state.getplaybackstatus() == mediafile.videoplaybackstatus.paused){ mmediamanager.resume(error -> { if (null != error) { showtoasts(继续播放失败: + error.getdescription()); } else { djilog.e(tag, 继续播放成功); runonuithread(new runnable() { @override public void run() { mimageviewvideoplay.setenabled(false); mimageviewvideopause.setenabled(true); } }); } }); } break; case r.id.img_video_pause: mmediamanager.pause(error -> { if (null != error) { showtoasts(暂停播放失败: + error.getdescription()); } else { djilog.e(tag, 暂停播放成功); runonuithread(new runnable() { @override public void run() { mimageviewvideoplay.setenabled(true); mimageviewvideopause.setenabled(false); } }); } }); break; case r.id.img_video_stop: mmediamanager.stop(error -> { if (null != error) { showtoasts(停止播放失败: + error.getdescription()); } else { djilog.e(tag, 停止播放成功); } }); break; } } private void uploadfilebyindex(int index) { if ((mediafilelist.get(index).getmediatype() == mediafile.mediatype.mov) || (mediafilelist.get(index).getmediatype() == mediafile.mediatype.mp4)) { showprogressdialog(正在上传); new thread(new runnable() { @override public void run() { boolean isconnect = sftp.connect().isconnected(); if (isconnect){ boolean isupdate = sftp.uploadfile(/mnt/uavftpfolder/,mediafilelist.get(index).getfilename(), fly_file_video, mediafilelist.get(index).getfilename()); if (isupdate){ runonuithread(new runnable() { @override public void run() { removeprogressdialog(); http.gethttp(get_video_info+?filename=+mediafilelist.get(index).getfilename(),get); } }); sftp.disconnect(); }else { runonuithread(new runnable() { @override public void run() { showerrortip(上传失败); removeprogressdialog(); } }); } }else { runonuithread(new runnable() { @override public void run() { showerrortip(服务器连接失败); removeprogressdialog(); } }); } } }).start(); }else { showtoasts(当前仅支持视频上传,请选择视频文件!); } } private boolean ismavicair2() { baseproduct baseproduct = receiverapplication.getproductinstance(); if (baseproduct != null) { return baseproduct.getmodel() == model.mavic_air_2; } return false; } private boolean ism300() { baseproduct baseproduct = receiverapplication.getproductinstance(); if (baseproduct != null) { return baseproduct.getmodel() == model.matrice_300_rtk; } return false; }}
运行后界面如下:
Shuttle发布16屏输出的miniPC
Altera发布Quartus II软件v14.1扩展支持Arria 10 FPGA和SoC
民用无人机的十大用途详解
华为发布盘古数字人模型,或可达到“人人实现‘数字人’”
接触式图像传感器的信号读取与补偿技术
基于Mobile SDK V4版固件开发大疆无人机手机端遥控器(2)
奥迪的智能电动140亿欧元金元攻略
企业存储磁盘阵列技术分享(存储主要协议对比)
时序脉冲产生和分频电路
液位传感器工作原理和特点
ZWS行业应用–环境监测管理系统
泰凌微电子产测工具使用—如何增加GPIO测试功能
采用传感器技术的防错检测方案在汽车制造中的应用
性能领先|忆联×新华三,打造超融合架构下的高性能存储方案
八步排除LED显示屏系统故障
广告的影响能有多坏?
安捷伦E4440A频谱分析仪Agilent 26.5G频谱仪
自动驾驶汽车像智能手机一样具有变革性的技术
北京通信行业将围绕四个中心功能建设大力推进5G网络的高质量发展
新唐科技ISD91260C芯片介绍