本节全篇为大疆 Mobile SDK 安卓教程 部分,ios教程参见 IOS教程 .
开始使用UX SDK
在本教程中,您将学习如何使用DJI Android UX SDK和DJI Android SDK轻松创建功能齐全的mini-DJI Go app,具有标准的DJI Go UI和功能。在本教程结束时,您将拥有一个可用于显示相机FPV视图,检查飞机状态,拍摄照片,录制视频等功能的app。
您可以从 Github Page 下载教程的最终示例项目。
我们以Mavic Pro和Nexus 5为例进行演示。有关自定义iPhone设备布局的更多详细信息,请查看教程的Github示例项目。让我们开始吧!
介绍
DJI UX SDK是由UI元素组成的可视化SDK。它可以帮助您简化基于Android的DJI Mobile SDK应用程序的创建。与DJI Go类似的设计,UI元素允许您在应用程序和DJI应用程序之间创建一致的UX。
此外,由于易于使用,UX SDK让您更专注于业务和应用程序逻辑。
由于DJI UX SDK是构建在DJI Mobile SDK和VideoPreviewer之上的,所以在应用程序开发中需要将它们一起使用。
关于DJI UX SDK的深入学习,请访问 UX SDK Introduction 。
在中国进行应用激活和飞机绑定
对于在中国使用的DJI SDK移动应用程序,需要激活应用程序并将飞机绑定到用户的DJI帐户。
如果未激活应用程序,未绑定飞机(如果需要)或使用旧版SDK(<4.1),则将禁用所有** 摄像机实时流 **,并且飞行将限制为直径100米的区域和30米高度,以确保飞机保持在视线范围内。
要了解如何实现此功能,请查看本教程 Application Activation and Aircraft Binding .
导入DJI UX SDK
- 创建新项目,名称为 "UXSDKDemo"
- 输入域名和包名(这里我们使用 "com.dji.uxsdkdemo" )
- 选择手机版,设置最低SDK版本为
API 19: Android 4.4 (KitKat)
- 选择 "Empty Activity"
- 其他默认
配置 Gradle 脚本
打开 "build.gradle(Module: app)" 并添加以下代码:
apply plugin: 'com.android.application'
android {
...
defaultConfig {
...
}
...
packagingOptions{
doNotStrip "*/*/libdjivideo.so"
doNotStrip "*/*/libSDKRelativeJNI.so"
doNotStrip "*/*/libFlyForbid.so"
doNotStrip "*/*/libduml_vision_bokeh.so"
doNotStrip "*/*/libyuv2.so"
doNotStrip "*/*/libGroudStation.so"
doNotStrip "*/*/libFRCorkscrew.so"
doNotStrip "*/*/libUpgradeVerify.so"
doNotStrip "*/*/libFR.so"
pickFirst 'lib/*/libstlport_shared.so'
pickFirst 'lib/*/libRoadLineRebuildAPI.so'
pickFirst 'lib/*/libGNaviUtils.so'
pickFirst 'lib/*/libGNaviMapex.so'
pickFirst 'lib/*/libGNaviData.so'
pickFirst 'lib/*/libGNaviMap.so'
pickFirst 'lib/*/libGNaviSearch.so'
exclude '/lib/armeabi-v7a/libChineseFontPkg.so'
exclude 'META-INF/rxjava.properties'
}
}
dependencies {
...
//compile ('com.dji:dji-uxsdk:4.9')
//provided ('com.dji:dji-sdk-provided:4.9')
implementation 'com.dji:dji-uxsdk:4.9'
compileOnly 'com.dji:dji-sdk-provided:4.9'
}
在上面的代码中,我们实现了以下功能:
- 添加
packagingOptions
以防程序出现意外崩溃。 - 添加
compile
和provided
(新版AS为implementation
和compileOnly
)依赖用来导入最新的DJI Android UX SDK和SDK Maven依赖项。
完成以上步骤后,点击 Sync Now 并等待Gradle Project 同步完成。
双重检查Maven依赖
在Android Studio菜单中选择 File->Project Structure ,打开 "Project Structure" 窗口。然后选择“app”模块并单击 Dependencies 选项卡。你应该看到最新的DJI Android UX SDK compile和sdk provided的依赖项已经导入。
使用UX SDK构建默认布局
现在,让我们继续打开 "activity_main.xml" 文件,并用替换为以下代码:
在上面的xml文件中,我们实现了以下UI:
-
首先,我们添加
dji.ux.widget.FPVWidget
anddji.ux.widget.FPVOverlayWidget
元素来显示第一人称视图(FPV)。 -
接下来,在屏幕顶部,我们创建一个 LinearLayout 去组成顶部状态栏的小组件,如
PreFlightStatusWidget
,FlightModeWidget
,GPSSignalWidget
,RemoteControlSignalWidget
等 -
此外,我们在状态栏下面创建另一个 LinearLayout 去组成相机配置和配置小组件的,如
AutoExposureLockWidget
,FocusExposureSwitchWidget
,CameraConfigISOWidget
,CameraConfigStorageWidget
等。此外,我们添加dji.ui.widget.RemainingFlightTimeWidget
元素,用来显示顶部状态栏小组件集下方的剩余飞行时间组件。 在顶部状态栏下方,我们添加一个
RemainingFlightTimeWidget
用来显示剩余飞行时间。-
在屏幕的底部,我们添加另一个 LinearLayout 来分组
DashboardWidget
。它包括圆形CompassWidget
(罗盘),DistanceHomeWidget
(home距离),HorizontalVelocityWidget
(水平速度),DistanceRCWidget
(遥控器距离),VerticalVelocityWidget
(垂直速度) andAltitudeWidget
(高度) 如下所示: -
在屏幕的左侧,我们添加了一个 LinearLayout 对
TakeOffWidget
和ReturnHomeWidget
进行分组,将其显示为两个按钮。 -
在屏幕右侧,我们添加
dji.ui.widget.controls.CameraControlsWidget
元素以创建一个CameraSettingAdvancedPanel
以显示相机控件组件。点击顶部的菜单按钮将触发CameraSettingAdvancedPanel
。点击中间的切换按钮将在 拍照 和 录像 之间切换相机模式。点击底部按钮将触发CameraSettingExposurePanel
组件显示和隐藏。 -
为了添加
CameraSettingExposurePanel
,我们添加dji.ui.panel.CameraSettingExposurePanel
元素并配置其属性。 -
为了添加
CameraSettingAdvancedPanel
,我们添加dji.ui.panel.CameraSettingAdvancedPanel
元素并配置其属性。 -
最后,我们添加
dji.ui.panel.PreFlightCheckListPanel
元素来创建PreFlightCheckListPanel
。当用户按下时PreFlightStatusWidget
,它将显示在顶部状态栏下方。
完成上述步骤后,打开 "colors.xml" 文件并替换以下内容:
#3F51B5
#303F9F
#FF4081
#242d34
#00000000
#80000000
此外,让我们打开 "styles.xml" 文件并替换以下内容:
在DJI UX SDK的帮助下,在您自己的应用程序中简单直接的实现了标准的DJI Go UI和功能。
应用程序注册
现在让我们使用您从DJI开发者网站申请的 App Key 注册我们的应用程序。如果您不熟悉App Key,请查看 Get Started 。
实现MApplication和DemoApplication
新建一个 "MApplication" 类,然后用以下代码替换:
package com.dji.uxsdkdemo;
import android.app.Application;
import android.content.Context;
import com.secneo.sdk.Helper;
public class MApplication extends Application {
private DemoApplication demoApplication;
@Override
protected void attachBaseContext(Context paramContext) {
super.attachBaseContext(paramContext);
Helper.install(MApplication.this);
if (demoApplication == null) {
demoApplication = new DemoApplication();
demoApplication.setContext(this);
}
}
@Override
public void onCreate() {
super.onCreate();
demoApplication.onCreate();
}
}
在这里,我们重写 attachBaseContext()
方法,然后添加 Helper.install(MApplication.this);
,此外, 重写 onCreate()
方法来调用 DemoApplication
类中的 onCreate()
方法。
Note: 由于现在需要在使用之前加载一些SDK类,所以加载过程由
Helper.install()
完成。开发人员需要在使用任何SDK功能之前调用此方法。如果不这样做,将导致意外崩溃。
完成上述步骤后,我们继续创建 DemoApplication
类,并在本教程的 sample project 中用同名文件替换代码,这里我们解释一下重要部分:
@Override
public void onCreate() {
super.onCreate();
mHandler = new Handler(Looper.getMainLooper());
//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 < Build.VERSION_CODES.M || (permissionCheck == 0 && permissionCheck2 == 0)) {
//This is used to start SDK services and initiate SDK.
DJISDKManager.getInstance().registerApp(getApplicationContext(), mDJISDKManagerCallback);
} else {
Toast.makeText(getApplicationContext(), "Please check if the permission is granted.", Toast.LENGTH_LONG).show();
}
/**
* When starting SDK services, an instance of interface DJISDKManager.DJISDKManagerCallback will be used to listen to
* the SDK Registration result and the product changing.
*/
mDJISDKManagerCallback = new DJISDKManager.SDKManagerCallback() {
//Listens to the SDK registration result
@Override
public void onRegister(DJIError error) {
if(error == DJISDKError.REGISTRATION_SUCCESS) {
DJISDKManager.getInstance().startConnectionToProduct();
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(), "Register Success", Toast.LENGTH_LONG).show();
}
});
loginAccount();
} else {
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(), "Register Failed, check network is available", Toast.LENGTH_LONG).show();
}
});
}
Log.e("TAG", error.toString());
}
@Override
public void onProductDisconnect() {
Log.d("TAG", "onProductDisconnect");
notifyStatusChange();
}
@Override
public void onProductConnect(BaseProduct baseProduct) {
Log.d("TAG", String.format("onProductConnect newProduct:%s", baseProduct));
notifyStatusChange();
}
@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", "onComponentConnectivityChanged: " + isConnected);
notifyStatusChange();
}
});
}
Log.d("TAG",
String.format("onComponentChange key:%s, oldComponent:%s, newComponent:%s",
componentKey,
oldComponent,
newComponent));
}
};
}
我们在这里实现了几个功能:
- 我们重写了
onCreate()
方法,用来检查权限,并且调用了DJISDKManager
的registerApp()
方法用来首先注册应用程序。 - 初始化
SDKManagerCallback
变量,并实现了他的两个接口方法。你可以使用onRegister()
方法去检查App注册状态和显示文本信息通知用户。当产品连接或者断开连接的时候,onProductConnect()
andonProductDisconnect()
方法将被调用。此外,我们使用onComponentChange()
方法去检查组件改变,并调用notifyStatusChange()
方法去通知这次改变。
创建 MApplication
类后,请在 DemoApplication
类的 onCreate()
方法中初始化 DJI Android SDK 类变量,通过调用 Helper.install()
来完成SDK类的加载。
更多详情,请查看本教程的github示例。
修改AndroidManifest文件
完成上述步骤后,我们打开 "AndroidManifest.xml" 文件,并在 application 元素上添加一下元素:
在这里,我们请求的应用程序必须被授权,以便它正确注册DJI SDK。此外,我们还声明了应用程序所使用的相机和USB硬件。
此外,在 application
元素开头添加 android:name=".MApplication"
。
再然后,我们在 "MainActivity" activity 上面添加以下元素:
在上面的代码中,你可以用你申请的 App Key 代替 value 属性中的 "Please enter your App Key here." 。 至于 "accessory_filter.xml" 文件,你可以在教程示例程序中找到它(sdk4.9中已经有了,无需再次添加)。
最后,更新 "MainActivity" activity 元素,如下所示:
在以上代码中,多了一行强制横屏的代码。
处理MainActivity
最后,让我们打开 "MainActivity.java" 文件,替换如下代码:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// When the compile and target version is higher than 22, please request the
// following permissions at runtime to ensure the
// SDK work well.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.VIBRATE,
Manifest.permission.INTERNET, Manifest.permission.ACCESS_WIFI_STATE,
Manifest.permission.WAKE_LOCK, Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.ACCESS_NETWORK_STATE, Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.CHANGE_WIFI_STATE, Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS,
Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.SYSTEM_ALERT_WINDOW,
Manifest.permission.READ_PHONE_STATE,
}
, 1);
}
setContentView(R.layout.activity_main);
}
}
在 onCreate()
方法中,我们在运行时请求几种权限来确保编译和目标SDK版本高于22时可以正常工作。(从Android 6.0 = API 23开始需要动态权限)
现在,我们来构建和运行项目,并安装到你的Android设备上。如果一些ok,当你注册成功时,将会看到 “Register Success” 文本框。
连接到飞机并运行该项目
现在,请检查这个连接移动设备并运行应用程序指南来运行应用程序,并根据我们目前完成的应用程序来试试UX SDK的mini-DJI Go特性!
Connect Mobile Device and Run Application
如果您能够看到实时视频提要并像这样测试这些特性,那么恭喜您!使用DJI UX SDK就是这么简单。
摘要
在本教程中,您已经学习了如何使用DJI Android UX SDK和DJI Android SDK轻松创建一个功能齐全的mini-DJI Go app,具有典型的DJI Go ui和功能。希望你喜欢!