Flutter硬件接口访问插件hid的使用
Flutter硬件接口访问插件hid的使用
hid
插件是一个多平台插件,允许应用程序在 Linux、Windows、Android 和 macOS 上与 USB HID 类设备进行交互。
完整示例代码
以下是一个完整的示例代码,展示了如何使用 hid
插件来列出连接到设备的所有 HID 设备,并展示其相关信息。
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:hid/hid.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
List<Device>? _hidDevices;
@override
void initState() {
super.initState();
_listDevices();
}
// 平台消息是异步的,因此我们在异步方法中初始化。
Future<void> _listDevices() async {
setState(() {
_hidDevices = null;
});
final hidDevices = await getDeviceList();
hidDevices.sort((a, b) => a.usage?.compareTo(b.usage ?? 0) ?? 0);
hidDevices.sort((a, b) => a.usagePage?.compareTo(b.usagePage ?? 0) ?? 0);
hidDevices.sort((a, b) => a.productId.compareTo(b.productId));
hidDevices.sort((a, b) => a.vendorId.compareTo(b.vendorId));
hidDevices.sort((a, b) => a.productName.compareTo(b.productName));
// 如果小部件在异步平台消息还在飞行时从树中移除,则我们希望丢弃回复而不是调用
// setState 更新我们的不存在的外观。
if (!mounted) return;
setState(() {
_hidDevices = hidDevices;
});
}
_getUsagePageIcon(int? usagePage, int? usage) {
// 根据 usagePage 和 usage 返回相应的图标
switch (usagePage) {
case 0x01:
switch (usage) {
case 0x01:
return Icons.north_west;
case 0x02:
return Icons.mouse;
case 0x04:
case 0x05:
return Icons.gamepad;
case 0x06:
return Icons.keyboard;
}
return Icons.computer;
case 0x0b:
switch (usage) {
case 0x04:
case 0x05:
return Icons.headset_mic;
}
return Icons.phone;
case 0x0c:
return Icons.toggle_on;
case 0x0d:
return Icons.touch_app;
case 0xf1d0:
return Icons.security;
}
return Icons.usb;
}
@override
Widget build(BuildContext context) {
final dev = _hidDevices;
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('HID 插件示例应用'),
),
body: dev == null
? const Center(child: CircularProgressIndicator())
: ListView.builder(
itemCount: dev.length,
itemBuilder: (context, index) => ListTile(
leading: Icon(_getUsagePageIcon(
dev[index].usagePage, dev[index].usage)),
title: Text(dev[index].productName),
subtitle: Text(
'${dev[index].vendorId.toRadixString(16).padLeft(4, '0')}:${dev[index].productId.toRadixString(16).padLeft(4, '0')} ${dev[index].serialNumber}'),
),
),
floatingActionButton: FloatingActionButton(
child: const Icon(Icons.refresh),
onPressed: dev == null ? null : _listDevices,
),
),
);
}
}
代码说明
-
导入必要的库
import 'dart:async'; import 'package:flutter/material.dart'; import 'package:hid/hid.dart';
-
主函数
void main() { runApp(const MyApp()); }
-
创建一个状态管理类
_MyAppState
class MyApp extends StatefulWidget { const MyApp({Key? key}) : super(key: key); @override State<MyApp> createState() => _MyAppState(); }
-
初始化设备列表
class _MyAppState extends State<MyApp> { List<Device>? _hidDevices; @override void initState() { super.initState(); _listDevices(); }
-
获取设备列表
Future<void> _listDevices() async { setState(() { _hidDevices = null; }); final hidDevices = await getDeviceList(); hidDevices.sort((a, b) => a.usage?.compareTo(b.usage ?? 0) ?? 0); hidDevices.sort((a, b) => a.usagePage?.compareTo(b.usagePage ?? 0) ?? 0); hidDevices.sort((a, b) => a.productId.compareTo(b.productId)); hidDevices.sort((a, b) => a.vendorId.compareTo(b.vendorId)); hidDevices.sort((a, b) => a.productName.compareTo(b.productName)); if (!mounted) return; setState(() { _hidDevices = hidDevices; }); }
-
根据设备类型返回对应的图标
_getUsagePageIcon(int? usagePage, int? usage) { switch (usagePage) { case 0x01: switch (usage) { case 0x01: return Icons.north_west; case 0x02: return Icons.mouse; case 0x04: case 0x05: return Icons.gamepad; case 0x06: return Icons.keyboard; } return Icons.computer; case 0x0b: switch (usage) { case 0x04: case 0x05: return Icons.headset_mic; } return Icons.phone; case 0x0c: return Icons.toggle_on; case 0x0d: return Icons.touch_app; case 0xf1d0: return Icons.security; } return Icons.usb; }
-
构建界面
@override Widget build(BuildContext context) { final dev = _hidDevices; return MaterialApp( home: Scaffold( appBar: AppBar( title: const Text('HID 插件示例应用'), ), body: dev == null ? const Center(child: CircularProgressIndicator()) : ListView.builder( itemCount: dev.length, itemBuilder: (context, index) => ListTile( leading: Icon(_getUsagePageIcon( dev[index].usagePage, dev[index].usage)), title: Text(dev[index].productName), subtitle: Text( '${dev[index].vendorId.toRadixString(16).padLeft(4, '0')}:${dev[index].productId.toRadixString(16).padLeft(4, '0')} ${dev[index].serialNumber}'), ), ), floatingActionButton: FloatingActionButton( child: const Icon(Icons.refresh), onPressed: dev == null ? null : _listDevices, ), ), ); }
更多关于Flutter硬件接口访问插件hid的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter硬件接口访问插件hid的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
在Flutter中访问硬件接口(如HID设备)通常需要使用平台通道(Platform Channels)与原生代码进行交互。由于HID(Human Interface Devices)设备的访问涉及到底层系统API,Flutter本身并不直接提供对HID设备的访问能力,因此我们需要通过插件来实现这一功能。
以下是一个简单的示例,展示如何创建一个Flutter插件来访问HID设备。这个示例将分为两部分:Flutter前端代码和原生后端代码(包括Android和iOS)。
Flutter 前端代码
首先,创建一个新的Flutter项目,并添加一个自定义插件。
- 创建一个新的Flutter项目:
flutter create flutter_hid_example
cd flutter_hid_example
- 添加自定义插件:
在flutter_hid_example/
目录下,运行以下命令来生成插件模板:
flutter create --template=plugin flutter_hid_plugin
这将创建一个名为flutter_hid_plugin
的目录,其中包含插件的代码结构。
- 在
flutter_hid_example/pubspec.yaml
中添加对插件的依赖:
dependencies:
flutter:
sdk: flutter
flutter_hid_plugin:
path: ../flutter_hid_plugin
- 使用插件在Flutter中访问HID设备:
在flutter_hid_example/lib/main.dart
中,编写如下代码:
import 'package:flutter/material.dart';
import 'package:flutter_hid_plugin/flutter_hid_plugin.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
String deviceInfo = "";
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Flutter HID Example'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text('HID Device Info:'),
Text(deviceInfo),
ElevatedButton(
onPressed: _listDevices,
child: Text('List HID Devices'),
),
],
),
),
),
);
}
Future<void> _listDevices() async {
try {
String result = await FlutterHidPlugin.listDevices();
setState(() {
deviceInfo = result;
});
} catch (e) {
setState(() {
deviceInfo = "Error: ${e.message}";
});
}
}
}
原生后端代码
接下来,我们需要在原生代码中实现HID设备的访问逻辑。
Android
- 在
flutter_hid_plugin/android/src/main/java/com/example/flutter_hid_plugin/FlutterHidPlugin.java
中,编写如下代码:
package com.example.flutter_hid_plugin;
import androidx.annotation.NonNull;
import io.flutter.embedding.engine.plugins.FlutterPlugin;
import io.flutter.embedding.engine.plugins.activity.ActivityAware;
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
import io.flutter.plugin.common.MethodChannel.Result;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbDeviceManager;
import android.hardware.usb.UsbManager;
import java.util.List;
public class FlutterHidPlugin implements FlutterPlugin, MethodCallHandler, ActivityAware {
private MethodChannel channel;
private ActivityPluginBinding activityBinding;
@Override
public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBinding) {
channel = new MethodChannel(flutterPluginBinding.getBinaryMessenger(), "flutter_hid_plugin");
channel.setMethodCallHandler(this);
}
@Override
public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) {
if (call.method.equals("listDevices")) {
List<UsbDevice> devices = getUsbDevices();
StringBuilder sb = new StringBuilder();
for (UsbDevice device : devices) {
sb.append(device.getDeviceName()).append("\n");
}
result.success(sb.toString());
} else {
result.notImplemented();
}
}
@Override
public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {
channel.setMethodCallHandler(null);
}
private List<UsbDevice> getUsbDevices() {
UsbManager usbManager = (UsbManager) activityBinding.getActivity().getSystemService(android.content.Context.USB_SERVICE);
return (usbManager != null) ? usbManager.getDeviceList().values() : null;
}
@Override
public void onAttachedToActivity(ActivityPluginBinding binding) {
activityBinding = binding;
}
@Override
public void onDetachedFromActivityForConfigChanges() {
activityBinding = null;
}
@Override
public void onReattachedToActivityForConfigChanges(ActivityPluginBinding binding) {
activityBinding = binding;
}
@Override
public void onDetachedFromActivity() {
activityBinding = null;
}
}
注意:这个示例仅列出了USB设备,并没有进行HID设备的具体筛选和访问。实际项目中,你可能需要使用更具体的HID API或库来处理HID设备。
iOS
iOS上访问HID设备通常需要使用IOKit
框架。由于iOS开发的复杂性,这里仅提供一个简单的框架搭建思路,具体实现需要更深入的iOS开发知识。
- 在
flutter_hid_plugin/ios/Classes/FlutterHidPlugin.swift
中,编写如下代码:
import Flutter
import IOKit.hid
public class FlutterHidPlugin: NSObject, FlutterPlugin {
public static func register(with registrar: FlutterRegistrar) {
let channel = FlutterMethodChannel(name: "flutter_hid_plugin", binaryMessenger: registrar.messenger())
let instance = FlutterHidPlugin()
registrar.addMethodCallDelegate(instance, channel: channel)
}
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
if call.method == "listDevices" {
let devices = listDevices()
result(devices)
} else {
result(FlutterMethodNotImplementedError(methodName: call.method))
}
}
private func listDevices() -> [String] {
var deviceNames: [String] = []
// TODO: Implement HID device listing using IOKit
return deviceNames
}
}
注意:在iOS上,你需要使用IOKit
框架来列出和访问HID设备。这通常涉及到底层C语言的调用和Objective-C/Swift的桥接,可能需要较深的iOS系统级开发知识。
总结
上述代码提供了一个基本的框架,展示了如何在Flutter中通过平台通道访问原生代码。然而,由于HID设备的访问涉及到底层系统API,实际项目中你可能需要更深入地了解相关平台的API和库,以完成HID设备的具体访问和操作。
请根据你的具体需求和目标平台的API文档,进一步完善和扩展上述代码。