refactor(android): 重构Android端实现使用官方SDK替代反射调用
- 移除反射机制,直接集成CH934XLib.jar官方SDK - 添加CH934XManager初始化逻辑并处理Application上下文兼容性 - 实现设备枚举、串口打开关闭等核心功能的直接调用 - 集成IDataCallback和IModemStatus回调处理 - 更新异常回调机制,支持原生层主动推送异常事件 - 优化设备连接状态管理和USB权限处理 - 为Dart模型类添加相等性比较和哈希码实现 - 更新示例应用UI以适配新的串口索引选择逻辑
This commit is contained in:
+57
-17
@@ -43,7 +43,9 @@ class _Ch934xSerialExamplePageState extends State<Ch934xSerialExamplePage> {
|
||||
|
||||
List<Ch934xDeviceInfo> _devices = const <Ch934xDeviceInfo>[];
|
||||
Ch934xDeviceInfo? _selectedDevice;
|
||||
Ch934xSerialPortInfo? _selectedPort;
|
||||
/// 当前选中设备的可用串口索引集合(由 SDK getSerialCount 决定)。
|
||||
List<int> _availablePortIndices = const <int>[];
|
||||
int? _selectedPortIndex;
|
||||
StreamSubscription<Ch934xException>? _exceptionSubscription;
|
||||
StreamSubscription<Uint8List>? _dataSubscription;
|
||||
|
||||
@@ -87,26 +89,58 @@ class _Ch934xSerialExamplePageState extends State<Ch934xSerialExamplePage> {
|
||||
Future<void> _refreshDeviceList() async {
|
||||
try {
|
||||
final devices = await _plugin.getDeviceList();
|
||||
if (!mounted) return;
|
||||
setState(() {
|
||||
_devices = devices;
|
||||
// 清理已不再列表中的旧选项,避免 DropdownButton value 不在 items 中报错。
|
||||
final selected = _selectedDevice;
|
||||
if (selected != null && !devices.contains(selected)) {
|
||||
_selectedDevice = null;
|
||||
_availablePortIndices = const <int>[];
|
||||
_selectedPortIndex = null;
|
||||
} else if (selected != null) {
|
||||
_availablePortIndices = _resolvePortIndices(selected);
|
||||
final current = _selectedPortIndex;
|
||||
if (current == null || !_availablePortIndices.contains(current)) {
|
||||
_selectedPortIndex = _availablePortIndices.isNotEmpty
|
||||
? _availablePortIndices.first
|
||||
: null;
|
||||
}
|
||||
}
|
||||
_status = '已扫描到 ${devices.length} 台 CH934X 设备';
|
||||
});
|
||||
} on Exception catch (e) {
|
||||
if (!mounted) return;
|
||||
setState(() => _status = '设备扫描失败: $e');
|
||||
}
|
||||
}
|
||||
|
||||
/// 把设备的串口描述转换为可用索引列表。
|
||||
///
|
||||
/// 优先使用 SDK 返回的 [Ch934xSerialPortInfo.portIndex],缺
|
||||
/// 失时回退到 0..N-1,确保 UI 始终有可选项。
|
||||
List<int> _resolvePortIndices(Ch934xDeviceInfo device) {
|
||||
if (device.serialPorts.isNotEmpty) {
|
||||
return device.serialPorts.map((p) => p.portIndex).toList()..sort();
|
||||
}
|
||||
if (device.interfaceCount > 0) {
|
||||
return List<int>.generate(device.interfaceCount, (i) => i);
|
||||
}
|
||||
// 最坏情况下,允许打开串口 0;用户可通过业务调用切换。
|
||||
return const <int>[0];
|
||||
}
|
||||
|
||||
Future<void> _openPort() async {
|
||||
final device = _selectedDevice;
|
||||
final port = _selectedPort;
|
||||
if (device == null || port == null) {
|
||||
final portIndex = _selectedPortIndex;
|
||||
if (device == null || portIndex == null) {
|
||||
setState(() => _status = '请先选择设备与串口');
|
||||
return;
|
||||
}
|
||||
final target = Ch934xPortTarget(
|
||||
deviceId: device.deviceId,
|
||||
interfaceNumber: device.interfaceCount > 0 ? 0 : 0,
|
||||
serialPortIndex: port.portIndex,
|
||||
interfaceNumber: 0,
|
||||
serialPortIndex: portIndex,
|
||||
);
|
||||
final ok = await _plugin.openPort(target);
|
||||
if (!ok) {
|
||||
@@ -115,7 +149,7 @@ class _Ch934xSerialExamplePageState extends State<Ch934xSerialExamplePage> {
|
||||
}
|
||||
setState(() {
|
||||
_portOpened = true;
|
||||
_status = '串口 ${port.portIndex} 已打开';
|
||||
_status = '串口 $portIndex 已打开';
|
||||
});
|
||||
_startReceiving();
|
||||
}
|
||||
@@ -215,27 +249,33 @@ class _Ch934xSerialExamplePageState extends State<Ch934xSerialExamplePage> {
|
||||
onChanged: (device) {
|
||||
setState(() {
|
||||
_selectedDevice = device;
|
||||
_selectedPort = device?.serialPorts.isNotEmpty == true
|
||||
? device!.serialPorts.first
|
||||
: null;
|
||||
if (device == null) {
|
||||
_availablePortIndices = const <int>[];
|
||||
_selectedPortIndex = null;
|
||||
} else {
|
||||
_availablePortIndices = _resolvePortIndices(device);
|
||||
_selectedPortIndex = _availablePortIndices.isNotEmpty
|
||||
? _availablePortIndices.first
|
||||
: null;
|
||||
}
|
||||
});
|
||||
},
|
||||
),
|
||||
if (_selectedDevice?.serialPorts.isNotEmpty == true) ...[
|
||||
if (_selectedDevice != null) ...[
|
||||
const SizedBox(height: 8),
|
||||
DropdownButton<Ch934xSerialPortInfo>(
|
||||
DropdownButton<int>(
|
||||
isExpanded: true,
|
||||
value: _selectedPort,
|
||||
value: _selectedPortIndex,
|
||||
hint: const Text('选择串口'),
|
||||
items: _selectedDevice!.serialPorts
|
||||
items: _availablePortIndices
|
||||
.map(
|
||||
(p) => DropdownMenuItem<Ch934xSerialPortInfo>(
|
||||
value: p,
|
||||
child: Text('port #${p.portIndex}'),
|
||||
(idx) => DropdownMenuItem<int>(
|
||||
value: idx,
|
||||
child: Text('port #$idx'),
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
onChanged: (p) => setState(() => _selectedPort = p),
|
||||
onChanged: (idx) => setState(() => _selectedPortIndex = idx),
|
||||
),
|
||||
],
|
||||
const SizedBox(height: 16),
|
||||
|
||||
Reference in New Issue
Block a user