title: SDK not registering (from non view constructor, not an onCreate()) - No errors
body: <p>I am making a cleaner version of a research drone android app that utilises DJI SDK/Hardware and attempting to structure the app more appropriately such that it can be expanded later. The application allows user selection of hardware (currently mock/test, DJI and ToDo) from a config pop up in the main display (class UserInterface extends AppCompatActivity). This is to allow the app to be used without registering or check perms when it is not being used for DJI. Previously I registered the DJI SDK when the app first opens, but it was my first real app and was a mess to follow its flow and didn't manage screen real estate very well.</p>
  <p>When the DJI option is actioned from the pop up &quot;config&quot; window on the main interface from UI class, the UI class saves the config to a SettingsManager instance and calls the EventsManager instance with method runSettings(). The method actions the relevant SDK by try/catch{new DJI SDK class} and passes both the instances of EventsManager and UI.</p>
  <p>The difference of this major version compared to my first version (which functions correctly) is the API key (changed package name, so new key), I am not doing the SDK registration in the first main activity and the SDK registration is not a viewable class, it only forwards strings to run on UI thread for showToast method in the UI class.</p>
  <ul>
  <li>App does not return any errors.</li>
  <li>showToast for messages in the DJI SDK class appear on the display but nothing inside the
  SDKManagerCallback occurs.</li>
  <li>Unsure of constructor in a class with extends AppCompatActivity, context methods seem unavailable when
  tried with different class extensions.</li>
  <li>I have tried creating two DJI developer keys, no difference.</li>
  <li>Unsure of DJI class listing in Manifest as it is not an activity started by an intent with bundle but
  does require context.</li>
  <li>DJI SDK class is extracted from DJISDKDemo (I am fairly new to android app development, not sure I
  could write my own version from the limited explanation on DJI dev site).</li>
  </ul>
  <p>Thank you greatly for your help and any other tips appreciated.</p>
  <p>The SDKRegistration class:</p>
  <p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
  <div class="snippet-code">
  <pre class="snippet-code-js lang-js prettyprint-override"><code>package com.research.droneapp; // mock package name for SO
  
  import android.Manifest;
  import android.content.Intent;
  import android.content.pm.PackageManager;
  import android.os.AsyncTask;
  import android.os.Build;
  import android.os.Handler;
  import android.os.Looper;
  import android.util.Log;
  
  import androidx.annotation.NonNull;
  import androidx.appcompat.app.AppCompatActivity;
  import androidx.core.app.ActivityCompat;
  import androidx.core.content.ContextCompat;
  
  import java.util.ArrayList;
  import java.util.List;
  import java.util.concurrent.atomic.AtomicBoolean;
  
  import dji.common.error.DJIError;
  import dji.common.error.DJISDKError;
  import dji.sdk.base.BaseComponent;
  import dji.sdk.base.BaseProduct;
  import dji.sdk.sdkmanager.DJISDKInitEvent;
  import dji.sdk.sdkmanager.DJISDKManager;
  
  public class SoftwareDevelopmentKitDJI extends AppCompatActivity {
      private static final String TAG = "SoftwareDevelopmentKit";
  
      public UserInterface userInterface;
      public EventsManager eventsManager;
  
      public static final String FLAG_CONNECTION_CHANGE = "dji_sdk_connection_change";
      private static BaseProduct mProduct;
      private Handler mHandler;
  
      public boolean isConnected = false; // Variable for start up flag
  
      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&lt;String&gt; missingPermission = new ArrayList&lt;&gt;();
      private AtomicBoolean isRegistrationInProgress = new AtomicBoolean(false);
      private static final int REQUEST_PERMISSION_CODE = 12345;
  
      public SoftwareDevelopmentKitDJI(UserInterface userInterface, EventsManager eventsManager) {
          Log.d(TAG, "SoftwareDevelopmentKitDJI");
          this.userInterface = userInterface;
          this.eventsManager = eventsManager;
  
          // Permission checked true actions SDK registration
          if (Build.VERSION.SDK_INT &gt;= Build.VERSION_CODES.M) {
              checkAndRequestPermissions();
          }
  
          // Handle DJI SDK hardware changes in background thread??
          // ToDo: Receive hardware changes in EventsManager
          mHandler = new Handler(Looper.getMainLooper());
      }
  
      /**
       * Checks if there is any missing permissions, and
       * requests runtime permission if needed.
       */
      private void checkAndRequestPermissions() {
          Log.d(TAG, "checkAndRequestPermissions: S");
          // Check for permissions
          for (String eachPermission : REQUIRED_PERMISSION_LIST) {
              if (ContextCompat.checkSelfPermission(userInterface, eachPermission) !=
                      PackageManager.PERMISSION_GRANTED) {
                  missingPermission.add(eachPermission);
              }
          }
          // Request for missing permissions
          if (missingPermission.isEmpty()) {
              Log.d(TAG, "notMissingPerms");
              startSDKRegistration();
          } else if (Build.VERSION.SDK_INT &gt;= Build.VERSION_CODES.M) {
              Log.d(TAG, "missingPerms");
              passToastToUI("Need permissions!");
              ActivityCompat.requestPermissions(userInterface,
                      missingPermission.toArray(new String[missingPermission.size()]),
                      REQUEST_PERMISSION_CODE);
          }
          Log.d(TAG, "checkAndRequestPermissions: E");
      }
  
      /**
       * 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 &gt;= 0; i--) {
                  if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
                      missingPermission.remove(permissions[i]);
                  }
              }
          }
          // If no missing permission, start SDK registration
          if (missingPermission.isEmpty()) {
              startSDKRegistration();
          } else {
              passToastToUI("Missing permissions!!!");
          }
      }
  
      private void startSDKRegistration() {
          Log.d(TAG, "startSDKRegistration: S");
          if (isRegistrationInProgress.compareAndSet(false, true)) {
              AsyncTask.execute(new Runnable() {
                  @Override
                  public void run() {
                      passToastToUI("registering, pls wait...");
                      Log.d(TAG, "startSDKRegistration: run");
  
                      // ToDO: Investigate why SDKManagerCallback's don't occur
                      //  (is getApplicationContext() correct?)
                      DJISDKManager.getInstance().registerApp(getApplicationContext(),
                              new DJISDKManager.SDKManagerCallback() {
                          @Override
                          public void onRegister(DJIError djiError) {
                              Log.d(TAG, "onRegister: S");
                              if (djiError == DJISDKError.REGISTRATION_SUCCESS) {
                                  passToastToUI("Register Success");
                                  DJISDKManager.getInstance().startConnectionToProduct();
                              }
                              else {
                                  passToastToUI("Register sdk failed!");
                              }
                              Log.v(TAG, djiError.getDescription());
                              Log.d(TAG, "onRegister: E");
                          }
                          @Override
                          public void onProductDisconnect() {
                              Log.d(TAG, "onProductDisconnect");
                              passToastToUI("Product Disconnected");
                              notifyStatusChange();
                              isConnected = false;        // Set hardware connection flag
                          }
                          @Override
                          public void onProductConnect(BaseProduct baseProduct) {
                              Log.d(TAG, String.format("onProductConnect newProduct:%s", baseProduct));
                              passToastToUI("Product Connected");
                              notifyStatusChange();
                              isConnected = true;         // Set hardware connection flag
                          }
                          @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));
                          }
                          @Override
                          public void onInitProcess(DJISDKInitEvent djisdkInitEvent, int i) {
                              Log.d(TAG, "startSDKRegistration: onInitProcess");
                          }
                          @Override
                          public void onDatabaseDownloadProgress(long l, long l1) {
                              Log.d(TAG, "startSDKRegistration: onDatabaseDownloadProgress");
                          }
                      });
                  }
              });
          }
          Log.d(TAG, "startSDKRegistration: E");
      }
  
      private void notifyStatusChange() {
          mHandler.removeCallbacks(updateRunnable);
          mHandler.postDelayed(updateRunnable, 500);
      }
  
      private Runnable updateRunnable = () -&gt; {
          Intent intent = new Intent(FLAG_CONNECTION_CHANGE);
          sendBroadcast(intent);
      };
  
      private void passToastToUI(String toastMsg) {
          runOnUiThread(() -&gt; {
              userInterface.showToast(toastMsg);
          });
      }
  }</code></pre>
  <pre class="snippet-code-html lang-html prettyprint-override"><code>&lt;?xml version="1.0" encoding="utf-8"?&gt;
  &lt;manifest xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:tools="http://schemas.android.com/tools"
      package="com.research.droneapp"&gt; &lt;!-- mock package name for SO --&gt;
  
      &lt;!-- Permissions and features --&gt;
      &lt;uses-permission android:name="android.permission.BLUETOOTH" /&gt;
      &lt;uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /&gt;
      &lt;uses-permission android:name="android.permission.VIBRATE" /&gt;
      &lt;uses-permission android:name="android.permission.INTERNET" /&gt;
      &lt;uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /&gt;
      &lt;uses-permission android:name="android.permission.WAKE_LOCK" /&gt;
      &lt;uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /&gt;
      &lt;uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /&gt;
      &lt;uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /&gt;
      &lt;uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /&gt;
      &lt;uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"
          tools:ignore="ProtectedPermissions" /&gt;
      &lt;uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /&gt;
      &lt;uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /&gt;
      &lt;uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /&gt;
      &lt;uses-permission android:name="android.permission.READ_PHONE_STATE" /&gt;
  
      &lt;uses-feature android:name="android.hardware.camera" /&gt;
      &lt;uses-feature android:name="android.hardware.camera.autofocus" /&gt;
      &lt;uses-feature
          android:name="android.hardware.usb.host"
          android:required="false" /&gt;
      &lt;uses-feature
          android:name="android.hardware.usb.accessory"
          android:required="true" /&gt;
  
      &lt;!-- App Activity Process --&gt;
      &lt;application
          android:name="com.research.droneapp.MApplication"
          android:allowBackup="true"
          android:icon="@mipmap/hmu_icon"
          android:label="@string/app_name"
          android:roundIcon="@mipmap/hmu_icon_round"
          android:supportsRtl="true"
          android:theme="@style/Theme.AppCompat.NoActionBar"&gt;
  
          &lt;!-- Main Display --&gt;
          &lt;activity android:name="com.research.droneapp.UserInterface" /&gt;
  
          &lt;!-- DJI SDK --&gt;
          &lt;uses-library android:name="com.android.future.usb.accessory" /&gt;
          &lt;meta-data
              android:name="com.dji.sdk.API_KEY"
              android:value="*************" /&gt; &lt;!-- removed for SO --&gt;
  
          &lt;activity
              android:name="dji.sdk.sdkmanager.DJIAoaControllerActivity"
              android:theme="@android:style/Theme.Translucent"&gt;
              &lt;intent-filter&gt;
                  &lt;action android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED" /&gt;
              &lt;/intent-filter&gt;
              &lt;meta-data
                  android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED"
                  android:resource="@xml/accessory_filter" /&gt;
          &lt;/activity&gt;
  
          &lt;service android:name="dji.sdk.sdkmanager.DJIGlobalService"&gt;
          &lt;/service&gt;
  
          &lt;activity android:name="com.research.droneapp.SoftwareDevelopmentKitDJI" /&gt;
  
          &lt;!-- Splash Screen at Launch --&gt;
          &lt;activity android:name="com.research.droneapp.Splash" &gt;
              &lt;intent-filter&gt;
                  &lt;action android:name="android.intent.action.MAIN" /&gt;
                  &lt;category android:name="android.intent.category.LAUNCHER" /&gt;
              &lt;/intent-filter&gt;
          &lt;/activity&gt;
  
      &lt;/application&gt;
  
  &lt;/manifest&gt;</code></pre>
  </div>
  </div>
  </p>
  <p>The method that starts the SDK class:</p>
  <p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
  <div class="snippet-code">
  <pre class="snippet-code-js lang-js prettyprint-override"><code>    /**
       * Settings changes to start relevant classes
       */
      public void runSettings() {
          Log.d(TAG, "runSettings: S");
                                                              // Get hardware selection from settings
          int hardwarePosition = settingsManager.getHardwareInt();
  
          /*ToDo: Set Test Environment*/
          if (hardwarePosition == 0) {                        // Operate settings for test environment
              Log.d(TAG, "runSettings: hardPos Test");
              userInterface.showToast("runSetting: TEST");
          }
          else if (hardwarePosition == 1) {                   // Operate settings for DJI
              Log.d(TAG, "runSettings: hardPos MavP2");
              try {
                  this.softwareDevelopmentKitDJI = new SoftwareDevelopmentKitDJI(
                          userInterface, this);
                  Log.d(TAG, "runSettings: DJI Launched");
                  userInterface.showToast("runSetting: DJI");
              } catch (Exception e) {
                  Log.d(TAG, "runSettings: DJI Error: "+ e.toString());
                  userInterface.showToast("runSetting: Error");
              }
          }                                                   // Operate settings for...?
          else if (hardwarePosition == 2) { /*ToDo*/
              Log.d(TAG, "runSettings: hardPos ToDo");
              userInterface.showToast("runSetting: ToDo");
          }
          else {                                              // Unknown hardware
              Log.d(TAG, "runSettings: Error");
              userInterface.showToast("runSetting:Error");
          }
          Log.d(TAG, "runSettings: E");
      }</code></pre>
  </div>
  </div>
  </p>
  <p>The config window click listener for action changes button, within the method of UI class for config pop up window:</p>
  <p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
  <div class="snippet-code">
  <pre class="snippet-code-js lang-js prettyprint-override"><code>// Action changes
          Button btnAction = popupView.findViewById(R.id.btnAction);
          btnAction.setOnClickListener(new View.OnClickListener() {
              @Override
              public void onClick(View v) {
                  Log.d(TAG, "displayConfigOverlay: onClick -&gt; configAction");
                  
                  // Update hardware setting
                  String hardware =
                          (btnTest.isChecked())?settingsManager.HARDWARE_OPTIONS[0]:
                          (btnMavP2.isChecked())?settingsManager.HARDWARE_OPTIONS[1]:
                          (btnToDo.isChecked())?settingsManager.HARDWARE_OPTIONS[2]:
                                  "NoSelection!";
                  settingsManager.setHardware(hardware);
  
                  // Update port number
                  String port = serverPortEdit.getText().toString();
                  settingsManager.setServerPort(port);
  
                  // Update WSS launch setting
                  boolean autoLunchWSS = swAutoWSS.isChecked();
                  settingsManager.setAutoLaunchWSS(autoLunchWSS);
  
                  // Display to user
                  showToast("Hardware: " + hardware + "\nPort: " + port + "\nAutoWSS: " +
                          autoLunchWSS);
  
                  // Push settings
                  eventsManager.runSettings();
  
                  // Close config pop up
                  popupConfig.dismiss();
              }
          });</code></pre>
  </div>
  </div>
  </p>
  <p>Apologises for the lack of and mixed commenting styles. Again any tips appreciated, still new to android and java.</p>