In mavsdkServer.run(), calling initNative
returns a negative handle, and after entering runNative
, there is no response. I don’t know what to do??
Currently, the package seems normal:
- The
build
directory contains the arm64-v8a
package.
- The result of
adb shell getprop ro.product.cpu.abi
is arm64-v8a
.
The code as follows:
private void startMavsdkConnection() {
MavsdkEventQueue.executor().execute(() → {
int mavsdkServerPort = mavsdkServer.run();
drone = new System(BACKEND_IP_ADDRESS, mavsdkServerPort);
disposables.add(drone.getTelemetry().getFlightMode()...);
disposables.add(drone.getTelemetry().getArmed()...);
disposables.add(drone.getTelemetry().getPosition()...);
isMavsdkServerRunning = true;
runOnUiThread(() ->
buttonRunDestroyMavsdkServer.setText(R.string.destroy_mavsdk_server));
});
}
UsbSerialHandler as follows:
which runs OK
package io.mavsdk.androidclient;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbManager;
import android.os.Handler;
import android.os.Looper;
import com.hoho.android.usbserial.driver.UsbSerialDriver;
import com.hoho.android.usbserial.driver.UsbSerialPort;
import com.hoho.android.usbserial.driver.UsbSerialProber;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicBoolean;
public class UsbSerialHandler {
private static final Logger logger = LoggerFactory.getLogger(UsbSerialHandler.class);
private static final String ACTION_USB_PERMISSION = “io.mavsdk.androidclient.USB_PERMISSION”;
private static final int WRITE_WAIT_MILLIS = 2000;
private static final int READ_BUFFER_SIZE = 1024;
private static final int UDP_PORT = 14550; // MAVLink standard port
private final Context context;
private final UsbManager usbManager;
private final ExecutorService executor = Executors.newSingleThreadExecutor();
private final Handler mainHandler = new Handler(Looper.getMainLooper());
private UsbSerialPort serialPort;
private DatagramSocket udpSocket;
private final AtomicBoolean running = new AtomicBoolean(false);
private UsbConnectionCallback callback;
public interface UsbConnectionCallback {
void onConnectionResult(boolean success);
}
public UsbSerialHandler(Context context) {
this.context = context;
this.usbManager = (UsbManager) context.getSystemService(Context.USB_SERVICE);
setupUsbPermissionReceiver();
}
private final BroadcastReceiver usbPermissionReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (ACTION_USB_PERMISSION.equals(intent.getAction())) {
synchronized (this) {
UsbDevice device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
if (device != null) {
connectToDevice(device);
}
} else {
logger.error("USB Permission denied");
notifyCallback(false);
}
}
}
}
};
private void setupUsbPermissionReceiver() {
IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
context.registerReceiver(usbPermissionReceiver, filter);
}
public void connect(int baudRate, UsbConnectionCallback callback) {
this.callback = callback;
List<UsbSerialDriver> availableDrivers = UsbSerialProber.getDefaultProber().findAllDrivers(usbManager);
if (availableDrivers.isEmpty()) {
logger.error("No USB serial devices found");
notifyCallback(false);
return;
}
UsbSerialDriver driver = availableDrivers.get(0);
UsbDevice device = driver.getDevice();
if (usbManager.hasPermission(device)) {
connectToDevice(device);
} else {
requestUsbPermission(device);
}
}
private void requestUsbPermission(UsbDevice device) {
PendingIntent permissionIntent = PendingIntent.getBroadcast(
context, 0, new Intent(ACTION_USB_PERMISSION), PendingIntent.FLAG_IMMUTABLE);
usbManager.requestPermission(device, permissionIntent);
}
private void connectToDevice(UsbDevice device) {
executor.execute(() -> {
try {
List<UsbSerialDriver> availableDrivers = UsbSerialProber.getDefaultProber().findAllDrivers(usbManager);
UsbSerialDriver driver = availableDrivers.get(0);
UsbDeviceConnection connection = usbManager.openDevice(device);
if (connection == null) {
logger.error("Failed to open device");
notifyCallback(false);
return;
}
serialPort = driver.getPorts().get(0);
serialPort.open(connection);
serialPort.setParameters(57600, 8, UsbSerialPort.STOPBITS_1, UsbSerialPort.PARITY_NONE);
// Setup UDP socket
udpSocket = new DatagramSocket();
running.set(true);
// Start read/write threads
startUsbReadThread();
notifyCallback(true);
} catch (Exception e) {
logger.error("Error connecting to USB device", e);
notifyCallback(false);
}
});
}
private void startUsbReadThread() {
executor.execute(() -> {
byte[] buffer = new byte[READ_BUFFER_SIZE];
while (running.get()) {
try {
int len = serialPort.read(buffer, WRITE_WAIT_MILLIS);
if (len > 0) {
// Forward to UDP
DatagramPacket packet = new DatagramPacket(
buffer, len,
InetAddress.getLocalHost(), UDP_PORT
);
udpSocket.send(packet);
}
} catch (IOException e) {
if (running.get()) {
logger.error("Error reading from USB", e);
}
}
}
});
}
private void notifyCallback(boolean success) {
mainHandler.post(() -> {
if (callback != null) {
callback.onConnectionResult(success);
}
});
}
public void disconnect() {
running.set(false);
executor.execute(() -> {
try {
if (serialPort != null) {
serialPort.close();
serialPort = null;
}
if (udpSocket != null) {
udpSocket.close();
udpSocket = null;
}
} catch (IOException e) {
logger.error("Error closing USB connection", e);
}
});
}
public boolean isConnected() {
return serialPort != null && running.get();
}
public void onDestroy() {
disconnect();
try {
context.unregisterReceiver(usbPermissionReceiver);
} catch (Exception e) {
// Ignore if receiver is not registered
}
executor.shutdown();
}
}