如何在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
相关产品推荐
相关产品推荐

