Context
I'm building a Flutter Plugin above the DJK SDK. For that, I have to implement the communication with the aircraft on the native side, and I'm doing it with Java. I'm also doing it only for Android.
One of the methods of the API is boolean connectToAircraft()
, which must return if the connection with the aircraft succeeded.
Expected/current behavior
After I call connectToAircraft()
- which invokes the DJISDKManager.getInstance().startConnectionToProduct()
method, I expected to be able to use anything related to aircraft immediately, but this doesn't happen. I have to wait a few seconds before I can retrieve data from the aircraft.
Some code
public class UavApi implements IUavApi, DJISDKManager.SDKManagerCallback {
...
private final CountDownLatch onConnectToUavFinishedSignal = new CountDownLatch(1);
...
public boolean connectToUav() throws InterruptedException {
Logger.v("connectToUav()");
DJISDKManager.getInstance().startConnectionToProduct();
synchronized (onConnectToUavFinishedSignal) {
onConnectToUavFinishedSignal.await();
}
return DJISDKManager.getInstance().getProduct() instanceof Aircraft;
}
...
@Override
public void onProductConnect(@Nullable final BaseProduct baseProduct) {
Logger.v(MessageFormat.format("onProductConnect(product: {0})", baseProduct));
if (baseProduct != null) {
handleProductConnected(baseProduct);
}
}
@Override
public void onProductChanged(@Nullable final BaseProduct baseProduct) {
Logger.v(MessageFormat.format("onProductChanged(product: {0})", baseProduct));
if (baseProduct != null) {
handleProductConnected(baseProduct);
}
}
...
private void handleProductConnected(@NonNull final BaseProduct baseProduct) {
Logger.d(MessageFormat.format("Is null? {0}", baseProduct == null ? "Yes" : "No"));
Logger.d(MessageFormat.format("Type: {0}", baseProduct.getClass().getSimpleName()));
onConnectToUavFinishedSignal.countDown();
}
...
}
Problem
The code above is what I tried to do, but it's not working and guess it's because I'm misunderstanding the use of the onProductChange()
and onProductConnect()
methods.
The DJISDKManager.getInstance().getProduct()
is always returning null.
OBS: It's always returning null immediately after the onConnectToUavFinishedSignal.await()
call finishes. After a few seconds, I get a valid instance of the aircraft.
Something I've also noticed is that sometimes the onProductChange()
is called with some value that the log outputs as Unknwoun and None. What are those and how can I test for them? Like if (baseProduct == ???) doSomething()
Environment
- Android 9
- MSDK 4.13.1
- Phantom 4 Pro
Difference
According to the SDK Docs
onProductChanged
is primarily used to detect when the connection status changes from only remote controller connected to a full connection between the aircraft and the SDK running on your device.Keep in mind that when the aircraft is disconnected, this method will be called with an instance of an aircraft, but this instance will come with property
isConnected
asfalse
. If you print the aircraft object to the console you will notice that ifisConnected
istrue
, it will print the aircraft name, otherwise, it will print "None".As long for the
onProductConnect
, it will be called always afterDJISDKManager.getInstance().registerApp()
succeeded or after you manually connect to the aircraft with success usingDJISDKManager.getInstance().startConnectionToProduct()
. In my tests, even though the app registration succeeds, the method will returnfalse
, so you might need to check if theSDKManagerCallback::onRegister
results inDJISDKError.REGISTRATION_SUCCESS
.Solution
You need to listen to component change events. Unfortunately just because the product is connected it does not mean that the individual components, such as the flight controller, camera etc are connected. You will need to implement
onComponentChange
and add a listener to detect when a component is connected. These don't always connect in the same order and may start to connect before or after the product is connected.