本文以大疆官方给出的Android Mobile SDK为例子,讲解怎么在自己的应用程序中导入该SDK,以及注册生产应用程序密匙。本文内容参考官方的英文文档,需要的朋友可以去文末的网址进行查看。
包含如下步骤:
步骤1: 新建一个工程
步骤2:更新build.gradle
步骤3:进行同步
步骤4:新建一个Java类并继承Application。
步骤5:进行Activity的设置工作
步骤6:配置AndroidManiFest.XML文件
步骤7: 去官网注册APP应用密钥
步骤8: 添加密钥
下面开始进行详细的讲解:
步骤1: 新建一个工程,均按默认设置即可(注意记录好工程名和包名,以便后续进行申请密匙时需要)
步骤2:更新build.gradle(moudle: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"
exclude 'META-INF/rxjava.properties'
}
}
dependencies {
...
compile ('com.dji:dji-sdk:4.7')
provided ('com.dji:dji-sdk-provided:4.7')
}
主要变化是:
• 添加packagingOptions若要防止应用程序意外崩溃,请执行以下操作。
• 添加compile和provided依赖项来导入最新的DJIAndroidSDKMaven依赖项。
• (注:高版本AS已更换关键字compile为implementation,privided关键字也已经过时了,不进行替换编译时会发出警告,但不会影响程序使用,可根据自身要求选择替换或不替换,本文就不进行替换了)
更新后代码如下:
applyplugin:'com.android.application'
android{
compileSdkVersion28
defaultConfig{
applicationId"importsdktest.dji.com.importsdktest"
minSdkVersion19
targetSdkVersion28
versionCode1
versionName"1.0"
testInstrumentationRunner"android.support.test.runner.AndroidJUnitRunner"
}
buildTypes{
release{
minifyEnabledfalse
proguardFilesgetDefaultProguardFile('proguard-android.txt'),'proguard-rules.pro'
}
}
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"
exclude'META-INF/rxjava.properties'
}
}
dependencies{
implementationfileTree(dir:'libs',include:['*.jar'])
implementation'com.android.support:appcompat-v7:28.0.0-rc02'
implementation'com.android.support.constraint:constraint-layout:1.0.2'
testImplementation'junit:junit:4.12'
androidTestImplementation'com.android.support.test:runner:1.0.1'
androidTestImplementation'com.android.support.test.espresso:espresso-core:3.0.1'
compile('com.dji:dji-sdk:4.7')
provided('com.dji:dji-sdk-provided:4.7')
}
步骤3:进行同步,当步骤2完成后依次选择工具->Android->带有Gradle文件的同步项目,进行项目的同步,导入SDK。
同步无任何错误后即可依次选择:文件->项目结构在AndroidStudio菜单中打开“ProjectStructure”窗口。然后选择“app”模块并单击相依性标签。您应该看到最新的DJISDK编译,并提供了已经导入的DJISDK。
如下图所示:
步骤4:当确认成功添加了SDK后在当前的包路径下新建一个Java类并命名为:MApplication
并将其中代码替换如下:
package com.dji.importSDKDemo;
import android.app.Application;
import android.content.Context;
import com.secneo.sdk.Helper;
public class MApplication extends Application {
@Override
protected void attachBaseContext(Context paramContext) {
super.attachBaseContext(paramContext);
Helper.install(MApplication.this);
}
}
步骤5:进行Activity的设置工作
打开MainActivity将里面的原始代码替换如下:
packageimportsdktest.dji.com.importsdktest;
importandroid.Manifest;
importandroid.content.Intent;
importandroid.content.pm.PackageManager;
importandroid.os.AsyncTask;
importandroid.os.Build;
importandroid.os.Bundle;
importandroid.os.Handler;
importandroid.os.Looper;
importandroid.support.annotation.NonNull;
importandroid.support.v4.app.ActivityCompat;
importandroid.support.v4.content.ContextCompat;
importandroid.support.v7.app.AppCompatActivity;
importandroid.util.Log;
importandroid.widget.Toast;
importjava.util.ArrayList;
importjava.util.List;
importjava.util.concurrent.atomic.AtomicBoolean;
importdji.common.error.DJIError;
importdji.common.error.DJISDKError;
importdji.sdk.base.BaseComponent;
importdji.sdk.base.BaseProduct;
importdji.sdk.sdkmanager.DJISDKManager;
publicclassMainActivityextendsAppCompatActivity{
privatestaticfinalStringTAG=MainActivity.class.getName();
publicstaticfinalStringFLAG_CONNECTION_CHANGE="dji_sdk_connection_change";
privatestaticBaseProductmProduct;
privateHandlermHandler;
privatestaticfinalString[]REQUIRED_PERMISSION_LIST=newString[]{
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.WRITE_EXTERNAL_STORAGE,
Manifest.permission.BLUETOOTH,
Manifest.permission.BLUETOOTH_ADMIN,
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.READ_PHONE_STATE,
};
privateList<String>missingPermission=newArrayList<>();
privateAtomicBooleanisRegistrationInProgress=newAtomicBoolean(false);
privatestaticfinalintREQUEST_PERMISSION_CODE=12345;
@Override
protectedvoidonCreate(BundlesavedInstanceState){
super.onCreate(savedInstanceState);
//Whenthecompileandtargetversionishigherthan22,pleaserequestthefollowingpermissionatruntimetoensuretheSDKworkswell.
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.M){
checkAndRequestPermissions();
}
setContentView(R.layout.activity_main);
//InitializeDJISDKManager
mHandler=newHandler(Looper.getMainLooper());
}
/**
*Checksifthereisanymissingpermissions,and
*requestsruntimepermissionifneeded.
*/
privatevoidcheckAndRequestPermissions(){
//Checkforpermissions
for(StringeachPermission:REQUIRED_PERMISSION_LIST){
if(ContextCompat.checkSelfPermission(this,eachPermission)!=PackageManager.PERMISSION_GRANTED){
missingPermission.add(eachPermission);
}
}
//Requestformissingpermissions
if(missingPermission.isEmpty()){
startSDKRegistration();
}elseif(Build.VERSION.SDK_INT>=Build.VERSION_CODES.M){
showToast("Needtograntthepermissions!");
ActivityCompat.requestPermissions(this,
missingPermission.toArray(newString[missingPermission.size()]),
REQUEST_PERMISSION_CODE);
}
}
/**
*Resultofruntimepermissionrequest
*/
@Override
publicvoidonRequestPermissionsResult(intrequestCode,
@NonNullString[]permissions,
@NonNullint[]grantResults){
super.onRequestPermissionsResult(requestCode,permissions,grantResults);
//Checkforgrantedpermissionandremovefrommissinglist
if(requestCode==REQUEST_PERMISSION_CODE){
for(inti=grantResults.length-1;i>=0;i--){
if(grantResults[i]==PackageManager.PERMISSION_GRANTED){
missingPermission.remove(permissions[i]);
}
}
}
//Ifthereisenoughpermission,wewillstarttheregistration
if(missingPermission.isEmpty()){
startSDKRegistration();
}else{
showToast("Missingpermissions!!!");
}
}
privatevoidstartSDKRegistration(){
if(isRegistrationInProgress.compareAndSet(false,true)){
AsyncTask.execute(newRunnable(){
@Override
publicvoidrun(){
showToast("registering,plswait...");
DJISDKManager.getInstance().registerApp(MainActivity.this.getApplicationContext(),newDJISDKManager.SDKManagerCallback(){
@Override
publicvoidonRegister(DJIErrordjiError){
if(djiError==DJISDKError.REGISTRATION_SUCCESS){
showToast("RegisterSuccess");
DJISDKManager.getInstance().startConnectionToProduct();
}else{
showToast("Registersdkfails,pleasecheckthebundleidandnetworkconnection!");
}
Log.v(TAG,djiError.getDescription());
}
@Override
publicvoidonProductDisconnect(){
Log.d(TAG,"onProductDisconnect");
showToast("ProductDisconnected");
notifyStatusChange();
}
@Override
publicvoidonProductConnect(BaseProductbaseProduct){
Log.d(TAG,String.format("onProductConnectnewProduct:%s",baseProduct));
showToast("ProductConnected");
notifyStatusChange();
}
@Override
publicvoidonComponentChange(BaseProduct.ComponentKeycomponentKey,BaseComponentoldComponent,
BaseComponentnewComponent){
if(newComponent!=null){
newComponent.setComponentListener(newBaseComponent.ComponentListener(){
@Override
publicvoidonConnectivityChange(booleanisConnected){
Log.d(TAG,"onComponentConnectivityChanged:"+isConnected);
notifyStatusChange();
}
});
}
Log.d(TAG,
String.format("onComponentChangekey:%s,oldComponent:%s,newComponent:%s",
componentKey,
oldComponent,
newComponent));
}
});
}
});
}
}
privatevoidnotifyStatusChange(){
mHandler.removeCallbacks(updateRunnable);
mHandler.postDelayed(updateRunnable,500);
}
privateRunnableupdateRunnable=newRunnable(){
@Override
publicvoidrun(){
Intentintent=newIntent(FLAG_CONNECTION_CHANGE);
sendBroadcast(intent);
}
};
privatevoidshowToast(finalStringtoastMsg){
Handlerhandler=newHandler(Looper.getMainLooper());
handler.post(newRunnable(){
@Override
publicvoidrun(){
Toast.makeText(getApplicationContext(),toastMsg,Toast.LENGTH_LONG).show();
}
});
}
}
步骤6:配置AndroidManiFest.XML文件
配置好后完整的文件代码如下:
<?xmlversion="1.0"encoding="utf-8"?>
<manifestxmlns:android="http://schemas.android.com/apk/res/android"
package="importsdktest.dji.com.importsdktest">
<!--Permissionsandfeatures-->
<uses-permissionandroid:name="android.permission.BLUETOOTH"/>
<uses-permissionandroid:name="android.permission.BLUETOOTH_ADMIN"/>
<uses-permissionandroid:name="android.permission.VIBRATE"/>
<uses-permissionandroid:name="android.permission.INTERNET"/>
<uses-permissionandroid:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permissionandroid:name="android.permission.WAKE_LOCK"/>
<uses-permissionandroid:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permissionandroid:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permissionandroid:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permissionandroid:name="android.permission.CHANGE_WIFI_STATE"/>
<uses-permissionandroid:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permissionandroid:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permissionandroid:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<uses-permissionandroid:name="android.permission.READ_PHONE_STATE"/>
<uses-featureandroid:name="android.hardware.camera"/>
<uses-featureandroid: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"/>
<!--Permissionsandfeatures-->
<application
android:name=".MApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<uses-libraryandroid:name="com.android.future.usb.accessory"/>
<meta-data
android:name="com.dji.sdk.API_KEY"
android:value="PleaseenteryourAppKeyhere."/>
<activity
android:name="dji.sdk.sdkmanager.DJIAoaControllerActivity"
android:theme="@android:style/Theme.Translucent">
<intent-filter>
<actionandroid: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>
<serviceandroid:name="dji.sdk.sdkmanager.DJIGlobalService">
</service>
<activityandroid:name=".MainActivity"
android:configChanges="orientation"
android:screenOrientation="portrait">
<intent-filter>
<actionandroid:name="android.intent.action.MAIN"/>
<categoryandroid:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
</manifest>
(注:在使用官方给出的替换代码时有一行会被AS报错,这是因为此权限已经被禁止使用,因此选择了删除那一行,具体被删除的代码为:
<uses-permissionandroid:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
步骤7去官网注册APP应用密钥
7.1首先登录你自己的大疆开发者账号,然后进入如下界面
点击“CREATE APP”创建一个APP。(在此之前要注意要先选择SDK类型和后面的APP类型才能正确创建,否则点击后没有任何反应)
配置后如上图所示:
点击后出现如上图所示的界面,你现在就需要步骤1创建工程时需要的包名了(如果忘记,可以从AndroidManifest.XML文件开头找到)
填入信息如上图所示;重要的时填入的App名称和package Name 一定要和本地的App一致,否则会导致错误。category可根据情况选择,后续两行也可按个人情况进行填写。
创建成功你创建的App如下所示:此时还需要你用你的邮箱进行激活。点击Resend Email发送一封验证邮件,随后进入邮箱完成验证。
激活后如下图:
从邮箱中进入激活的App界面,复制App Key那一项后面的数字
步骤8:添加密钥
将刚刚复制的数字添加到下图的位置:
然后同步以下;下载进真机或者模拟器
当下载好后,你将会看到如下两个界面代表注册DJI Mobile SDK导入成功了: