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

上一篇文章(基于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芯片介绍