├── .gitignore ├── ActivationAndBindingDemo ├── app │ ├── .gitignore │ ├── build.gradle │ ├── proguard-rules.pro │ └── src │ │ └── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ └── com │ │ │ └── dji │ │ │ └── activationDemo │ │ │ ├── ConnectionActivity.java │ │ │ ├── DemoApplication.java │ │ │ ├── MApplication.java │ │ │ └── MainActivity.java │ │ └── res │ │ ├── drawable │ │ ├── round_btn.xml │ │ ├── round_btn_disable.xml │ │ ├── round_btn_normal.xml │ │ └── round_btn_pressed.xml │ │ ├── layout │ │ ├── activity_connection.xml │ │ └── activity_main.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── raw │ │ └── keep.xml │ │ └── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── import-summary.txt └── settings.gradle ├── LICENSE.txt └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # built application files 2 | *.apk 3 | *.ap_ 4 | 5 | # files for the dex VM 6 | *.dex 7 | 8 | # Java class files 9 | *.class 10 | 11 | # generated files 12 | bin/ 13 | gen/ 14 | obj/ 15 | DJI-SDK-LIB_3.1/build/ 16 | build/ 17 | 18 | # generated file 19 | lint.xml 20 | 21 | # Local configuration file (sdk/lib path, etc) 22 | local.properties 23 | project.properties 24 | 25 | # Eclipse project files 26 | .classpath 27 | .settings/ 28 | 29 | # Proguard folder generated by Eclipse 30 | proguard/ 31 | 32 | # Intellij project files 33 | *.iml 34 | *.ipr 35 | *.iws 36 | .idea/ 37 | 38 | # Mac files 39 | .DS_Store 40 | 41 | # Gradle generated files 42 | .gradle/ 43 | 44 | # Signing files 45 | .signing/ 46 | 47 | # User-specific configurations 48 | .idea/libraries/ 49 | .idea/workspace.xml 50 | .idea/tasks.xml 51 | .idea/.name 52 | .idea/compiler.xml 53 | .idea/copyright/profiles_settings.xml 54 | .idea/encodings.xml 55 | .idea/misc.xml 56 | .idea/modules.xml 57 | .idea/scopes/scope_settings.xml 58 | .idea/vcs.xml 59 | *.iml 60 | 61 | # OS-specific files 62 | .DS_Store 63 | .DS_Store? 64 | ._* 65 | .Spotlight-V100 66 | .Trashes 67 | ehthumbs.db 68 | Thumbs.db 69 | 70 | # Import summary file 71 | import-summary.txt 72 | -------------------------------------------------------------------------------- /ActivationAndBindingDemo/app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /ActivationAndBindingDemo/app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | repositories { 4 | mavenLocal() 5 | } 6 | 7 | android { 8 | compileSdkVersion 30 9 | buildToolsVersion '30.0.2' 10 | useLibrary 'org.apache.http.legacy' 11 | 12 | defaultConfig { 13 | minSdkVersion 19 14 | targetSdkVersion 30 15 | multiDexEnabled true 16 | ndk { 17 | // On x86 devices that run Android API 23 or above, if the application is targeted with API 23 or 18 | // above, FFmpeg lib might lead to runtime crashes or warnings. 19 | abiFilters 'armeabi-v7a', 'arm64-v8a' 20 | } 21 | } 22 | 23 | buildTypes { 24 | release { 25 | minifyEnabled false 26 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 27 | } 28 | debug { 29 | shrinkResources true 30 | minifyEnabled true 31 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 32 | } 33 | } 34 | 35 | dexOptions { 36 | javaMaxHeapSize "4g" 37 | } 38 | 39 | packagingOptions { 40 | doNotStrip "*/*/libdjivideo.so" 41 | doNotStrip "*/*/libSDKRelativeJNI.so" 42 | doNotStrip "*/*/libFlyForbid.so" 43 | doNotStrip "*/*/libduml_vision_bokeh.so" 44 | doNotStrip "*/*/libyuv2.so" 45 | doNotStrip "*/*/libGroudStation.so" 46 | doNotStrip "*/*/libFRCorkscrew.so" 47 | doNotStrip "*/*/libUpgradeVerify.so" 48 | doNotStrip "*/*/libFR.so" 49 | doNotStrip "*/*/libDJIFlySafeCore.so" 50 | doNotStrip "*/*/libdjifs_jni.so" 51 | doNotStrip "*/*/libsfjni.so" 52 | doNotStrip "*/*/libDJICommonJNI.so" 53 | doNotStrip "*/*/libDJICSDKCommon.so" 54 | doNotStrip "*/*/libDJIUpgradeCore.so" 55 | doNotStrip "*/*/libDJIUpgradeJNI.so" 56 | doNotStrip "*/*/libDJIWaypointV2Core.so" 57 | doNotStrip "*/*/libAMapSDK_MAP_v6_9_2.so" 58 | doNotStrip "*/*/libDJIMOP.so" 59 | doNotStrip "*/*/libDJISDKLOGJNI.so" 60 | exclude 'META-INF/rxjava.properties' 61 | } 62 | 63 | compileOptions { 64 | sourceCompatibility JavaVersion.VERSION_1_8 65 | targetCompatibility JavaVersion.VERSION_1_8 66 | } 67 | } 68 | 69 | 70 | dependencies { 71 | implementation 'androidx.multidex:multidex:2.0.1' 72 | implementation 'com.squareup:otto:1.3.8' 73 | implementation('com.dji:dji-sdk:4.15', { 74 | /** 75 | * Uncomment the "library-anti-distortion" if your app does not need Anti Distortion for Mavic 2 Pro and Mavic 2 Zoom. 76 | * Uncomment the "fly-safe-database" if you need database for release, or we will download it when DJISDKManager.getInstance().registerApp 77 | * is called. 78 | * Both will greatly reducing the size of the APK. 79 | */ 80 | exclude module: 'library-anti-distortion' 81 | exclude module: 'fly-safe-database' 82 | }) 83 | compileOnly 'com.dji:dji-sdk-provided:4.15' 84 | 85 | implementation 'androidx.appcompat:appcompat:1.2.0' 86 | implementation 'androidx.core:core:1.3.2' 87 | implementation 'androidx.constraintlayout:constraintlayout:2.0.4' 88 | implementation 'androidx.recyclerview:recyclerview:1.1.0' 89 | implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0' 90 | implementation 'androidx.annotation:annotation:1.2.0' 91 | } 92 | -------------------------------------------------------------------------------- /ActivationAndBindingDemo/app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | -keepattributes Exceptions,InnerClasses,*Annotation*,Signature,EnclosingMethod 2 | 3 | -dontoptimize 4 | -dontpreverify 5 | -dontwarn okio.** 6 | -dontwarn org.bouncycastle.** 7 | -dontwarn dji.** 8 | -dontwarn com.dji.** 9 | -dontwarn sun.** 10 | -dontwarn java.** 11 | -dontwarn com.amap.api.** 12 | -dontwarn com.here.** 13 | -dontwarn com.mapbox.** 14 | -dontwarn okhttp3.** 15 | -dontwarn retrofit2.** 16 | 17 | -keepclassmembers enum * { 18 | public static ; 19 | } 20 | 21 | -keepnames class * implements java.io.Serializable 22 | -keepclassmembers class * implements java.io.Serializable { 23 | static final long serialVersionUID; 24 | private static final java.io.ObjectStreamField[] serialPersistentFields; 25 | !static !transient ; 26 | private void writeObject(java.io.ObjectOutputStream); 27 | private void readObject(java.io.ObjectInputStream); 28 | java.lang.Object writeReplace(); 29 | java.lang.Object readResolve(); 30 | } 31 | -keep class * extends android.os.Parcelable { 32 | public static final android.os.Parcelable$Creator *; 33 | } 34 | 35 | -keep,allowshrinking class * extends dji.publics.DJIUI.** { 36 | public ; 37 | } 38 | 39 | -keep class net.sqlcipher.** { *; } 40 | 41 | -keep class net.sqlcipher.database.* { *; } 42 | 43 | -keep class dji.** { *; } 44 | 45 | -keep class com.dji.** { *; } 46 | 47 | -keep class com.google.** { *; } 48 | 49 | -keep class org.bouncycastle.** { *; } 50 | 51 | -keep,allowshrinking class org.** { *; } 52 | 53 | -keep class com.squareup.wire.** { *; } 54 | 55 | -keep class sun.misc.Unsafe { *; } 56 | 57 | -keep class com.secneo.** { *; } 58 | 59 | -keep class org.greenrobot.eventbus.**{*;} 60 | 61 | -keep class it.sauronsoftware.ftp4j.**{*;} 62 | 63 | -keepclasseswithmembers,allowshrinking class * { 64 | native ; 65 | } 66 | 67 | -keep class * implements com.google.gson.TypeAdapterFactory 68 | -keep class * implements com.google.gson.JsonSerializer 69 | -keep class * implements com.google.gson.JsonDeserializer 70 | 71 | -keep class androidx.appcompat.widget.SearchView { *; } 72 | 73 | -keepclassmembers class * extends android.app.Service 74 | -keepclassmembers public class * extends android.view.View { 75 | void set*(***); 76 | *** get*(); 77 | } 78 | -keepclassmembers class * extends android.app.Activity { 79 | public void *(android.view.View); 80 | } 81 | -keep class androidx.** { *; } 82 | -keep class android.media.** { *; } 83 | -keep class okio.** { *; } 84 | -keep class com.lmax.disruptor.** { *; } 85 | -keep class com.qx.wz.dj.rtcm.* { *; } 86 | 87 | -dontwarn com.mapbox.services.android.location.LostLocationEngine 88 | -dontwarn com.mapbox.services.android.location.MockLocationEngine 89 | -keepclassmembers class * implements android.arch.lifecycle.LifecycleObserver { 90 | (...); 91 | } 92 | # ViewModel's empty constructor is considered to be unused by proguard 93 | -keepclassmembers class * extends android.arch.lifecycle.ViewModel { 94 | (...); 95 | } 96 | # keep Lifecycle State and Event enums values 97 | -keepclassmembers class android.arch.lifecycle.Lifecycle$State { *; } 98 | -keepclassmembers class android.arch.lifecycle.Lifecycle$Event { *; } 99 | # keep methods annotated with @OnLifecycleEvent even if they seem to be unused 100 | # (Mostly for LiveData.LifecycleBoundObserver.onStateChange(), but who knows) 101 | -keepclassmembers class * { 102 | @android.arch.lifecycle.OnLifecycleEvent *; 103 | } 104 | 105 | -keepclassmembers class * implements android.arch.lifecycle.LifecycleObserver { 106 | (...); 107 | } 108 | 109 | -keep class * implements android.arch.lifecycle.LifecycleObserver { 110 | (...); 111 | } 112 | -keepclassmembers class android.arch.** { *; } 113 | -keep class android.arch.** { *; } 114 | -dontwarn android.arch.** 115 | 116 | -keep class org.apache.commons.** {*;} 117 | 118 | 119 | #<------------ utmiss config start------------> 120 | -keep class dji.sdk.utmiss.** { *; } 121 | -keep class utmisslib.** { *; } 122 | #<------------ utmiss config end------------> -------------------------------------------------------------------------------- /ActivationAndBindingDemo/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 25 | 28 | 29 | 30 | 37 | 38 | 39 | 40 | 41 | 42 | 45 | 46 | 47 | 48 | 49 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 65 | 66 | 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /ActivationAndBindingDemo/app/src/main/java/com/dji/activationDemo/ConnectionActivity.java: -------------------------------------------------------------------------------- 1 | package com.dji.activationDemo; 2 | 3 | import android.Manifest; 4 | import android.content.BroadcastReceiver; 5 | import android.content.Context; 6 | import android.content.Intent; 7 | import android.content.IntentFilter; 8 | import android.content.pm.PackageManager; 9 | import android.os.AsyncTask; 10 | import android.os.Build; 11 | import android.os.Bundle; 12 | import android.app.Activity; 13 | import androidx.annotation.NonNull; 14 | import androidx.core.app.ActivityCompat; 15 | import androidx.core.content.ContextCompat; 16 | import android.util.Log; 17 | import android.view.View; 18 | import android.widget.Button; 19 | import android.widget.TextView; 20 | import android.widget.Toast; 21 | 22 | import java.util.ArrayList; 23 | import java.util.List; 24 | import java.util.concurrent.atomic.AtomicBoolean; 25 | 26 | import dji.common.error.DJIError; 27 | import dji.common.error.DJISDKError; 28 | import dji.log.DJILog; 29 | import dji.sdk.base.BaseComponent; 30 | import dji.sdk.base.BaseProduct; 31 | import dji.sdk.products.Aircraft; 32 | import dji.sdk.sdkmanager.DJISDKInitEvent; 33 | import dji.sdk.sdkmanager.DJISDKManager; 34 | 35 | public class ConnectionActivity extends Activity implements View.OnClickListener { 36 | 37 | private static final String TAG = ConnectionActivity.class.getName(); 38 | 39 | private TextView mTextConnectionStatus; 40 | private TextView mTextProduct; 41 | private Button mBtnOpen; 42 | private TextView mVersionTv; 43 | 44 | private static final String[] REQUIRED_PERMISSION_LIST = new String[]{ 45 | Manifest.permission.BLUETOOTH, 46 | Manifest.permission.BLUETOOTH_ADMIN, 47 | Manifest.permission.VIBRATE, 48 | Manifest.permission.INTERNET, 49 | Manifest.permission.ACCESS_WIFI_STATE, 50 | Manifest.permission.ACCESS_COARSE_LOCATION, 51 | Manifest.permission.ACCESS_NETWORK_STATE, 52 | Manifest.permission.ACCESS_FINE_LOCATION, 53 | Manifest.permission.CHANGE_WIFI_STATE, 54 | Manifest.permission.RECORD_AUDIO, 55 | Manifest.permission.WRITE_EXTERNAL_STORAGE, 56 | Manifest.permission.READ_EXTERNAL_STORAGE, 57 | Manifest.permission.READ_PHONE_STATE, 58 | }; 59 | 60 | private List missingPermission = new ArrayList<>(); 61 | private AtomicBoolean isRegistrationInProgress = new AtomicBoolean(false); 62 | private static final int REQUEST_PERMISSION_CODE = 12345; 63 | 64 | @Override 65 | protected void onCreate(Bundle savedInstanceState) { 66 | super.onCreate(savedInstanceState); 67 | 68 | checkAndRequestPermissions(); 69 | setContentView(R.layout.activity_connection); 70 | 71 | initUI(); 72 | 73 | // Register the broadcast receiver for receiving the device connection's changes. 74 | IntentFilter filter = new IntentFilter(); 75 | filter.addAction(DemoApplication.FLAG_CONNECTION_CHANGE); 76 | registerReceiver(mReceiver, filter); 77 | 78 | } 79 | 80 | /** 81 | * Checks if there is any missing permissions, and 82 | * requests runtime permission if needed. 83 | */ 84 | private void checkAndRequestPermissions() { 85 | // Check for permissions 86 | for (String eachPermission : REQUIRED_PERMISSION_LIST) { 87 | if (ContextCompat.checkSelfPermission(this, eachPermission) != PackageManager.PERMISSION_GRANTED) { 88 | missingPermission.add(eachPermission); 89 | } 90 | } 91 | // Request for missing permissions 92 | if (!missingPermission.isEmpty() && Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { 93 | ActivityCompat.requestPermissions(this, 94 | missingPermission.toArray(new String[missingPermission.size()]), 95 | REQUEST_PERMISSION_CODE); 96 | } 97 | 98 | } 99 | 100 | /** 101 | * Result of runtime permission request 102 | */ 103 | @Override 104 | public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { 105 | super.onRequestPermissionsResult(requestCode, permissions, grantResults); 106 | // Check for granted permission and remove from missing list 107 | if (requestCode == REQUEST_PERMISSION_CODE) { 108 | for (int i = grantResults.length - 1; i >= 0; i--) { 109 | if (grantResults[i] == PackageManager.PERMISSION_GRANTED) { 110 | missingPermission.remove(permissions[i]); 111 | } 112 | } 113 | } 114 | // If there is enough permission, we will start the registration 115 | if (missingPermission.isEmpty()) { 116 | startSDKRegistration(); 117 | } else { 118 | showToast("Missing permissions!!!"); 119 | } 120 | } 121 | 122 | private void startSDKRegistration() { 123 | if (isRegistrationInProgress.compareAndSet(false, true)) { 124 | AsyncTask.execute(new Runnable() { 125 | @Override 126 | public void run() { 127 | showToast( "registering, pls wait..."); 128 | DJISDKManager.getInstance().registerApp(getApplicationContext(), new DJISDKManager.SDKManagerCallback() { 129 | @Override 130 | public void onRegister(DJIError djiError) { 131 | if (djiError == DJISDKError.REGISTRATION_SUCCESS) { 132 | DJILog.e("App registration", DJISDKError.REGISTRATION_SUCCESS.getDescription()); 133 | DJISDKManager.getInstance().startConnectionToProduct(); 134 | showToast("Register Success"); 135 | } else { 136 | showToast( "Register sdk fails, check network is available"); 137 | } 138 | Log.v(TAG, djiError.getDescription()); 139 | } 140 | 141 | @Override 142 | public void onProductDisconnect() { 143 | Log.d(TAG, "onProductDisconnect"); 144 | showToast("Product Disconnected"); 145 | 146 | } 147 | 148 | @Override 149 | public void onProductConnect(BaseProduct baseProduct) { 150 | Log.d(TAG, String.format("onProductConnect newProduct:%s", baseProduct)); 151 | showToast("Product Connected"); 152 | 153 | } 154 | 155 | @Override 156 | public void onProductChanged(BaseProduct baseProduct) { 157 | 158 | } 159 | 160 | @Override 161 | public void onComponentChange(BaseProduct.ComponentKey componentKey, BaseComponent oldComponent, 162 | BaseComponent newComponent) { 163 | if (newComponent != null) { 164 | newComponent.setComponentListener(new BaseComponent.ComponentListener() { 165 | 166 | @Override 167 | public void onConnectivityChange(boolean isConnected) { 168 | Log.d(TAG, "onComponentConnectivityChanged: " + isConnected); 169 | } 170 | }); 171 | } 172 | Log.d(TAG, String.format("onComponentChange key:%s, " + "oldComponent:%s, " + "newComponent:%s", 173 | componentKey, oldComponent, newComponent)); 174 | } 175 | @Override 176 | public void onInitProcess(DJISDKInitEvent djisdkInitEvent, int i) { 177 | 178 | } 179 | 180 | @Override 181 | public void onDatabaseDownloadProgress(long l, long l1) { 182 | 183 | } 184 | }); 185 | } 186 | }); 187 | } 188 | } 189 | 190 | @Override 191 | public void onResume() { 192 | Log.e(TAG, "onResume"); 193 | super.onResume(); 194 | } 195 | 196 | @Override 197 | public void onPause() { 198 | Log.e(TAG, "onPause"); 199 | super.onPause(); 200 | } 201 | 202 | @Override 203 | public void onStop() { 204 | Log.e(TAG, "onStop"); 205 | super.onStop(); 206 | } 207 | 208 | public void onReturn(View view){ 209 | Log.e(TAG, "onReturn"); 210 | this.finish(); 211 | } 212 | 213 | @Override 214 | protected void onDestroy() { 215 | Log.e(TAG, "onDestroy"); 216 | unregisterReceiver(mReceiver); 217 | super.onDestroy(); 218 | } 219 | 220 | private void initUI() { 221 | mTextConnectionStatus = (TextView) findViewById(R.id.text_connection_status); 222 | mTextProduct = (TextView) findViewById(R.id.text_product_info); 223 | mBtnOpen = (Button) findViewById(R.id.btn_open); 224 | mBtnOpen.setOnClickListener(this); 225 | mBtnOpen.setEnabled(false); 226 | mVersionTv = (TextView) findViewById(R.id.textView2); 227 | mVersionTv.setText(getResources().getString(R.string.sdk_version, DJISDKManager.getInstance().getSDKVersion())); 228 | } 229 | 230 | protected BroadcastReceiver mReceiver = new BroadcastReceiver() { 231 | 232 | @Override 233 | public void onReceive(Context context, Intent intent) { 234 | refreshSDKRelativeUI(); 235 | } 236 | }; 237 | 238 | private void refreshSDKRelativeUI() { 239 | BaseProduct mProduct = DemoApplication.getProductInstance(); 240 | 241 | if (null != mProduct && mProduct.isConnected()) { 242 | Log.v(TAG, "refreshSDK: True"); 243 | mBtnOpen.setEnabled(true); 244 | 245 | String str = mProduct instanceof Aircraft ? "DJIAircraft" : "DJIHandHeld"; 246 | mTextConnectionStatus.setText("Status: " + str + " connected"); 247 | 248 | if (null != mProduct.getModel()) { 249 | mTextProduct.setText("" + mProduct.getModel().getDisplayName()); 250 | } else { 251 | mTextProduct.setText(R.string.product_information); 252 | } 253 | 254 | } else { 255 | Log.v(TAG, "refreshSDK: False"); 256 | mBtnOpen.setEnabled(false); 257 | 258 | mTextProduct.setText(R.string.product_information); 259 | mTextConnectionStatus.setText(R.string.connection_loose); 260 | } 261 | } 262 | 263 | @Override 264 | public void onClick(View v) { 265 | if (v.getId() == R.id.btn_open) { 266 | Intent intent = new Intent(this, MainActivity.class); 267 | startActivity(intent); 268 | } 269 | } 270 | 271 | private void showToast(final String toastMsg) { 272 | runOnUiThread(new Runnable() { 273 | @Override 274 | public void run() { 275 | Toast.makeText(getApplicationContext(), toastMsg, Toast.LENGTH_LONG).show(); 276 | } 277 | }); 278 | } 279 | } 280 | -------------------------------------------------------------------------------- /ActivationAndBindingDemo/app/src/main/java/com/dji/activationDemo/DemoApplication.java: -------------------------------------------------------------------------------- 1 | package com.dji.activationDemo; 2 | 3 | import android.app.Application; 4 | import android.content.Context; 5 | import android.content.Intent; 6 | import android.os.Build; 7 | import android.os.Handler; 8 | import android.os.Looper; 9 | import androidx.core.content.ContextCompat; 10 | import android.util.Log; 11 | import android.widget.Toast; 12 | 13 | import dji.common.error.DJIError; 14 | import dji.common.error.DJISDKError; 15 | import dji.sdk.base.BaseComponent; 16 | import dji.sdk.base.BaseProduct; 17 | import dji.sdk.camera.Camera; 18 | import dji.sdk.products.Aircraft; 19 | import dji.sdk.products.HandHeld; 20 | import dji.sdk.sdkmanager.DJISDKInitEvent; 21 | import dji.sdk.sdkmanager.DJISDKManager; 22 | 23 | public class DemoApplication extends Application { 24 | public static final String FLAG_CONNECTION_CHANGE = "activationDemo_connection_change"; 25 | 26 | private static BaseProduct mProduct; 27 | public Handler mHandler; 28 | 29 | private Application instance; 30 | 31 | public void setContext(Application application) { 32 | instance = application; 33 | } 34 | 35 | @Override 36 | public Context getApplicationContext() { 37 | return instance; 38 | } 39 | 40 | public DemoApplication() { 41 | 42 | } 43 | 44 | /** 45 | * This function is used to get the instance of DJIBaseProduct. 46 | * If no product is connected, it returns null. 47 | */ 48 | public static synchronized BaseProduct getProductInstance() { 49 | if (null == mProduct) { 50 | mProduct = DJISDKManager.getInstance().getProduct(); 51 | } 52 | return mProduct; 53 | } 54 | 55 | @Override 56 | public void onCreate() { 57 | super.onCreate(); 58 | mHandler = new Handler(Looper.getMainLooper()); 59 | 60 | /** 61 | * When starting SDK services, an instance of interface DJISDKManager.DJISDKManagerCallback will be used to listen to 62 | * the SDK Registration result and the product changing. 63 | */ 64 | //Listens to the SDK registration result 65 | DJISDKManager.SDKManagerCallback mDJISDKManagerCallback = new DJISDKManager.SDKManagerCallback() { 66 | 67 | //Listens to the SDK registration result 68 | @Override 69 | public void onRegister(DJIError error) { 70 | 71 | if (error == DJISDKError.REGISTRATION_SUCCESS) { 72 | 73 | Handler handler = new Handler(Looper.getMainLooper()); 74 | handler.post(new Runnable() { 75 | @Override 76 | public void run() { 77 | Toast.makeText(getApplicationContext(), "Register Success", Toast.LENGTH_LONG).show(); 78 | } 79 | }); 80 | 81 | DJISDKManager.getInstance().startConnectionToProduct(); 82 | 83 | } else { 84 | 85 | Handler handler = new Handler(Looper.getMainLooper()); 86 | handler.post(new Runnable() { 87 | 88 | @Override 89 | public void run() { 90 | Toast.makeText(getApplicationContext(), "Register sdk fails, check network is available", Toast.LENGTH_LONG).show(); 91 | } 92 | }); 93 | 94 | } 95 | Log.e("TAG", error.toString()); 96 | } 97 | 98 | @Override 99 | public void onProductDisconnect() { 100 | Log.d("TAG", "onProductDisconnect"); 101 | notifyStatusChange(); 102 | } 103 | 104 | @Override 105 | public void onProductConnect(BaseProduct baseProduct) { 106 | Log.d("TAG", String.format("onProductConnect newProduct:%s", baseProduct)); 107 | notifyStatusChange(); 108 | 109 | } 110 | 111 | @Override 112 | public void onProductChanged(BaseProduct baseProduct) { 113 | 114 | } 115 | 116 | @Override 117 | public void onComponentChange(BaseProduct.ComponentKey componentKey, BaseComponent oldComponent, 118 | BaseComponent newComponent) { 119 | if (newComponent != null) { 120 | newComponent.setComponentListener(new BaseComponent.ComponentListener() { 121 | 122 | @Override 123 | public void onConnectivityChange(boolean isConnected) { 124 | Log.d("TAG", "onComponentConnectivityChanged: " + isConnected); 125 | notifyStatusChange(); 126 | } 127 | }); 128 | } 129 | 130 | Log.d("TAG", 131 | String.format("onComponentChange key:%s, oldComponent:%s, newComponent:%s", 132 | componentKey, 133 | oldComponent, 134 | newComponent)); 135 | 136 | } 137 | 138 | @Override 139 | public void onInitProcess(DJISDKInitEvent djisdkInitEvent, int i) { 140 | 141 | } 142 | 143 | @Override 144 | public void onDatabaseDownloadProgress(long l, long l1) { 145 | 146 | } 147 | }; 148 | //Check the permissions before registering the application for android system 6.0 above. 149 | int permissionCheck = ContextCompat.checkSelfPermission(getApplicationContext(), android.Manifest.permission.WRITE_EXTERNAL_STORAGE); 150 | int permissionCheck2 = ContextCompat.checkSelfPermission(getApplicationContext(), android.Manifest.permission.READ_PHONE_STATE); 151 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M || (permissionCheck == 0 && permissionCheck2 == 0)) { 152 | //This is used to start SDK services and initiate SDK. 153 | DJISDKManager.getInstance().registerApp(getApplicationContext(), mDJISDKManagerCallback); 154 | Toast.makeText(getApplicationContext(), "registering, pls wait...", Toast.LENGTH_LONG).show(); 155 | 156 | } else { 157 | Toast.makeText(getApplicationContext(), "Please check if the permission is granted.", Toast.LENGTH_LONG).show(); 158 | } 159 | 160 | } 161 | 162 | private void notifyStatusChange() { 163 | mHandler.removeCallbacks(updateRunnable); 164 | mHandler.postDelayed(updateRunnable, 500); 165 | } 166 | 167 | private Runnable updateRunnable = new Runnable() { 168 | 169 | @Override 170 | public void run() { 171 | Intent intent = new Intent(FLAG_CONNECTION_CHANGE); 172 | getApplicationContext().sendBroadcast(intent); 173 | } 174 | }; 175 | } 176 | -------------------------------------------------------------------------------- /ActivationAndBindingDemo/app/src/main/java/com/dji/activationDemo/MApplication.java: -------------------------------------------------------------------------------- 1 | package com.dji.activationDemo; 2 | 3 | import android.app.Application; 4 | import android.content.Context; 5 | 6 | import com.secneo.sdk.Helper; 7 | 8 | public class MApplication extends Application { 9 | private DemoApplication demoApplication; 10 | 11 | @Override 12 | protected void attachBaseContext(Context paramContext) { 13 | super.attachBaseContext(paramContext); 14 | Helper.install(MApplication.this); 15 | if (demoApplication == null) { 16 | demoApplication = new DemoApplication(); 17 | demoApplication.setContext(this); 18 | } 19 | } 20 | 21 | @Override 22 | public void onCreate() { 23 | super.onCreate(); 24 | demoApplication.onCreate(); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /ActivationAndBindingDemo/app/src/main/java/com/dji/activationDemo/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.dji.activationDemo; 2 | 3 | import androidx.appcompat.app.AppCompatActivity; 4 | import android.os.Bundle; 5 | import android.util.Log; 6 | import android.view.View; 7 | import android.widget.Button; 8 | import android.widget.TextView; 9 | import android.widget.Toast; 10 | 11 | import dji.common.error.DJIError; 12 | import dji.common.realname.AircraftBindingState; 13 | import dji.common.realname.AppActivationState; 14 | import dji.common.useraccount.UserAccountState; 15 | import dji.common.util.CommonCallbacks; 16 | import dji.sdk.realname.AppActivationManager; 17 | import dji.sdk.sdkmanager.DJISDKManager; 18 | import dji.sdk.useraccount.UserAccountManager; 19 | 20 | public class MainActivity extends AppCompatActivity implements View.OnClickListener { 21 | 22 | private static final String TAG = MainActivity.class.getName(); 23 | protected Button loginBtn; 24 | protected Button logoutBtn; 25 | protected TextView bindingStateTV; 26 | protected TextView appActivationStateTV; 27 | private AppActivationManager appActivationManager; 28 | private AppActivationState.AppActivationStateListener activationStateListener; 29 | private AircraftBindingState.AircraftBindingStateListener bindingStateListener; 30 | 31 | @Override 32 | protected void onCreate(Bundle savedInstanceState) { 33 | super.onCreate(savedInstanceState); 34 | setContentView(R.layout.activity_main); 35 | initUI(); 36 | initData(); 37 | } 38 | 39 | @Override 40 | public void onResume() { 41 | Log.e(TAG, "onResume"); 42 | setUpListener(); 43 | super.onResume(); 44 | } 45 | 46 | @Override 47 | public void onPause() { 48 | Log.e(TAG, "onPause"); 49 | super.onPause(); 50 | } 51 | 52 | @Override 53 | public void onStop() { 54 | Log.e(TAG, "onStop"); 55 | super.onStop(); 56 | } 57 | 58 | public void onReturn(View view){ 59 | Log.e(TAG, "onReturn"); 60 | this.finish(); 61 | } 62 | 63 | @Override 64 | protected void onDestroy() { 65 | Log.e(TAG, "onDestroy"); 66 | tearDownListener(); 67 | super.onDestroy(); 68 | } 69 | 70 | private void initUI(){ 71 | bindingStateTV = (TextView) findViewById(R.id.tv_binding_state_info); 72 | appActivationStateTV = (TextView) findViewById(R.id.tv_activation_state_info); 73 | loginBtn = (Button) findViewById(R.id.btn_login); 74 | logoutBtn = (Button) findViewById(R.id.btn_logout); 75 | loginBtn.setOnClickListener(this); 76 | logoutBtn.setOnClickListener(this); 77 | } 78 | 79 | private void initData(){ 80 | setUpListener(); 81 | appActivationManager = DJISDKManager.getInstance().getAppActivationManager(); 82 | if (appActivationManager != null) { 83 | appActivationManager.addAppActivationStateListener(activationStateListener); 84 | appActivationManager.addAircraftBindingStateListener(bindingStateListener); 85 | MainActivity.this.runOnUiThread(new Runnable() { 86 | @Override 87 | public void run() { 88 | appActivationStateTV.setText("" + appActivationManager.getAppActivationState()); 89 | bindingStateTV.setText("" + appActivationManager.getAircraftBindingState()); 90 | } 91 | }); 92 | } 93 | } 94 | 95 | private void setUpListener() { 96 | // Example of Listener 97 | activationStateListener = new AppActivationState.AppActivationStateListener() { 98 | @Override 99 | public void onUpdate(final AppActivationState appActivationState) { 100 | MainActivity.this.runOnUiThread(new Runnable() { 101 | @Override 102 | public void run() { 103 | appActivationStateTV.setText("" + appActivationState); 104 | } 105 | }); 106 | } 107 | }; 108 | 109 | bindingStateListener = bindingState -> MainActivity.this.runOnUiThread(new Runnable() { 110 | @Override 111 | public void run() { 112 | bindingStateTV.setText("" + bindingState); 113 | } 114 | }); 115 | } 116 | 117 | private void tearDownListener() { 118 | if (activationStateListener != null) { 119 | appActivationManager.removeAppActivationStateListener(activationStateListener); 120 | MainActivity.this.runOnUiThread(new Runnable() { 121 | @Override 122 | public void run() { 123 | appActivationStateTV.setText("Unknown"); 124 | } 125 | }); 126 | } 127 | if (bindingStateListener !=null) { 128 | appActivationManager.removeAircraftBindingStateListener(bindingStateListener); 129 | MainActivity.this.runOnUiThread(new Runnable() { 130 | @Override 131 | public void run() { 132 | bindingStateTV.setText("Unknown"); 133 | } 134 | }); 135 | } 136 | } 137 | 138 | public void showToast(final String msg) { 139 | runOnUiThread(new Runnable() { 140 | public void run() { 141 | Toast.makeText(MainActivity.this, msg, Toast.LENGTH_SHORT).show(); 142 | } 143 | }); 144 | } 145 | 146 | @Override 147 | public void onClick(View v) { 148 | switch (v.getId()) { 149 | case R.id.btn_login: 150 | loginAccount(); 151 | break; 152 | case R.id.btn_logout: 153 | logoutAccount(); 154 | break; 155 | default: 156 | break; 157 | } 158 | } 159 | 160 | private void loginAccount(){ 161 | UserAccountManager.getInstance().logIntoDJIUserAccount(this, 162 | new CommonCallbacks.CompletionCallbackWith() { 163 | @Override 164 | public void onSuccess(final UserAccountState userAccountState) { 165 | showToast("Login Success"); 166 | } 167 | @Override 168 | public void onFailure(DJIError error) { 169 | showToast("Login Error:" 170 | + error.getDescription()); 171 | } 172 | }); 173 | } 174 | 175 | private void logoutAccount(){ 176 | UserAccountManager.getInstance().logoutOfDJIUserAccount(error -> { 177 | if (null == error) { 178 | showToast("Logout Success"); 179 | } else { 180 | showToast("Logout Error:" 181 | + error.getDescription()); 182 | } 183 | }); 184 | } 185 | } 186 | -------------------------------------------------------------------------------- /ActivationAndBindingDemo/app/src/main/res/drawable/round_btn.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ActivationAndBindingDemo/app/src/main/res/drawable/round_btn_disable.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | -------------------------------------------------------------------------------- /ActivationAndBindingDemo/app/src/main/res/drawable/round_btn_normal.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | -------------------------------------------------------------------------------- /ActivationAndBindingDemo/app/src/main/res/drawable/round_btn_pressed.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | -------------------------------------------------------------------------------- /ActivationAndBindingDemo/app/src/main/res/layout/activity_connection.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 20 | 21 | 33 | 34 |