flutter_web_bluetooth 0.1.0 flutter_web_bluetooth: ^0.1.0 copied to clipboard
A library to use the web bluetooth api in your web project. Will play nice if used in IO projects.
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_web_bluetooth/flutter_web_bluetooth.dart';
import 'package:flutter_web_bluetooth_example/business/bluetooth_business.dart';
import 'package:flutter_web_bluetooth_example/model/main_page_device.dart';
import 'package:flutter_web_bluetooth_example/pages/device_services_page.dart';
import 'package:flutter_web_bluetooth_example/web_helpers/web_helpers.dart';
import 'package:flutter_web_bluetooth_example/widgets/bluetooth_device_widget.dart';
import 'package:flutter_web_bluetooth_example/widgets/floating_action_buttons.dart';
const redirect = bool.fromEnvironment('redirectToHttps', defaultValue: false);
void main() {
if (redirect) {
WebHelpers.redirectToHttps();
}
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
return StreamBuilder<bool>(
stream: FlutterWebBluetooth.instance.isAvailable,
initialData: false,
builder: (BuildContext context, AsyncSnapshot<bool> snapshot) {
final available = snapshot.requireData;
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const SelectableText('Bluetooth web example app'),
),
body: MainPage(
isBluetoothAvailable: available,
),
floatingActionButtonLocation: FloatingActionButtonLocation.endDocked,
floatingActionButton: const FABS(),
));
},
);
}
}
class MainPage extends StatefulWidget {
final bool isBluetoothAvailable;
const MainPage({
Key? key,
required this.isBluetoothAvailable,
}) : super(key: key);
@override
State<StatefulWidget> createState() {
return MainPageState();
}
}
class MainPageState extends State<MainPage> {
Stream<Set<MainPageDevice>>? _devicesStream;
Color? _getErrorColor() {
if (!mounted) {
return null;
}
final theme = Theme.of(context);
return theme.colorScheme.error;
}
@override
void initState() {
super.initState();
_devicesStream = BluetoothBusiness.createDeviceStream();
}
Future<void> handleDeviceTap(final MainPageDevice device) async {
DeviceServicesPage? page;
if (device is MainPageDevice<BluetoothDevice>) {
page = DeviceServicesPage(bluetoothDevice: device.device);
} else {
final state =
await BluetoothBusiness.requestAdvertisementDevice(device.device);
late String message;
switch (state.state) {
case RequestDeviceState.adapterNotAvailable:
message = 'No bluetooth adapter available';
break;
case RequestDeviceState.userCancelled:
message = 'User canceled the dialog';
break;
case RequestDeviceState.deviceNotFound:
message = 'No devices found';
break;
case RequestDeviceState.ok:
message = '';
break;
case RequestDeviceState.other:
default:
message = 'Unknown error';
break;
}
if (state.state == RequestDeviceState.ok && state.device == null) {
message = 'Unknown error';
}
if (message.isNotEmpty && mounted) {
ScaffoldMessenger.maybeOf(context)?.showSnackBar(SnackBar(
content: Text(message),
backgroundColor: _getErrorColor(),
));
} else {
page = DeviceServicesPage(bluetoothDevice: state.device!);
}
}
if (page != null && mounted) {
final finalPage = page;
Navigator.push(context,
MaterialPageRoute(builder: (BuildContext context) {
return finalPage;
}));
} else {
debugPrint('Could not open the page because not mounted anymore');
}
}
@override
Widget build(BuildContext context) {
return Column(children: [
MainPageHeader(
isBluetoothAvailable: widget.isBluetoothAvailable,
),
const Divider(),
Expanded(
child: StreamBuilder(
stream: _devicesStream,
initialData: const {},
builder: (final BuildContext context, final AsyncSnapshot snapshot) {
final devices = snapshot.requireData;
return ListView.builder(
itemCount: devices.length,
itemBuilder: (BuildContext context, int index) {
final device = devices.toList()[index];
return BluetoothDeviceWidget(
bluetoothDevice: device,
onTap: () async {
await handleDeviceTap(device);
},
);
},
);
},
),
),
]);
}
}
class MainPageHeader extends StatelessWidget {
const MainPageHeader({Key? key, required this.isBluetoothAvailable})
: super(key: key);
final bool isBluetoothAvailable;
@override
Widget build(BuildContext context) {
final text = isBluetoothAvailable ? 'supported' : 'unsupported';
final screenWidth = MediaQuery.of(context).size.width;
final phoneSize = screenWidth <= 620.0;
final children = <Widget>[
SizedBox(
width: phoneSize ? screenWidth : screenWidth * 0.5,
child: ListTile(
title: const SelectableText('Bluetooth api available'),
subtitle: SelectableText(
FlutterWebBluetooth.instance.isBluetoothApiSupported
? 'true'
: 'false'),
)),
SizedBox(
width: phoneSize ? screenWidth : screenWidth * 0.5,
child: ListTile(
title: const SelectableText('Bluetooth available'),
subtitle: SelectableText(text),
)),
];
if (phoneSize) {
children.insert(1, const Divider());
return Column(
children: children,
);
} else {
return Row(children: children);
}
}
}