navideck/universal_ble/universal-ble-setup

Claude Code and agent skill by navideck/universal_ble

Trust tier 3
  • community
  • ext:[{"type":"plugin","description":"Custom plugin integration"}]
Source check pending

Checking that the SKILL.md file is still in the repository.

Use when adding universal_ble to a Flutter app for the first time — BLE scanning, connecting, service discovery, read/write, notifications and indications, or peripheral advertising — or when configuring platform permissions on Android, iOS, macOS, Windows, Linux, or Web, including the Android manifest permissions, the Apple Info.plist keys and macOS Bluetooth entitlement, and Web optional services. Also use when a scan returns nothing, connect times out, a read/write fails, notifications never…

Install

npx vskill@latest install navideck/universal_ble/universal-ble-setup

Semi-extensibleMentions customization, but needs skill-specific knowledge. Read the extensible skills standard

SKILL.md

Adding universal_ble to a Flutter app

universal_ble is a single Flutter plugin for BLE central (and peripheral) on Android, iOS, macOS, Windows, Linux, and Web. This skill gets a first integration working and points to the README for detail. The README anchors below link to `README.md`.

Rules

  1. Depend on universal_ble only. One package covers every platform — Windows

support is built in (no flutter_blue_plus_winrt-style add-on).

  1. Read the README Platform-specific setup

before the first build; missing manifest/plist/entitlement entries make BLE silently fail or the app get killed.

  1. Check availability before scanning: wait for AvailabilityState.poweredOn

via getBluetoothAvailabilityState() or availabilityStream (Bluetooth Availability).

  1. Register onScanResult or listen to scanStream before calling

startScan(); results are per-device BleDevice events, not batches.

  1. startScan() has no timeout: parameter. Stop it yourself with a Timer or

stopScan(), and stop scanning before connecting.

  1. Call discoverServices() after every (re)connection. getService() and

getCharacteristic() auto-discover when the cache is empty, but an explicit call is recommended.

  1. Subscribe before listening: await characteristic.notifications.subscribe()

(or indications.subscribe()), then read characteristic.onValueReceived.

  1. write() defaults to with response. Pass withResponse: false for a

write-without-response.

  1. Permissions are requested automatically on startScan(). Call

requestPermissions() explicitly before connect()/read()/write() if you need them confirmed first.

  1. connect(autoConnect: true) reconnects while the device is available; call

disconnect() to stop it.

  1. UUIDs are format-agnostic: pass "180f", "180F", or the full 128-bit form.

Results always come back lowercase 128-bit.

  1. Peripheral APIs require getCapabilities().supportsPeripheralMode. Linux

and Web do not support peripheral mode.

Setup (central role)

yaml
# pubspec.yaml
dependencies:
universal_ble: ^3.0.0
dart
import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:universal_ble/universal_ble.dart';
Future<void> startBle() async {
// 1. Wait until Bluetooth is on. See #bluetooth-availability.
if (await UniversalBle.getBluetoothAvailabilityState() !=
AvailabilityState.poweredOn) {
return;
}
// 2. Listen for results, then scan. See #scanning and #scan-filter.
UniversalBle.scanStream.listen((BleDevice device) {
debugPrint('${device.deviceId} ${device.name} rssi=${device.rssi}');
});
await UniversalBle.startScan(
scanFilter: ScanFilter(withServices: ['180f']),
);
Timer(const Duration(seconds: 15), () => UniversalBle.stopScan());
// 3. Connect and discover. See #connecting and #discovering-services.
final device = BleDevice(deviceId: 'DEVICE_ID', name: null);
await device.connect();
final services = await device.discoverServices();
// 4. Read or subscribe. See #reading--writing-data and #subscriptions.
final characteristic = services
.firstWhere((s) => BleUuidParser.compareStrings(s.uuid, '180f'))
.getCharacteristic('2a19');
final value = await characteristic.read();
await characteristic.notifications.subscribe();
characteristic.onValueReceived.listen((v) => debugPrint('$value $v'));
}

Other topics the README covers in depth: scan filters, system devices, auto-connect and background events, pairing, MTU, RSSI, command queue, timeout, error handling, and logging.

Prefer the object API (bleDevice, characteristic) above. The Low-Level API is a deviceId-based alternative for stateless or service-style code.

Peripheral role (pointer)

Check capabilities before using UniversalBlePeripheral:

dart
final caps = await UniversalBlePeripheral.getCapabilities();
if (!caps.supportsPeripheralMode) return;

