我在过去几天将DJI SDK从4.3.2更新到4.4.1。我正试图让它工作,但它在某种程度上无法识别我何时连接无人机的遥控器。
使用的硬件/软件:
智能手机: Google Pixel XL
智能手机操作系统: Android 8.1.0
无人机:DJI Phantom 4 Pro
DJI SDK: 4.4.1
请注意,我不需要使用API级别> = 26,因为其他依赖项,我不能低于此。
的build.gradle
apply plugin: 'com.android.application'
repositories {
maven { url 'https://maven.google.com' }
}
android {
compileSdkVersion 26
buildToolsVersion '26.0.2'
defaultConfig {
applicationId "com.test.droneapp"
minSdkVersion 19
targetSdkVersion 26
versionCode 9
versionName "1.0"
//Enabling multidex support
multiDexEnabled true
vectorDrawables.useSupportLibrary = true
useLibrary 'org.apache.http.legacy'
ndk {
abiFilters 'armeabi-v7a', 'x86', 'arm64-v8a'
}
}
lintOptions {
disable 'MissingTranslation'
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
dexOptions {
preDexLibraries = false
javaMaxHeapSize "4g"
}
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"
}
}
repositories {
flatDir {
dirs 'libs'
}
google()
}
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
// Support Library
compile "com.android.support:support-v4:26.1.0"
compile "com.android.support:recyclerview-v7:26.1.0"
compile "com.android.support:appcompat-v7:26.1.0"
compile "com.android.support:design:26.1.0"
// Google Play Services
compile "com.google.android.gms:play-services-maps:11.6.2"
compile "com.google.android.gms:play-services-auth:11.6.2"
compile "com.google.android.gms:play-services-gcm:11.6.2"
compile "com.google.android.gms:play-services-location:11.6.2"
// MultiDex
compile 'com.android.support:multidex:1.0.1'
// DJI SDK
// compile ('com.dji:dji-sdk:4.3.2')
compile 'com.dji:dji-sdk:4.4.1'
provided 'com.dji:dji-sdk-provided:4.4.1'
}
LauncherApplication.java
package com.test.droneapp;
import android.app.Application;
import android.content.Context;
import android.os.Environment;
import android.support.multidex.MultiDex;
import com.crashlytics.android.Crashlytics;
import com.secneo.sdk.Helper;
import java.io.File;
import io.fabric.sdk.android.Fabric;
public class LauncherApplication extends Application {
private DJIApplication mDJIApplication;
@Override
protected void attachBaseContext(Context paramContext) {
super.attachBaseContext(paramContext);
MultiDex.install(this);
Helper.install(this);
if (mDJIApplication == null) {
mDJIApplication = new DJIApplication();
mDJIApplication.setContext(this);
}
}
@Override
public void onCreate() {
super.onCreate();
mDJIApplication.onCreate();
// Initialize Fabric
Fabric.with(this, new Crashlytics());
}
}
DJIApplication.java
package com.test.droneapp;
import android.app.Application;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.support.v4.content.ContextCompat;
import android.util.Log;
import android.widget.Toast;
import dji.common.error.DJIError;
import dji.common.error.DJISDKError;
import dji.sdk.base.BaseComponent;
import dji.sdk.base.BaseProduct;
import dji.sdk.camera.Camera;
import dji.sdk.products.Aircraft;
import dji.sdk.products.HandHeld;
import dji.sdk.sdkmanager.DJISDKManager;
public class DJIApplication extends Application {
private static final String TAG = "DroneApp";
public static final String FLAG_CONNECTION_CHANGE = "dji_sdk_connection_change";
private DJISDKManager.SDKManagerCallback mDJISDKManagerCallback;
private BaseProduct.BaseProductListener mDJIBaseProductListener;
private BaseComponent.ComponentListener mDJIComponentListener;
private static BaseProduct mProduct;
public Handler mHandler;
private Application instance;
public void setContext(Application application) {
instance = application;
}
@Override
public Context getApplicationContext() {
return instance;
}
public DJIApplication() {
}
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 isProductModuleAvailable() {
return (null != DJIApplication.getProductInstance());
}
public static boolean isCameraModuleAvailable() {
return isProductModuleAvailable() &&
(null != DJIApplication.getProductInstance().getCamera());
}
public static boolean isPlaybackAvailable() {
return isCameraModuleAvailable() &&
(null != DJIApplication.getProductInstance().getCamera().getPlaybackManager());
}
@Override
public void onCreate() {
super.onCreate();
mHandler = new Handler(Looper.getMainLooper());
mDJIComponentListener = new BaseComponent.ComponentListener() {
@Override
public void onConnectivityChange(boolean isConnected) {
notifyStatusChange();
}
};
mDJIBaseProductListener = new BaseProduct.BaseProductListener() {
@Override
public void onComponentChange(BaseProduct.ComponentKey key, BaseComponent oldComponent, BaseComponent newComponent) {
if (newComponent != null) {
newComponent.setComponentListener(mDJIComponentListener);
}
notifyStatusChange();
}
@Override
public void onConnectivityChange(boolean isConnected) {
notifyStatusChange();
}
};
/**
* 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) {
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(), "Register Success", Toast.LENGTH_LONG).show();
}
});
DJISDKManager.getInstance().startConnectionToProduct();
} else {
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(), "Register sdk fails, check network is available", Toast.LENGTH_LONG).show();
}
});
}
Log.e("TAG", error.toString());
}
//Listens to the connected product changing, including two parts, component changing or product connection changing.
@Override
public void onProductChange(BaseProduct oldProduct, BaseProduct newProduct) {
mProduct = newProduct;
if (mProduct != null) {
mProduct.setBaseProductListener(mDJIBaseProductListener);
}
notifyStatusChange();
}
};
//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);
Toast.makeText(getApplicationContext(), "registering, pls wait...", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(getApplicationContext(), "Please check if the permission is granted.", Toast.LENGTH_LONG).show();
}
}
private void notifyStatusChange() {
mHandler.removeCallbacks(updateRunnable);
mHandler.postDelayed(updateRunnable, 500);
}
private Runnable updateRunnable = new Runnable() {
@Override
public void run() {
Intent intent = new Intent(FLAG_CONNECTION_CHANGE);
getApplicationContext().sendBroadcast(intent);
}
};
}
ConnectionActivity.java(只是重要部分......)
package com.test.droneapp;
import android.Manifest;
import android.app.Dialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.graphics.Color;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.TextView;
import com.airbnb.lottie.LottieAnimationView;
import com.airbnb.lottie.SimpleColorFilter;
import com.geniusforapp.fancydialog.FancyAlertDialog;
import com.securepreferences.SecurePreferences;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import com.test.droneapp.utils.NetworkUtils;
import com.test.droneapp.utils.SystemUtils;
import com.test.droneapp.utils.UIUtils;
import dji.common.error.DJIError;
import dji.common.error.DJISDKError;
import dji.log.DJILog;
import dji.sdk.base.BaseProduct;
import dji.sdk.sdkmanager.DJISDKManager;
public class ConnectionActivity extends AppCompatActivity implements View.OnClickListener {
private static final String TAG = "droneapp";
private static final String[] REQUIRED_PERMISSION_LIST = new String[]{
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,
};
private List<String> missingPermission = new ArrayList<>();
private AtomicBoolean isRegistrationInProgress = new AtomicBoolean(false);
private static final int REQUEST_PERMISSION_CODE = 12345;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
checkAndRequestPermissions();
setContentView(R.layout.activity_connection);
initUI();
// Register the broadcast receiver for receiving the device connection's changes.
IntentFilter filter = new IntentFilter();
filter.addAction(DJIApplication.FLAG_CONNECTION_CHANGE);
registerReceiver(mReceiver, filter);
}
@Override
public void onResume() {
Log.e(TAG, "onResume");
super.onResume();
}
@Override
public void onPause() {
Log.e(TAG, "onPause");
super.onPause();
}
@Override
public void onStop() {
Log.e(TAG, "onStop");
super.onStop();
}
@Override
protected void onDestroy() {
Log.e(TAG, "onDestroy");
unregisterReceiver(mReceiver);
super.onDestroy();
}`
/**
* Checks if there is any missing permissions, and
* requests runtime permission if needed.
*/
private void checkAndRequestPermissions() {
// Check for permissions
for (String eachPermission : REQUIRED_PERMISSION_LIST) {
if (ContextCompat.checkSelfPermission(this, eachPermission) != PackageManager.PERMISSION_GRANTED) {
missingPermission.add(eachPermission);
}
}
// Request for missing permissions
if (!missingPermission.isEmpty() && Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
ActivityCompat.requestPermissions(this,
missingPermission.toArray(new String[missingPermission.size()]),
REQUEST_PERMISSION_CODE);
} else {
startSDKRegistration();
}
}
/**
* Result of runtime permission request
*/
@Override
public void onRequestPermissionsResult(int requestCode,
@NonNull String[] permissions,
@NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
// Check for granted permission and remove from missing list
if (requestCode == REQUEST_PERMISSION_CODE) {
for (int i = grantResults.length - 1; i >= 0; i--) {
if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
missingPermission.remove(permissions[i]);
}
}
}
// If there is enough permission, we will start the registration
if (missingPermission.isEmpty()) {
startSDKRegistration();
} else {
UIUtils.errorSnacky("Missing permissions!!!");
}
}
protected BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
refreshSDKRelativeUI();
}
};
private void startSDKRegistration() {
if (isRegistrationInProgress.compareAndSet(false, true)) {
AsyncTask.execute(new Runnable() {
@Override
public void run() {
showToast( "registering, pls wait...");
DJISDKManager.getInstance().registerApp(getApplicationContext(), new DJISDKManager.SDKManagerCallback() {
@Override
public void onRegister(DJIError djiError) {
if (djiError == DJISDKError.REGISTRATION_SUCCESS) {
DJILog.e("App registration", DJISDKError.REGISTRATION_SUCCESS.getDescription());
DJISDKManager.getInstance().startConnectionToProduct();
runOnUiThread(new Runnable() {
@Override
public void run() {
UIUtils.successSnacky("Register Success");
}
});
} else {
runOnUiThread(new Runnable() {
@Override
public void run() {
UIUtils.errorSnacky( "Register sdk fails, check network is available");
}
});
}
Log.v(TAG, djiError.getDescription());
}
@Override
public void onProductChange(BaseProduct oldProduct, BaseProduct newProduct) {
Log.d(TAG, String.format("onProductChanged oldProduct:%s, newProduct:%s", oldProduct, newProduct));
}
});
}
});
}
}
}
的AndroidManifest.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.test.droneapp">
<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.WAKE_LOCK" />
<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.MOUNT_UNMOUNT_FILESYSTEMS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<uses-permission android:name="android.permission.CHANGE_CONFIGURATION" />
<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" />
<application
android:name=".LauncherApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme"
tools:replace="android:icon">
<!-- DJI SDK -->
<uses-library android:name="com.android.future.usb.accessory" />
<meta-data
android:name="com.dji.sdk.API_KEY"
android:value="XXXXXXXXXXXXXXXXXXXXXX" />
<activity
android:name="dji.sdk.sdkmanager.DJIAoaControllerActivity"
android:theme="@android:style/Theme.Translucent" >
<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" >
</service>
<!-- DJI SDK -->
<meta-data
android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" />
<activity
android:name=".ConnectionActivity"
android:label="@string/app_name"
android:screenOrientation="landscape">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
4.3.2一切都运行良好,更新后我跟着DJI网站上的指南,让它工作但我无法弄清楚我做错了什么。
任何帮助将不胜感激!
答案 0 :(得分:0)
您可以使用RemoteController
类
Application
个对象
/**
* This method is used for getting RemoteController instance.
*
* @return
*/
public static synchronized RemoteController getRemoteControllerInstance() {
if (!isAircraftConnected()) return null;
return getAircraftInstance().getRemoteController();
}