Flutter USB通信插件libusb_android_helper的使用

Flutter USB通信插件libusb_android_helper的使用

libusb_android_helper 是一个用于在 Flutter 应用程序中进行 USB 通信的插件。该插件通过使用原生 Java API 来查找和打开设备,并检索原生文件描述符,从而可以继续使用 libusb_android 进行操作。

获取开始

首先,在你的 pubspec.yaml 文件中添加依赖项:

dependencies:
  libusb_android_helper: ^1.0.0

然后,在 Dart 文件顶部导入该包:

import 'package:libusb_android_helper/libusb_android_helper.dart';

可选配置

为了使应用能够监听 USB 设备的连接和断开事件,你需要在 AndroidManifest.xml 中添加以下配置:

<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <uses-feature android:name="android.hardware.usb.host" />
    ...
    <application ... >
        <activity ... >
        ...
            <intent-filter>
                <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"/>
                <action android:name="android.hardware.usb.action.USB_DEVICE_DETACHED"/>
            </intent-filter>

            <meta-data android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
                    android:resource="@xml/device_filter" />
            <meta-data android:name="android.hardware.usb.action.USB_DEVICE_DETACHED"
                android:resource="@xml/device_filter" />
        </activity>
    </application>
</manifest>

同时,在 res/xml 目录下创建一个名为 device_filter.xml 的文件,并添加以下内容:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <usb-device vendor-id="[Your vid]" product-id="[Your pid]" />
</resources>

使用方法

以下是完整的示例代码,展示了如何列出已连接的设备、请求权限并打开设备进行操作:

import 'package:flutter/material.dart';
import 'dart:async';
import 'package:flutter/services.dart';
import 'package:libusb_android_helper/libusb_android_helper.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatefulWidget {
  const MyApp({super.key});

  [@override](/user/override)
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  String _message = "";
  UsbDevice? _device;
  
  Future<List<UsbDevice>> _getUsbDevices() async {
    List<UsbDevice>? devices;
    try {
      devices = await LibusbAndroidHelper.listDevices();
    } on PlatformException catch (e) {
      return List<UsbDevice>.empty();
    }
    if (devices != null) {
      return devices;
    } else {
      return List<UsbDevice>.empty();
    }
  }

  Future<void> _requestPermissionAndOpenDevice() async {
    if (_device == null) {
      return;
    }
    if (!(await _device!.hasPermission())) {
      await _device!.requestPermission();
    }
    await _device!.open();
  }

  String getDeviceMessage() {
    if (_device != null && _device!.isOpen && _device!.handle != 0) {
      return "Successfully opened device \"${_device!.identifier}\" with handle \"${_device!.handle}\"";
    } else {
      return "Error: Unable to open device";
    }
  }

  [@override](/user/override)
  void initState() {
    super.initState();
    initUsbDevices();
    String msg = "";
    LibusbAndroidHelper.usbEventStream?.listen((event) async {
      try {
        if (event.action == UsbAction.usbDeviceAttached) {  
          _device = event.device;
          await _requestPermissionAndOpenDevice();
          msg = getDeviceMessage();
        } else if (event.action == UsbAction.usbDeviceDetached) {
          _device = null;
          msg = "USB device disconnected";
        }
      } on PlatformException catch (e) {
        _device = null;
        msg = "Error: ${e.message}";
      }
      if (mounted) {
        setState(() => _message = msg);
      }
    });
  }

  void initUsbDevices() async {
    String msg = "";
    try {
      List<UsbDevice> devices = await _getUsbDevices();
      if (devices.isNotEmpty) {
        _device = devices.first;
        await _requestPermissionAndOpenDevice();
        msg = getDeviceMessage();
      }
    } on PlatformException catch(e) {
      msg = "Error: ${e.message}";
    }
    if (mounted) { 
      setState(() => _message = msg);
    }    
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('libusb_android_helper example app'),
        ),
        body: Center(
          child: Text(_message.isEmpty ? "No device connected" : _message),
        ),
      ),
    );
  }
}

