import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_usb_serial/flutter_usb_serial.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatefulWidget { const MyApp({super.key}); @override State createState() => _MyAppState(); } class _MyAppState extends State { List _devices = const []; String _status = 'Tap refresh to scan for attached USB serial devices.'; bool _isLoading = false; @override void initState() { super.initState(); unawaited(_refreshDevices()); } Future _refreshDevices() async { setState(() { _isLoading = true; }); try { final devices = await FlutterUsbSerial.listDevices(); if (!mounted) return; setState(() { _devices = devices; _status = devices.isEmpty ? 'No USB serial devices detected.' : 'Found ${devices.length} USB serial device(s).'; }); } on MissingPluginException { if (!mounted) return; setState(() { _devices = const []; _status = 'USB serial support is only available on Android.'; }); } on PlatformException catch (error) { if (!mounted) return; setState(() { _devices = const []; _status = error.message ?? 'Failed to list USB serial devices.'; }); } finally { if (mounted) { setState(() { _isLoading = false; }); } } } Future _requestPermission(UsbSerialDevice device) async { String status; try { final granted = await FlutterUsbSerial.requestPermission(device); status = granted ? 'Permission granted for device ${device.deviceId}.' : 'Permission denied for device ${device.deviceId}.'; } on MissingPluginException { status = 'USB serial support is only available on Android.'; } on PlatformException catch (error) { status = error.message ?? 'Failed to request USB permission.'; } if (!mounted) return; setState(() { _status = status; }); } @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar( title: const Text('USB Serial Example'), ), body: SafeArea( child: Column( children: [ Padding( padding: const EdgeInsets.all(16), child: Row( children: [ Expanded( child: Text( _status, key: const Key('status_text'), ), ), const SizedBox(width: 12), FilledButton.icon( onPressed: _isLoading ? null : _refreshDevices, icon: const Icon(Icons.refresh), label: const Text('Refresh devices'), ), ], ), ), Expanded( child: _isLoading ? const Center(child: CircularProgressIndicator()) : _devices.isEmpty ? const Center( child: Text('Connect an Android USB serial device to see it here.'), ) : ListView.separated( itemCount: _devices.length, separatorBuilder: (_, __) => const Divider(height: 1), itemBuilder: (context, index) { final device = _devices[index]; return ListTile( leading: const Icon(Icons.usb), title: Text( device.deviceName.isEmpty ? 'USB device ${device.deviceId}' : device.deviceName, ), subtitle: Text( 'VID 0x${device.vendorId.toRadixString(16).padLeft(4, '0')} ' 'PID 0x${device.productId.toRadixString(16).padLeft(4, '0')}\n' 'Manufacturer: ${device.manufacturerName.isEmpty ? 'Unknown' : device.manufacturerName}', ), isThreeLine: true, trailing: OutlinedButton( onPressed: () => _requestPermission(device), child: const Text('Request permission'), ), ); }, ), ), ], ), ), ), ); } }