Flutter配件设置插件flutter_accessorysetup的使用
Flutter配件设置插件flutter_accessorysetup的使用

目前库支持的功能包括:
- ✅ BLE(低功耗蓝牙)
- ✅ WiFi
- ✅ 迁移
重要提示:根据Apple的设计,该库仅适用于 iOS 18及以上版本。
如何使用
通过命令行安装库:
flutter pub get flutter_accessorysetup
设置
详细信息可参考 Apple文档。
Info.plist配置
你需要在iOS应用的Info.plist
文件中添加相应的键以使其正常工作。如果缺少必要的键,应用在显示选择器时会崩溃。
始终需要配置的键
<key>NSAccessorySetupKitSupports</key>
<array>
<string>Bluetooth</string>
<string>WiFi</string>
</array>
使用ASDiscoveryDescriptor
配置bluetoothServiceUUID
<key>NSAccessorySetupBluetoothServices</key>
<array>
<string>149E9E42-33AD-41AD-8665-70D153533EC1</string>
</array>
注意:这里的UUID字符串必须大写。
使用ASDiscoveryDescriptor
配置bluetoothNameSubstring
<key>NSAccessorySetupBluetoothNames</key>
<array>
<string>DeviceName</string>
</array>
注意:此功能在iOS 18开发者预览版2中无法使用。
其他制造商ID选项未在此处覆盖。
使用FlutterAccessorySetup
类
参考完整的代码示例,可以在示例应用中查看。
final _accessorySetup = FlutterAccessorySetup();
void activate() {
_accessorySetup.eventStream.listen((event) {
debugPrint('Got event: ${event.eventType}');
// 处理会话事件
});
await _accessorySetup.activate();
try {
_accessorySetup.showPickerForDevice(
'My Ble',
Assets.images.ble.path,
'4013ABDE-11C0-49E7-9939-4B4567C26ADA'
);
} on PlatformException {
debugPrint('Failed to show the picker');
}
}
void deactivate() {
_accessorySetup.dispose();
super.deactivate();
}
我们知道什么
- 应用在使用选择器与蓝牙设备交互时,无需请求蓝牙权限。
- 用户从选择器中选择设备非常方便。
- 如果想在同一类型设备中显示多个设备,每个设备应广播一个唯一的名称。选择器只会显示每种唯一名称的一个设备。如果设备暴露了0x1800服务,则该服务中的设备名称也应唯一。
- 当用户点击关闭按钮退出选择器时,
showPicker
闭包将发出错误(ASErrorDomain, code 700)。请注意处理这种情况。 - 如果用户选择了一个BLE配件,选择器将发送一个类型为
ASAccessoryEventType.accessoryChanged
的事件。但据观察,选择器应发送ASAccessoryEventType.accessoryAdded
类型的事件,这可能是一个bug。 - 如果设备之前已连接过,它会在会话激活后出现在
session.accessories
数组中。 - 如果设备已被其他应用连接过,选择器将显示由其他应用装饰过的设备——即图像和名称来自那个应用,而不是你提供的。要更改装饰,用户应该将设备添加到你的应用中。
- 当用户通过选择器选择设备时:
- 设备将在移动应用设置中的
Settings/Apps/YourApp
下的Accessories
部分显示。 - 设备将在
Settings/Bluetooth
下的My Devices
部分显示。 - 设备的信息屏幕将显示在发现过程中提供的图像和名称(即用户在选择器中看到的内容)。
- 设备将在移动应用设置中的
- 如果用户删除了应用,设备将自动断开连接。它将不再显示在
Settings/Bluetooth
屏幕的My Devices
部分。
请注意:AccessorySetup在模拟器上不工作。
参考资料
示例代码
以下是从示例应用中摘录的代码:
import 'package:flutter/material.dart';
import 'dart:async';
import 'package:flutter_accessorysetup/flutter_accessorysetup.dart';
import 'package:flutter_accessorysetup/gen/ios/accessory_setup_bindings.dart';
import 'package:flutter_accessorysetup_example/gen/assets.gen.dart';
import 'package:flutter_blue_plus/flutter_blue_plus.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 _deviceStatus = 'Disconnected';
String _events = "";
ASAccessory? _pickedAccessory;
StreamSubscription<BluetoothAdapterState>? _adapterStateSubscription;
StreamSubscription<ASAccessoryEvent>? _eventsSubscription;
final _accessorySetup = FlutterAccessorySetup();
[@override](/user/override)
void initState() {
super.initState();
_activateAccessorySession();
}
[@override](/user/override)
void deactivate() {
_adapterStateSubscription?.cancel();
_eventsSubscription?.cancel();
_accessorySetup.dispose();
super.deactivate();
}
Future<void> _activateAccessorySession() async {
_accessorySetup.eventStream.listen((event) {
debugPrint('Got event: ${event.eventType}');
setState(() {
_events += '\n\r${event.dartDescription};\n\r';
});
if (event.eventType == ASAccessoryEventType.ASAccessoryEventTypeActivated) {
connect();
} else if (event.eventType == ASAccessoryEventType.ASAccessoryEventTypeAccessoryAdded || event.eventType == ASAccessoryEventType.ASAccessoryEventTypeAccessoryChanged) {
setState(() {
_pickedAccessory = event.accessory;
});
} else if (event.eventType == ASAccessoryEventType.ASAccessoryEventTypePickerDidDismiss) {
debugPrint('user picked accessory: $_pickedAccessory)');
final accessory = _pickedAccessory;
setState(() {
_pickedAccessory = null;
});
final id = accessory?.dartBluetoothIdentifier;
if (accessory != null && id != null && accessory.state == ASAccessoryState.ASAccessoryStateAuthorized) {
_connectWithoutScanning(id);
} else {
throw Exception('added accessory should have identifier and be authorized');
}
}
});
_accessorySetup.activate();
}
Future<void> connect() async {
final firstAccessoryId = _accessorySetup.accessories.firstOrNull?.dartBluetoothIdentifier;
if (firstAccessoryId != null) {
debugPrint('Got an accessory, will try to connect: $firstAccessoryId');
await _connectWithoutScanning(firstAccessoryId);
return;
}
try {
// 为了使其正常工作,需要设置info.plist键
// NSAccessorySetupBluetoothServices -> UUID
// 和 NSAccessorySetupKitSupports -> Bluetooth
_accessorySetup.showPickerForDevice('My Ble', Assets.images.ble.path, '4013ABDE-11C0-49E7-9939-4B4567C26ADA');
} catch (e) {
if (e is NativeCodeError) {
debugPrint('Got native code error: $e');
} else {
debugPrint('Got error: $e');
}
}
}
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Accessory Setup App'),
),
body: Center(
child: Column(
children: [
Text('Device Status: $_deviceStatus'),
const SizedBox(height: 15),
Text('Setup Session Events: \n$_events'),
],
),
),
),
);
}
// 连接设备部分
Future<void> _connectWithoutScanning(String id) async {
debugPrint('_connectWithoutScanning: $id');
if (await FlutterBluePlus.isSupported == false) {
debugPrint('Bluetooth is not supported by this device');
return;
}
if (FlutterBluePlus.adapterStateNow == BluetoothAdapterState.on) {
_connectDevice(id);
return;
}
_adapterStateSubscription = FlutterBluePlus.adapterState.listen((BluetoothAdapterState state) {
debugPrint('got adapter state: $state');
if (state == BluetoothAdapterState.on) {
_connectDevice(id);
_adapterStateSubscription?.cancel();
}
});
}
Future<void> _connectDevice(String id) async {
var device = BluetoothDevice.fromId(id);
debugPrint('loaded device: $device');
try {
await device.connect();
setState(() {
_deviceStatus = 'Connected';
});
debugPrint('connected to device $device');
} catch (e) {
debugPrint('failed to connect: $e');
}
}
}
更多关于Flutter配件设置插件flutter_accessorysetup的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter配件设置插件flutter_accessorysetup的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
flutter_accessorysetup
是一个用于在 Flutter 应用中与配件(如智能家居设备)进行设置和配对的插件。这个插件通常用于简化与配件的连接和配置过程,使其更容易集成到 Flutter 应用中。
以下是一个基本的使用指南,帮助你开始使用 flutter_accessorysetup
插件。
1. 添加依赖
首先,你需要在 pubspec.yaml
文件中添加 flutter_accessorysetup
插件的依赖。
dependencies:
flutter:
sdk: flutter
flutter_accessorysetup: ^0.1.0 # 请使用最新版本
然后运行 flutter pub get
来安装依赖。
2. 导入插件
在你的 Dart 文件中导入 flutter_accessorysetup
插件。
import 'package:flutter_accessorysetup/flutter_accessorysetup.dart';
3. 初始化插件
在使用插件之前,通常需要先初始化它。
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await FlutterAccessorySetup.initialize();
runApp(MyApp());
}
4. 使用插件
flutter_accessorysetup
插件通常提供了一些方法来发现、连接和配置配件。以下是一些常见的使用场景:
4.1 发现配件
你可以使用插件来发现附近的配件。
void discoverAccessories() async {
List<Accessory> accessories = await FlutterAccessorySetup.discoverAccessories();
accessories.forEach((accessory) {
print('Found accessory: ${accessory.name}');
});
}
4.2 连接配件
发现配件后,你可以尝试连接到它。
void connectToAccessory(Accessory accessory) async {
bool isConnected = await FlutterAccessorySetup.connect(accessory);
if (isConnected) {
print('Successfully connected to ${accessory.name}');
} else {
print('Failed to connect to ${accessory.name}');
}
}
4.3 配置配件
连接成功后,你可以对配件进行配置。
void configureAccessory(Accessory accessory, Map<String, dynamic> config) async {
bool isConfigured = await FlutterAccessorySetup.configure(accessory, config);
if (isConfigured) {
print('Successfully configured ${accessory.name}');
} else {
print('Failed to configure ${accessory.name}');
}
}
5. 处理错误
在使用插件时,可能会遇到各种错误。你可以使用 try-catch
来捕获和处理这些错误。
void tryConnect(Accessory accessory) async {
try {
bool isConnected = await FlutterAccessorySetup.connect(accessory);
if (isConnected) {
print('Connected to ${accessory.name}');
} else {
print('Failed to connect to ${accessory.name}');
}
} catch (e) {
print('Error connecting to accessory: $e');
}
}
6. 监听状态变化
你可能还需要监听配件的状态变化,例如连接状态或配置状态。
void listenToAccessoryState(Accessory accessory) {
FlutterAccessorySetup.listenToState(accessory, (state) {
print('Accessory state changed: $state');
});
}
7. 清理资源
在应用退出或不再需要插件时,记得清理资源。
void dispose() {
FlutterAccessorySetup.dispose();
}
8. 示例应用
以下是一个简单的示例应用,展示如何发现、连接和配置配件。
import 'package:flutter/material.dart';
import 'package:flutter_accessorysetup/flutter_accessorysetup.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await FlutterAccessorySetup.initialize();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
home: AccessorySetupScreen(),
);
}
}
class AccessorySetupScreen extends StatefulWidget {
[@override](/user/override)
_AccessorySetupScreenState createState() => _AccessorySetupScreenState();
}
class _AccessorySetupScreenState extends State<AccessorySetupScreen> {
List<Accessory> accessories = [];
[@override](/user/override)
void initState() {
super.initState();
discoverAccessories();
}
void discoverAccessories() async {
accessories = await FlutterAccessorySetup.discoverAccessories();
setState(() {});
}
void connectToAccessory(Accessory accessory) async {
bool isConnected = await FlutterAccessorySetup.connect(accessory);
if (isConnected) {
print('Connected to ${accessory.name}');
} else {
print('Failed to connect to ${accessory.name}');
}
}
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Accessory Setup'),
),
body: ListView.builder(
itemCount: accessories.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(accessories[index].name),
onTap: () => connectToAccessory(accessories[index]),
);
},
),
);
}
}