以下介绍如何在Android Studio上搭建开发环境,并使用视图控件进行开发。
新建工程
在Android Studio中新建工程,操作如下:
图:创建工程 |
图:添加工程信息 |
配置Gradle
以下与其它Android开发环境类似,若您熟悉该流程,可跳过该步骤。
7.0以下版本
此处使用gradle6.5,若要使用7.0版本及其以上的gradle,注意环境配置差异。
现打开Project Structure,在Project栏中指定对应版本。
图:设置工程结构 |
图:设置Gradle版本 |
项目build.gradle文件参考:
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
google()
mavenCentral()
maven { url 'https://jitpack.io' }
}
dependencies {
classpath "com.android.tools.build:gradle:4.1.2"
}
}
allprojects {
repositories {
maven { url 'https://jitpack.io' }
google()
jcenter()
}
}
项目settings.gradle文件参考:
rootProject.name = "项目工程名称"
include ':模块名称'
7.0版本
第一步,打开Android Studio项目级“build.gradle”文件,添加Maven代码库。 在“buildscript > repositories”中配置Maven仓地址。
buildscript {
repositories {
google()
jcenter()
maven {url "https://..." }
}
}
第二步,打开项目级“settings.gradle”文件,配置Maven仓地址。
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
repositories {
google()
jcenter()
maven {url "https://..." }
}
}
}
7.1及以上版本
第一步,打开Android Studio项目级“build.gradle”文件,添加Maven代码库。 在“buildscript > repositories”中配置Maven仓地址。
buildscript {
repositories {
google()
jcenter()
maven {url "https://..." }
}
}
第二步,打开项目级“settings.gradle”文件,配置Maven仓地址。
pluginManagement {
repositories {
repositories {
google()
jcenter()
maven {url "https://..." }
}
}
}
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
repositories {
google()
jcenter()
maven {url "https://..." }
}
}
}
配置模块Gradle
以下与其它安卓开发环境类似。若您熟悉该流程,可跳过该步骤,关注jar与so导入即可。
配置模块的build.gradle,引入产品包中的so库和jar包。
将so库和jar包拷贝至项目如下位置。
图:添加so库和jar包到项目工程 |
本地视频开发
不引入DJI MSDK,适用于本地视频地图的开发。
build.gradle参考如下:
plugins {
id 'com.android.application'
}
android {
compileSdkVersion 28
defaultConfig {
applicationId "com.supermap.appuav_scene3d"
minSdkVersion 24
targetSdkVersion 28
versionCode 1
versionName "1.0"
ndk{
//abiFilters 'arm64-v8a'//使用64位的so
abiFilters 'armeabi-v7a'
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
sourceSets {
main {
jniLibs.srcDirs = ['libs']
}
}
}
dependencies {
implementation 'androidx.appcompat:appcompat:1.3.0'
implementation 'com.google.android.material:material:1.4.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
//注意:当前版本的sceneform-sm
implementation files('libs\\sceneform-sm-11.0.1.aar')
implementation files('libs\\com.supermap.data_v1100.jar')
implementation files(libs\\com.supermap.ar_v1100.jar')
//按需添加以下内容
//implementation files(libs\\com.supermap.mapping_v1100.jar')
//implementation files('libs\\com.supermap.realspace_v1101.jar')
}
实时视频开发
通过引入DJI MSDK接入大疆无人机的实时视频。在依赖配置上需要额外依赖DJI的SDK。
在build.gradle文件的dependencies节点下添加如下内容:
implementation 'androidx.multidex:multidex:2.0.0'
implementation 'com.squareup:otto:1.3.8'
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
implementation ('com.dji:dji-uxsdk:4.16', {
/**
* Uncomment the following line to exclude amap from the app.
* Note that Google Play Store does not allow APKs that include this library.
*/
exclude group: 'com.amap.api'
exclude group: 'com.mapbox.mapboxsdk'
})
compileOnly ('com.dji:dji-sdk-provided:4.16.1')
此外,为了防止DJI MSDK内部可能引起的依赖冲突。需要在build.gradle文件的android节点下,添加如下内容:
//use DJI SDK,添加 packagingOptions 以防冲突。
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'
//exclude 'META-INF/dji-sdk-lib_aar.kotlin_module'
}
完整的build.gradle文件参考如下:
plugins {
id 'com.android.application'
}
android {
compileSdk 28
defaultConfig {
applicationId "com.supermap.uavfly"
minSdk 24
targetSdk 28
versionCode 1
versionName "1.0"
ndk{
abiFilters 'armeabi-v7a'
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
sourceSets {
main {
jniLibs.srcDirs = ['libs']
}
}
//use DJI SDK,添加 packagingOptions 以防程序出现意外崩溃。
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'
//exclude 'META-INF/dji-sdk-lib_aar.kotlin_module'
}
}
dependencies {
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'com.google.android.material:material:1.1.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
//use DJI SDK
implementation 'androidx.multidex:multidex:2.0.0'
implementation 'com.squareup:otto:1.3.8'
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
implementation ('com.dji:dji-uxsdk:4.16', {
/**
* Uncomment the following line to exclude amap from the app.
* Note that Google Play Store does not allow APKs that include this library.
*/
exclude group: 'com.amap.api'
exclude group: 'com.mapbox.mapboxsdk'
})
compileOnly ('com.dji:dji-sdk-provided:4.16.1')
implementation 'pub.devrel:easypermissions:2.0.1'//权限申请
implementation files('libs\\sceneform-sm-11.0.1.aar')
implementation files('libs\\com.supermap.data_v1100.jar')
implementation files(libs\\com.supermap.ar_v1100.jar')
//按需添加以下内容
//implementation files(libs\\com.supermap.mapping_v1100.jar')
//implementation files('libs\\com.supermap.realspace_v1101.jar')
}
配置Android清单
每个Android应用都需要一个名为AndroidManifest.xml的程序清单文件,这个清单文件名是固定的并且放在每个Android应用的根目录下。
正常情况下,采用本地视频的开发方式,添加上手机的读写权限、网络相关权限即可。若是采用实时视频的开发方式,则需要连接无人机。
这可参考大疆的应用激活示例,链接如下: https://github.com/DJI-Mobile-SDK-Tutorials。
以下是采用USB连接方式的安卓清单(AndroidMainifest.xml)示例。
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.supermap.uavfly2">
<!-- DJI SDK need permission ↓ ↓ ↓-->
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />
<uses-feature android:name="android.hardware.usb.host" android:required="false" />
<uses-feature android:name="android.hardware.usb.accessory" android:required="true" />
<!-- SDK requirement permission ↑ ↑ ↑-->
<application
android:name="com.supermap.ar.areffect.uavfly.DJIFlyApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name_uav"
android:supportsRtl="true"
android:theme="@style/Theme.UavFly"
tools:replace="android:label">
<!-- ↓ ↓ ↓ ↓ ↓ ↓ DJI SDK 配置 ↓ ↓ ↓ ↓ ↓ ↓ -->
<uses-library android:name="com.android.future.usb.accessory" />
<uses-library
android:name="org.apache.http.legacy"
android:required="false" />
<meta-data
android:name="com.dji.sdk.API_KEY"
android:value="这里是DJI APP KEY" />
<activity
android:name="dji.sdk.sdkmanager.DJIAoaControllerActivity"
android:theme="@android:style/Theme.Translucent"
tools:ignore="IntentFilterExportedReceiver">
<intent-filter>
<action android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED" />
</intent-filter>
<meta-data
android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED"
android:resource="@xml/accessory_filter" />
</activity>
<service
android:name="dji.sdk.sdkmanager.DJIGlobalService"
tools:ignore="Instantiatable"></service>
<!-- ↑ ↑ ↑ ↑ ↑ ↑ DJI SDK 配置 ↑ ↑ ↑ ↑ ↑ ↑-->
<activity
android:name="com.supermap.MainActivity"
android:screenOrientation="landscape"
android:theme="@style/Theme.UavFly2"
tools:ignore="IntentFilterExportedReceiver">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
至此,开发环境已搭建完成。
编写代码
布局文件
(1). 在layout中添加视图控件(也可通过代码创建视图控件,这与使用RealativeLayout的方式一致)。
图:在layout中添加视图控件 |
(2). 在layout中添加一个按钮,用于控制视频的播放与暂停。
图:在layout中添加按钮 |
(3). 在layout中添加一个时间轴,便于视频播放位置的调节。
图:在layout中添加时间轴 |
应用代码
在MainActivity中编写应用程序代码如下:
/**
* 无人机视频简单开发模板
*/
public class MainActivity extends AppCompatActivity {
private UAVVideoEffectView effectView;
private UAVVideoTimeLine timeLine;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.INTERNET,
Manifest.permission.ACCESS_NETWORK_STATE,
Manifest.permission.CHANGE_WIFI_STATE,
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.READ_PHONE_STATE,
}, PackageManager.PERMISSION_GRANTED);
Environment.setLicensePath(StartActivity.LICENSE);
Environment.initialization(this);
setContentView(R.layout.activity_main_scene3d);
//布局控件
effectView = findViewById(R.id.ef_view);
timeLine = findViewById(R.id.uav_video_timeline);
//...读取数据(载入视频数据集)
//绑定时间轴,必须在读取数据后绑定
timeLine.bindView(effectView);
//指定视频到初始位置
effectView.getMediaPlayer().seekTo(0);
//UAV视图实时更新监听事件
effectView.addOnUpdateListener(new EffectView.OnUpdateListener() {
@Override
public void onUpdate() {
//画面更新时回调
}
});
}
@Override
protected void onResume() {
super.onResume();
effectView.onResume();
}
@Override
protected void onPause() {
super.onPause();
effectView.onPause();
}
@Override
protected void onDestroy() {
effectView.onDestroy();
super.onDestroy();
}
//基础事件
public void exchangeAction(View view) {
if (effectView.isPlaying()){
effectView.pause();
}else {
effectView.start();
}
}
}
注:参考“视频接入”部分介绍加载视频。
运行工程
选择真机或者模拟器,点击“运行”,将程序安装到设备中。
运行效果如下图所示。
图:工程运行效果 |