Full service management, advertising, request handlers, and event streams are in Peripheral Mode.

Traps

Scan returns nothing

  • Check AvailabilityState.poweredOn and that permissions were granted.
  • Stop any prior scan before starting a new one.
  • Android: for legacy BLE 4.x peripherals (e.g. ESP32) pass

platformConfig: PlatformConfig(android: AndroidOptions(legacy: true)) (Android scan options).

  • Web: you must list the services you will use in the scan filter

(Web).

`AvailabilityState.unsupported` on macOS

  • Symptom: availability reports unsupported even with Bluetooth on.
  • Fix: add the com.apple.security.device.bluetooth entitlement to both

DebugProfile.entitlements and Release.entitlements (macOS entitlements).

`MissingPluginException` right after adding the package

  • Hot reload/restart is not enough. Fully stop and re-run the app; try

flutter clean if it persists.

`connect()` throws or times out

  • Ensure Bluetooth is on, permissions are granted, and scanning is stopped.
  • Catch ConnectionException and inspect e.code

(UniversalBleErrorCode.connectionTimeout, connectionFailed, deviceDisconnected, …) (Error Handling).

`serviceNotFound` / `characteristicNotFound`

  • Call discoverServices() after connecting; UUIDs are format-agnostic.
  • Android keeps a GATT cache across connections; if the peripheral's layout

changed, pass platformConfig: DiscoverServicesPlatformConfig(android: AndroidDiscoverServicesOptions(clearGattCache: true)).

Notifications never fire

  • Subscribe first (notifications.subscribe() or indications.subscribe()),

then listen to onValueReceived.

  • Verify the characteristic advertises notify/indicate in

characteristic.properties.

Stale state after a hot restart

  • Native connections and scans can outlive Dart state in debug hot restart. Use

the resetBleState() helper (Resetting State on Hot Restart).

`write` appears to hang or behaves unexpectedly

  • write() is with-response by default. Use withResponse: false for

write-without-response.

Peripheral APIs throw / do nothing

  • Guard with caps.supportsPeripheralMode; Linux and Web return unsupported.

Where to go next

TaskREADME
Scan filters (services, manufacturer data, name prefix, exclusions)Scan Filter
Devices already connected by the OS / other appsSystem Devices
Auto-connect and background connection eventsAuto-connect
MTU, connection priority, RSSIRequesting MTU · Reading RSSI
Pairing / bondingPairing
DescriptorsReading & Writing data
Subscription statusCheck Subscription Status
Queueing and global timeoutCommand Queue · Timeout
Typed errorsError Handling
Debug loggingLogging
Mock / custom platform implementationCustomizing Platform Implementation
Peripheral serverPeripheral Mode
Coming from flutter_blue_plususe the universal-ble-migrate-from-flutter-blue-plus skill

When in doubt, follow the README — it is the source of truth for this package.

Security

  • Security scanPassed, 90 of 100Pattern checks on the skill's files.
  • Model reviewPassed

Quality evaluation

  • Task evaluationNot runNo evaluation yet. Run one in Skill Studio.

Source

Popularity

Repository stars
171
Repository forks
77
7-day trend score
0

Stars and forks are for the whole GitHub repository, not this skill alone. Not refreshed yet.

Extension points

  • pluginCustom plugin integration

Works with

Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.

  • Claude Code
  • Cursor
  • GitHub Copilot
  • Windsurf
  • Codex
  • Gemini CLI
  • Cline
  • Amp
  • Roo Code
  • Goose
  • Continue
  • Kilo Code
  • Junie
  • Trae
  • OpenHands
  • Qwen Code
  • AI Agent
  • Tabnine Chat
  • Sourcegraph Cody
  • Amazon Q
  • Firebase Genkit
  • Sweep
  • Devin
  • Phind
  • Mentat
  • Claude Desktop
  • Aider
  • GPT Pilot
  • Plandex
  • bolt.new
  • v0
  • Replit Agent
  • Anse
  • TypingMind
  • BetterChatGPT
  • LibreChat
  • Warp AI
  • Pieces
  • Fig AI
Embed badge
vskill VERIFIED badge
[![vskill VERIFIED](https://verified-skill.com/api/v1/skills/navideck/universal_ble/universal-ble-setup/badge)](https://verified-skill.com/skills/navideck/universal_ble/universal-ble-setup)

Something wrong with this skill or its page? Tell us.