问题
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
回答1:
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
as false
. If you print the aircraft object to the console you will notice that if isConnected
is true
, it will print the aircraft name, otherwise, it will print "None".
As long for the onProductConnect
, it will be called always after DJISDKManager.getInstance().registerApp()
succeeded or after you manually connect to the aircraft with success using DJISDKManager.getInstance().startConnectionToProduct()
. In my tests, even though the app registration succeeds, the method will return false
, so you might need to check if the SDKManagerCallback::onRegister
results in DJISDKError.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.
@Override
public void onComponentChange(
BaseProduct.ComponentKey componentKey,
BaseComponent oldBaseComponent,
BaseComponent newBaseComponent
) {
newBaseComponent.setComponentListener(isConnected -> {
// check if component connected and access data
if (isConnected) {
if(componentKey == ComponentKey.FLIGHT_CONTROLLER) {
// DJISDKManager.getInstance().getProduct() should no longer be null
DJISDKManager.getInstance().getProduct().getModel();
}
}
})
}
来源:https://stackoverflow.com/questions/64354240/difference-between-dji-onproductchange-and-onproductconnect