完整示例代码解释

  1. 导入库

    import 'package:flutter/material.dart';
    import 'dart:async';
    import 'package:flutter/services.dart';
    import 'package:libusb_android_helper/libusb_android_helper.dart';
    
  2. 初始化应用

    void main() {
      runApp(const MyApp());
    }
    
  3. 定义状态类

    class _MyAppState extends State<MyApp> {
      String _message = "";
      UsbDevice? _device;
    
  4. 获取已连接的 USB 设备列表

    Future<List<UsbDevice>> _getUsbDevices() async {
      List<UsbDevice>? devices;
      try {
        devices = await LibusbAndroidHelper.listDevices();
      } on PlatformException catch (e) {
        return List<UsbDevice>.empty();
      }
      if (devices != null) {
        return devices;
      } else {
        return List<UsbDevice>.empty();
      }
    }
    
  5. 请求权限并打开设备

    Future<void> _requestPermissionAndOpenDevice() async {
      if (_device == null) {
        return;
      }
      if (!(await _device!.hasPermission())) {
        await _device!.requestPermission();
      }
      await _device!.open();
    }
    
  6. 处理设备消息

    String getDeviceMessage() {
      if (_device != null && _device!.isOpen && _device!.handle != 0) {
        return "Successfully opened device \"${_device!.identifier}\" with handle \"${_device!.handle}\"";
      } else {
        return "Error: Unable to open device";
      }
    }
    
  7. 监听 USB 事件

    [@override](/user/override)
    void initState() {
      super.initState();
      initUsbDevices();
      String msg = "";
      LibusbAndroidHelper.usbEventStream?.listen((event) async {
        try {
          if (event.action == UsbAction.usbDeviceAttached) {  
            _device = event.device;
            await _requestPermissionAndOpenDevice();
            msg = getDeviceMessage();
          } else if (event.action == UsbAction.usbDeviceDetached) {
            _device = null;
            msg = "USB device disconnected";
          }
        } on PlatformException catch (e) {
          _device = null;
          msg = "Error: ${e.message}";
        }
        if (mounted) {
          setState(() => _message = msg);
        }
      });
    }
    
  8. 初始化 USB 设备

    void initUsbDevices() async {
      String msg = "";
      try {
        List<UsbDevice> devices = await _getUsbDevices();
        if (devices.isNotEmpty) {
          _device = devices.first;
          await _requestPermissionAndOpenDevice();
          msg = getDeviceMessage();
        }
      } on PlatformException catch(e) {
        msg = "Error: ${e.message}";
      }
      if (mounted) { 
        setState(() => _message = msg);
      }    
    }
    
  9. 构建 UI

    [@override](/user/override)
    Widget build(BuildContext context) {
      return MaterialApp(
        home: Scaffold(
          appBar: AppBar(
            title: const Text('libusb_android_helper example app'),
          ),
          body: Center(
            child: Text(_message.isEmpty ? "No device connected" : _message),
          ),
        ),
      );
    }
    

更多关于Flutter USB通信插件libusb_android_helper的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter USB通信插件libusb_android_helper的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,我可以为你提供一个关于如何在Flutter中使用libusb_android_helper插件进行USB通信的示例代码。这个插件允许Flutter应用与USB设备进行通信,特别是在Android平台上。

首先,确保你的Flutter项目已经添加了libusb_android_helper依赖。你可以在你的pubspec.yaml文件中添加以下依赖:

dependencies:
  flutter:
    sdk: flutter
  libusb_android_helper: ^最新版本号  # 请替换为实际最新版本号

然后运行flutter pub get来安装依赖。

接下来,你需要进行一些初始化工作,并编写与USB设备通信的代码。以下是一个基本的示例,展示了如何初始化libusb_android_helper并与USB设备通信。

1. 初始化插件

在你的Flutter应用的Dart文件中(例如main.dart),首先导入所需的包并初始化插件:

import 'package:flutter/material.dart';
import 'package:libusb_android_helper/libusb_android_helper.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter USB Communication',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: UsbCommunicationScreen(),
    );
  }
}

class UsbCommunicationScreen extends StatefulWidget {
  @override
  _UsbCommunicationScreenState createState() => _UsbCommunicationScreenState();
}

class _UsbCommunicationScreenState extends State<UsbCommunicationScreen> {
  LibUsb? libUsb;
  UsbDevice? device;

  @override
  void initState() {
    super.initState();
    _initUsb();
  }

  Future<void> _initUsb() async {
    libUsb = await LibUsb.getInstance();
    if (libUsb == null) {
      print("Failed to initialize libusb");
      return;
    }

    // 列出所有连接的USB设备
    List<UsbDevice> devices = await libUsb!.getDeviceList();
    if (devices.isEmpty) {
      print("No USB devices found");
      return;
    }

    // 假设我们选择第一个设备(实际中你可能需要更复杂的设备选择逻辑)
    device = devices.first;

    // 打开设备(注意:这里需要处理权限和设备状态等)
    if (await device!.openDevice()) {
      print("Device opened successfully");
      // 你可以在这里进行进一步的配置,如设置配置、声明接口等
    } else {
      print("Failed to open device");
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter USB Communication'),
      ),
      body: Center(
        child: Text('Check the console for USB communication status.'),
      ),
    );
  }

  @override
  void dispose() {
    // 确保在销毁时关闭设备
    device?.closeDevice();
    libUsb?.exit();
    super.dispose();
  }
}

2. 权限处理

由于访问USB设备需要特定的权限,你需要在Android的AndroidManifest.xml文件中添加以下权限:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.yourapp">

    <uses-permission android:name="android.permission.USB_PERMISSION"/>
    <application
        ...>
        <!-- Your application setup -->
    </application>

    <!-- USB Host feature -->
    <uses-feature android:name="android.hardware.usb.host" />
</manifest>

此外,你可能需要在运行时请求USB权限,这通常涉及到使用UsbManagerPendingIntent,但这部分通常在原生Android代码中处理,而libusb_android_helper插件可能会为你处理一些细节。

3. 更复杂的通信

上述代码只是展示了如何初始化libusb_android_helper并打开一个USB设备。实际的通信(如读取和写入数据)需要更复杂的逻辑,包括设置端点、配置和控制传输等。你可以参考libusb_android_helper的文档和示例代码来编写更详细的通信逻辑。

请注意,这个示例代码仅用于演示基本的初始化过程,并没有处理所有可能的错误情况和权限请求。在实际应用中,你需要添加适当的错误处理和用户交互逻辑来确保应用的健壮性和用户体验。

回到顶部