大疆Mobile SDK初步开发

1. 从MSDK示例代码开始

  • 配置代码运行环境
    (1)下载Moblie SDK:DJI MSDK下载。
    (2)准备Android开发环境,推荐使用Android Studio 2.1.1以上版本。官网下载网址:Download Android Studio或者 Android Studio

  • 从GitHub上下载Android demo project:Mobile-SDK-Android 。

  • 在大疆官网创建APP KEY。在大疆官网的个人中心的应用一栏中可以生成APP KEY

  • 在创建界面需要注意的是Package Name中需要填写的是实际代码程序中的包名,其余选项随意填写

  • 创建完成后点击打开示例代码中的Manifests->AndroidManifests.xml文件,把App key粘贴到android:value后

  • 连接手机,手机打开USB调试模式,如果Android Android未查询到手机可以在命令提示符中查询adb devices,没有显示连接设备则说明手机未安装adb 驱动

  • 点击run运行程序。

  • 手机连接无人机遥控器测试APP.

2. 进行视频流的接收

  • 在大疆官网文档中详细的介绍了如何完成一个对无人机视频流进行解码:Android Video Stream Decoding Sample - DJI Mobile SDK Documentation.

  • 1.初始化一个NativeHelper的实例对象,来监听来自无人机高空的视频数据。
    2.将原始的H.264视频数据送入FFmpeg中解析。
    3.将解析完成的视频数据从FFmpeg中取出,并将解析后的数据缓存到图像帧序列中
    4.将MediaCodec作为一个解码器,然后对视频中的I帧进行捕获。
    5.解码完成后,可为MediaCodec的输出数据配置一个TextureView或SurfaceView用来对视频画面进行预览,或者调用监听器对解码数据进行监听完成其他操作。
    6.释放FFmpeg和MediaCodec资源。
    
  • 通过上述流程我们能够知道要能够在设备上显示无人机相机画面大体上分为三步:接受无人机视频流、对视频流解码以及把解码后数据输出画面。那么为什么要把无人机传输过来的视频解码为YUV格式呢

  • 原因是在Android系统中,图像是以YUVImage的格式传递的,因此,在存储数据的时候我们就需要使用YUV图像格式。

  • 我们可以下载官网给出的 sample project:Github Page ,在项目代码中大疆给出了两种进行解码的方式:利用大疆自己编写的DJIViedeoStreamDecoder解码器以及利用之前大疆就编写好的DJICodecManager解码器。在布局中分别在livestream_preview_ttvlivestream_preview_sf中显示画面。

  • 在代码meidaDJIVideoStreamDecoder.java文件中我们可以看到初始化解码器MediaCodec的源代码:

  •    /*** Initialize the hardware decoder.*/private void initCodec() {if (width == 0 || height == 0) {return;}if (codec != null) {releaseCodec();}loge("initVideoDecoder----------------------------------------------------------");loge("initVideoDecoder video width = " + width + "  height = " + height);// create the media formatMediaFormat format = MediaFormat.createVideoFormat(VIDEO_ENCODING_FORMAT, width, height);if (surface == null) {logd("initVideoDecoder: yuv output");// The surface is null, which means that the yuv data is needed, so the color format should// be set to YUV420.format.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar);} else {logd("initVideoDecoder: display");// The surface is set, so the color format should be set to format surface.format.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);}try {// Create the codec instance.codec = MediaCodec.createDecoderByType(VIDEO_ENCODING_FORMAT);logd( "initVideoDecoder create: " + (codec == null));// Configure the codec. What should be noted here is that the hardware decoder would not // output any yuv data if a surface is configured into, which mean that if you want the yuv // frames, you should set "null" surface when calling the "configure" method of MediaCodec.//就是说要配置解码器之前要把surface设为"null"codec.configure(format, surface, null, 0);logd( "initVideoDecoder configure");//            codec.configure(format, null, null, 0);if (codec == null) {loge("Can't find video info!");return;}// Start the codeccodec.start();} catch (Exception e) {loge("init codec failed, do it again: " + e);e.printStackTrace();}}
    
  • 下面是解析为YUV格式(MainActivity.java中)的源代码:

  • @Overridepublic void onYuvDataReceived(MediaFormat format, final ByteBuffer yuvFrame, int dataSize, final int width, final int height) {//In this demo, we test the YUV data by saving it into JPG files.//DJILog.d(TAG, "onYuvDataReceived " + dataSize);if (count++ % 30 == 0 && yuvFrame != null) {final byte[] bytes = new byte[dataSize];yuvFrame.get(bytes);//DJILog.d(TAG, "onYuvDataReceived2 " + dataSize);AsyncTask.execute(new Runnable() {@Overridepublic void run() {// two samples here, it may has other color format.//两种像素格式 NV12或者YUV420Pint colorFormat = format.getInteger(MediaFormat.KEY_COLOR_FORMAT);switch (colorFormat) {case MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420SemiPlanar://NV12if (Build.VERSION.SDK_INT <= 23) {  //android API<=23oldSaveYuvDataToJPEG(bytes, width, height);} else {newSaveYuvDataToJPEG(bytes, width, height);}break;case MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar://YUV420PnewSaveYuvDataToJPEG420P(bytes, width, height);break;default:break;}}});}}
    
  • 代码如果有不明白的方法调用或者类名,可以去大疆官网查询相关的API。在本次开发过程中我选择了相对更加稳定和延迟更小的livestream_preview_sf.

  • 初步理解代码内容后,我们可以Run示例程序查看结果。

3. 增加对无人机的初步控制

  • 本步骤参考DJI MSDK开发文档中的Simulator 模拟器功能实现部分,代码以及文件参考: Github Page.

  • 在能显示无人机相机视角的基础上,我们现在的目标是添加飞机的自动起飞和降落以及能操控无人机的虚拟摇杆的功能。

  • 首先自动起飞和自动降落功能在大疆API已经有了,我们只需要很简单的调用以及在Android布局中增加两个按钮即可。

  • 对于按钮点击事件进行判断如下:

  •   //无人机起飞动作实现case R.id.btn_take_off:if (mFlightController != null){mFlightController.startTakeoff(new CommonCallbacks.CompletionCallback() {@Overridepublic void onResult(DJIError djiError) {if (djiError != null) {showToast(djiError.getDescription());} else {showToast("Take off Success");}}});}break;//无人机降落动作实现case R.id.btn_land:if (mFlightController != null){mFlightController.startLanding(djiError -> {if (djiError != null) {showToast(djiError.getDescription());} else {showToast("Start Landing");}});}
  • 我们第二步是增加两个虚拟摇杆,而为了操控杆控件,我们基于OnScreenJoystick文件实施操纵杆控制 。我们主要用到两个文件OnScreenJoystick.javaOnScreenJoystickListener.java.

  • OnScreenJoystickListener.java中看到当我们触摸到虚拟摇杆视图时会触发的监听方法onTouch.

    public interface OnScreenJoystickListener {/** Called when the joystick is touched.* @param joystick The joystick which has been touched.* @param pX The x coordinate of the knob. Values are between -1 (left) and 1 (right).* @param pY The y coordinate of the knob. Values are between -1 (down) and 1 (up).*/public void onTouch(final OnScreenJoystick joystick, final float pX, final float pY);
    }

    方法具体的实现代码如下:

    @Overridepublic boolean onTouch(final View arg0, final MotionEvent pEvent) {final float x = pEvent.getX();final float y = pEvent.getY();switch (pEvent.getAction()) {        //返回动作类型case MotionEvent.ACTION_UP:    //手指离开摇杆时触发if (isAutoCentering()) {mKnobX = Math.round((mBackgroundSize - mKnobSize) * 0.5f);mKnobY = Math.round((mBackgroundSize - mKnobSize) * 0.5f);}break;default:// Check if coordinates are in bounds. If they aren't move the knob// to the closest coordinate inbounds.if (checkBounds(x, y)) {mKnobX = Math.round(x - mKnobSize * 0.5f);mKnobY = Math.round(y - mKnobSize * 0.5f);} else {final double angle = Math.atan2(y - mRadius, x - mRadius);mKnobX = (int) (Math.round(mRadius+ (mRadius - mKnobSize * 0.5f) * Math.cos(angle)) - mKnobSize * 0.5f);mKnobY = (int) (Math.round(mRadius+ (mRadius - mKnobSize * 0.5f) * Math.sin(angle)) - mKnobSize * 0.5f);}}if (mJoystickListener != null) {mJoystickListener.onTouch(this,(0.5f - (mKnobX / (mRadius * 2 - mKnobSize))) * -2,(0.5f - (mKnobY / (mRadius * 2 - mKnobSize))) * 2);}return true;}
    
  • 然后把需要配置文件添加到res中,在大疆文档实现UI界面的第四步配置资源中已经描述的非常清楚了,此处把内容复制在下面:

    • 将示例项目中的joystick.pngjoystick_bg.png文件复制并粘贴到左侧导航器的mipmap文件夹中。
    • 将以下图像和xml文件从教程Github Sample项目的drawable文件夹复制到您的项目中,它们用于按钮的UI:

    • 接下来,打开"colors.xml"文件,并在底部添加以下代码以声明黑色叠加颜色:
    <color name="black_overlay">#66000000</color>
    
    • 此外,打开"strings.xml"文件并添加"success"字符串:
    <string name="success">Success</string>
    
    • 最后,打开"styles.xml"文件并添加以下代码以声明"common_button"样式:
    <!-- Common button style -->
    <style name="common_button"><item name="android:layout_width">100dp</item><item name="android:layout_height">45dp</item><item name="android:layout_marginTop">10dp</item><item name="android:background">@drawable/round_btn</item><item name="android:paddingLeft">5dp</item><item name="android:paddingRight">5dp</item><item name="android:textAllCaps">false</item><item name="android:textColor">@android:color/white</item><item name="android:textSize">14sp</item>
    </style>
    
  • 随后在布局中加入两个摇杆

    <com.dji.simulatorDemo.OnScreenJoystickandroid:id="@+id/directionJoystickLeft"android:layout_width="130dp"android:layout_height="130dp"android:layout_alignParentLeft="true"android:layout_alignParentBottom="true"android:layout_marginBottom="10dp"android:layout_marginLeft="10dp"android:background="@mipmap/joystick_bg"/><com.dji.simulatorDemo.OnScreenJoystickandroid:id="@+id/directionJoystickRight"android:layout_width="130dp"android:layout_height="130dp"android:layout_alignParentRight="true"android:layout_alignParentBottom="true"android:layout_marginBottom="10dp"android:layout_marginRight="10dp"android:background="@mipmap/joystick_bg"/>
    
  • MainActivity中我们初始化UI元素变量,重写onTouch()onClick()方法。

  • 确认根据文档步骤无误后,Run代码查看是否出现问题。

4. 结果展示

  • 后面我又加入了拍照和录象的功能,因为在大疆文档中都有很详细的介绍所以此处不过多赘述。

  • 最后做出来的UI界面如下:

  • 本文只是非常基础的根据大疆官方文档所做的一个练习,供大家参考。

DJI Mobile SDK初步开发相关推荐

  1. 大疆无人机二次开发进阶-DJI mobile SDK和DJI onboard SDK联合开发行业应用项目

    PS:最近又涉及该项目,增加部分没写内容,记录下详细步骤. 上一篇文章讲到了怎么使用DJI mobile SDK,这次主要讲解DJI mobile SDK和DJI onboard SDK联合开发. a ...

  2. 大疆 DJI Mobile SDK 开发:模拟器调试

    目录 创建飞行控制器界面 1.新建Activiity 2.MainActivity activity_main.xml MainActivity.java 3.FlightActivity activ ...

  3. 大疆无人机二次开发简介-引入DJI mobile SDK 4.8

    基于android studio 3.5 1.引入DJI mobile SDK 4.8和DJI UX SDK 4.8 部分build.gradle如下 apply plugin: 'com.andro ...

  4. 大疆 DJI mobile SDK系列详细教程——运行实例代码(跑通大疆官方提供Mobile SDK里的sample code)

    大疆 DJI mobile SDK系列详细教程--运行实例代码(跑通大疆官方提供Mobile SDK里的sample code) 文章目录 一.官方文献与资源地址 二.操作步骤 提示:昨天在尝试跑通大 ...

  5. DJI mobile SDK学习

    DJI Mobile SDK为开发者提供了丰富的API接口,可以供用户按自身需求开发出不同的移动应用软件.根据移动设备平台的不同,Mobile SDK又主要分为IOS SDK与Android SDK, ...

  6. 大疆无人机DJI Mobile SDK入门(一)

    目录: 大疆无人机DJI Mobile SDK(Android)入门(一) 大道无疆,创新无限! 将您的想法变为现实! 未来,无所不能! 小Z码农有幸能接触到这么高逼格的玩具.就将这段爱恨往事作为笔记 ...

  7. 【DJI Mobile SDK】RTMP 推流卡顿问题

    /** * 只对作者个人理解的功能进行描述说明,参考官方说明文档 * 需要其他功能教程或说明请留言或私信 * 需要其他合作请留言或私信 * auth by antman-s */ 项目场景: 使用大疆 ...

  8. DJI Mobile SDK(2):多自由度控制飞行(Virtual Stick)

      由于项目开发需要用电脑控制Mavic进行飞行.最终选择的方案是用手机做一个中转,即"电脑->手机app->遥控器->飞行器",电脑和手机之间采用TCPSock ...

  9. 开发自己的DJI四旋翼无人机(A3飞控Onboard SDK和Mobile SDK介绍)

    大疆作为无人机行业的佼佼者,其应用范围从户外旅行.拍照到影视拍摄,以及工业运用都有着极高的地位.那么,我们如何仅仅使用大疆的飞控来开发出我们自己的无人机呢? 首先,你需要如下的东西: 以及相应的机架, ...

最新文章

  1. MATLAB从入门到精通-以实例的形式带你玩转Matlab三角函数
  2. macOS下使用gcc编译GLUT+CPP的连接语句
  3. 保障实时音视频服务体验,华为云原生媒体网络有7大秘籍
  4. oracle查看表空间的内容,学习笔记:Oracle查看object对象 表空间 表 索引 数据文件的使用空间...
  5. Python内置函数(66)——vars
  6. 通过URL链接将文件下载到本地
  7. 微信小程序实例源码下载
  8. HC32F4 CRC32校验(附软件CRC32校验)
  9. Laravel文档梳理7、视图
  10. 计算机硬件的五大逻辑部分,计算机的硬件系统由五大部分组成(计算机由几部分组成)...
  11. 华为HCNE考试练习题经典模拟题
  12. html视频如何转换成mp4视频格式,将MP4、MPEG、MOV等格式的视频转换成WEBM格式的方法...
  13. 文件快速定位神器(C++小项目实战)
  14. Multisim实现极简数码管显示
  15. 数据库学习笔记2(补遗笔记1)
  16. 解决SVN文件不显示绿色小钩图标问题
  17. 育碧信条:AI 在手,天下我有
  18. 【C语言】变量和常量、数据类型、进制转换、数据存储
  19. 服务器最高安全防御策略选择与差异
  20. (阿里offer)春招知识点总结1:java基础+集合+并发+jvm+ssm

热门文章

  1. Redis5大经典面试题
  2. Android应用生死轮回的那些事儿(4) - 武器库(2)-应用组件查询相关API
  3. 解决console.log打印对象时出现大量省略号问题,以及控制台使用表格方式查看打印数据
  4. 计算机网络实验三:TCP Tahoe与Reno运行机制对比分析
  5. 京东智能店长主图长图功能怎么用?
  6. jeeplus快速开发框架
  7. 微众银行软件测试笔试题,微众银行--java面试题一
  8. 罗永浩:锤子手机一共卖了12万部(但计划50万)……我已经交出微博密码……(老罗想通了:-))...
  9. QT打开外部程序Windows Mac
  10. IOS OpenGL ES GPUImage 色彩加深混合 GPUImageColorBurnBlendFilter