You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Android原生Java中挂起Flutter Method Channel回调返回串口数据

Flutter与Android串口通信:MethodChannel无法返回串口数据的问题解决

你的核心问题是串口通信是异步操作,但你在调用串口写入方法后立刻检查返回值,这时候串口数据还没到达,自然拿不到有效结果。以下是具体分析和解决方案:

问题根源

  • select()调用后,主线程会马上执行if (!response.isEmpty()) result.success(response),但onNewData是串口数据到达时才触发的回调,此时response还是初始空值,所以判断条件不成立,result.success不会执行。
  • 直接删除判断条件的话,主线程会立刻返回空的response,完全等不到串口返回的数据。

解决方案

1. 保存MethodCallResult实例

把MethodChannel回调中的result保存为类变量,等串口数据到达后再调用它返回结果,而非立刻判断。

2. 切换到主线程返回结果

onNewData通常在子线程执行,Flutter要求MethodChannel的结果必须在主线程返回,所以需要用runOnUiThread切换线程。

3. 处理异常与重复请求

  • 串口写入失败时要及时返回错误,避免result一直处于等待状态。
  • 新请求到来时,取消旧的未处理请求,避免返回错误结果。

修改后的完整代码

public class MainActivity extends FlutterActivity implements SerialInputOutputManager.Listener {

    private static final String CHANNEL = "channel";

    private UsbSerialPort connectionPort;
    private MethodCallResult pendingResult; // 保存待处理的请求结果


    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
        super.configureFlutterEngine(flutterEngine);
        new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), CHANNEL)
                .setMethodCallHandler(
                        (call, result) -> {
                            // 取消之前未完成的请求
                            if (pendingResult != null) {
                                pendingResult.error("CANCELLED", "Previous request cancelled", null);
                            }
                            pendingResult = result;
                            select();
                        }
                );
    }

    @Override
    protected void onNewIntent(Intent intent) {
        if (intent.getAction().equals("android.hardware.usb.action.USB_DEVICE_ATTACHED")) {
            Toast.makeText(this, "new usb device detected!", Toast.LENGTH_SHORT).show();
        }
        super.onNewIntent(intent);
    }

    private void select() {
        try {
            connectionPort.write(...); // 你的串口写入逻辑
        } catch (IOException e) {
            // 写入失败时返回错误
            if (pendingResult != null) {
                pendingResult.error("WRITE_ERROR", "Failed to write to serial port", e.getMessage());
                pendingResult = null;
            }
        }
    }

    @Override
    public void onNewData(byte[] data) {
        String response = Utils.byteArrayToHexString(data);
        // 切换到主线程返回结果给Flutter
        runOnUiThread(() -> {
            if (pendingResult != null) {
                pendingResult.success(response);
                pendingResult = null; // 清空,避免重复调用
            }
        });
    }

    @Override
    public void onRunError(Exception e) {
        // 串口运行出错时返回错误
        runOnUiThread(() -> {
            if (pendingResult != null) {
                pendingResult.error("SERIAL_ERROR", "Serial port error", e.getMessage());
                pendingResult = null;
            }
        });
    }
}

额外注意事项

  • 确保connectionPort已经正确初始化并打开,否则会出现空指针或写入失败的情况。
  • 如果串口需要返回多段数据,可根据业务逻辑修改:比如用集合累积数据,在特定条件下再返回结果。
  • 长时间未收到串口数据时,可添加超时逻辑,主动返回超时错误,避免Flutter端一直等待。

内容的提问来源于stack exchange,提问作者Mohamadamin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 21:24:27