Flutter USB串口通信插件usb_serial_for_android的使用
Flutter USB串口通信插件usb_serial_for_android
的使用
usb_serial_for_android
是一个用于Android设备的串行库。
重要提示!
本项目与 usb_serial
非常相似,你可以使用它的文档来使用这个库。由于还有很多更改和测试需要进行,建议参考 usb_serial
的文档。
动机
在使用 usb_serial
进行开发时遇到了一些问题和错误,这些问题是由于我正在开发的一个项目的特殊需求导致的。
虽然 usb_serial
使用的是 https://github.com/felHR85/UsbSerial
,但此库使用的是 https://github.com/mik3y/usb-serial-for-android
来支持其功能。
完整示例代码
以下是一个完整的示例代码,展示了如何使用 usb_serial_for_android
插件进行USB串口通信。
import 'dart:async';
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:usb_serial_for_android/transaction.dart';
import 'package:usb_serial_for_android/usb_device.dart';
import 'package:usb_serial_for_android/usb_event.dart';
import 'package:usb_serial_for_android/usb_port.dart';
import 'package:usb_serial_for_android/usb_serial_for_android.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
[@override](/user/override)
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
UsbPort? _port;
String _status = "Idle";
List<Widget> _ports = [];
List<Widget> _serialData = [];
StreamSubscription<String>? _subscription;
Transaction<String>? _transaction;
UsbDevice? _device;
TextEditingController _textController = TextEditingController();
Future<bool> _connectTo(UsbDevice? device) async {
_serialData.clear();
if (_subscription != null) {
_subscription!.cancel();
_subscription = null;
}
if (_transaction != null) {
_transaction!.dispose();
_transaction = null;
}
if (_port != null) {
_port!.close();
_port = null;
}
if (device == null) {
_device = null;
setState(() {
_status = "Disconnected";
});
return true;
}
// 你可以在创建端口时自定义驱动程序和端口号
_port = await device.create(UsbSerial.CP21xx, 4);
if (await (_port!.open()) != true) {
setState(() {
_status = "Failed to open port";
});
return false;
}
_device = device;
await _port!.setDTR(true);
await _port!.setRTS(true);
await _port!.setPortParameters(
115200, UsbPort.DATABITS_8, UsbPort.STOPBITS_1, UsbPort.PARITY_NONE);
await _port!.connect();
_transaction = Transaction.stringTerminated(
_port!.inputStream as Stream<Uint8List>, Uint8List.fromList([13, 10]));
_subscription = _transaction!.stream.listen((String line) {
setState(() {
_serialData.add(Text(line));
if (_serialData.length > 20) {
_serialData.removeAt(0);
}
});
});
setState(() {
_status = "Connected";
});
return true;
}
void _getPorts() async {
_ports = [];
List<UsbDevice> devices = await UsbSerial.listDevices();
if (!devices.contains(_device)) {
_connectTo(null);
}
print(devices);
devices.forEach((device) {
_ports.add(ListTile(
leading: Icon(Icons.usb),
title: Text(device.productName!),
subtitle: Text(device.manufacturerName!),
trailing: ElevatedButton(
child: Text(_device == device ? "Disconnect" : "Connect"),
onPressed: () {
_connectTo(_device == device ? null : device).then((res) {
_getPorts();
});
},
)));
});
setState(() {
print(_ports);
});
}
[@override](/user/override)
void initState() {
super.initState();
UsbSerial.usbEventStream!.listen((UsbEvent event) {
_getPorts();
});
_getPorts();
}
[@override](/user/override)
void dispose() {
super.dispose();
_connectTo(null);
}
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('USB Serial Plugin example app'),
),
body: Center(
child: Column(children: <Widget>[
Text(
_ports.length > 0
? "Available Serial Ports"
: "No serial devices available",
style: Theme.of(context).textTheme.headline6),
..._ports,
Text('Status: $_status\n'),
Text('info: ${_port.toString()}\n'),
ListTile(
title: TextField(
controller: _textController,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Text To Send',
),
),
trailing: ElevatedButton(
child: Text("Send"),
onPressed: _port == null
? null
: () async {
if (_port == null) {
return;
}
String data = _textController.text + "\r\n";
await _port!.write(Uint8List.fromList(data.codeUnits));
_textController.text = "";
},
),
),
Text("Result Data", style: Theme.of(context).textTheme.headline6),
..._serialData,
])),
));
}
}
更多关于Flutter USB串口通信插件usb_serial_for_android的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter USB串口通信插件usb_serial_for_android的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是如何在Flutter应用中使用usb_serial_for_android
插件来实现USB串口通信的示例代码。这个插件主要用于Android平台,如果你还需要iOS支持,可能需要查看其他插件或解决方案。
首先,确保你的Flutter项目中已经添加了usb_serial_for_android
依赖。在pubspec.yaml
文件中添加以下依赖:
dependencies:
flutter:
sdk: flutter
usb_serial_for_android: ^x.x.x # 请替换为最新版本号
然后运行flutter pub get
来安装依赖。
接下来是示例代码,展示如何使用usb_serial_for_android
插件进行USB串口通信。
主文件:main.dart
import 'package:flutter/material.dart';
import 'package:usb_serial_for_android/usb_serial_for_android.dart';
import 'package:usb_serial_for_android/usb_device.dart';
import 'package:usb_serial_for_android/usb_port.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
UsbSerial? _usbSerial;
UsbDevice? _usbDevice;
UsbPort? _usbPort;
bool _isOpen = false;
@override
void initState() {
super.initState();
initUsb();
}
@override
void dispose() {
_usbSerial?.close();
super.dispose();
}
Future<void> initUsb() async {
UsbSerialManager manager = UsbSerialManager();
List<UsbDevice> devices = await manager.getDevices();
if (devices.isNotEmpty) {
setState(() {
_usbDevice = devices.first;
});
_usbSerial = await UsbSerial.fromUsbDevice(_usbDevice!);
List<UsbPort> ports = await _usbSerial!.getPorts();
if (ports.isNotEmpty) {
setState(() {
_usbPort = ports.first;
});
}
}
}
Future<void> openPort() async {
if (_usbSerial == null || _usbPort == null) return;
try {
await _usbSerial!.openPort(_usbPort!, 9600, UsbSerial.DATABITS_8, UsbSerial.STOPBITS_1, UsbSerial.PARITY_NONE);
setState(() {
_isOpen = true;
});
} catch (e) {
print(e);
}
}
Future<void> closePort() async {
if (_usbSerial != null) {
await _usbSerial!.closePort();
setState(() {
_isOpen = false;
});
}
}
Future<void> sendData(String data) async {
if (_usbSerial != null && _isOpen) {
await _usbSerial!.write(data.codeUnits);
}
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('USB Serial Communication'),
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
children: [
if (_usbDevice != null)
Text('Connected Device: ${_usbDevice!.deviceName}'),
ElevatedButton(
onPressed: _isOpen ? closePort : openPort,
child: Text(_isOpen ? 'Close Port' : 'Open Port'),
),
SizedBox(height: 16),
ElevatedButton(
onPressed: () async {
String data = 'Hello USB!';
await sendData(data);
print('Sent: $data');
},
child: Text('Send Data'),
),
],
),
),
),
);
}
}
注意事项:
- 权限:在
AndroidManifest.xml
文件中添加必要的USB权限。
<uses-feature android:name="android.hardware.usb.host" />
<uses-permission android:name="android.permission.USB_PERMISSION" />
-
运行时权限请求:对于Android 6.0及以上版本,你需要在运行时请求USB权限。你可以在
MainActivity.kt
或MainActivity.java
中添加相关代码来处理权限请求。 -
调试和错误处理:确保在实际设备上进行调试,因为模拟器通常不支持USB连接。添加适当的错误处理代码,以便在出现问题时能够捕获和记录错误信息。
这个示例代码展示了如何初始化USB设备、打开/关闭串口端口以及发送数据。根据实际需求,你可能需要扩展这个示例,比如添加接收数据的处理逻辑。