Open source · BSD-3-Clause · v0.1 on pub.dev

Flutter plugins for real hardware.

skio connects Flutter apps to USB serial devices and USB cameras, on Android and in the browser, with macOS, Windows, Linux and iPad coming soon. It binds native APIs directly with jnigen and dart:js_interop, so there are no platform channels, and the logic lives in testable Dart.

$ flutter pub add skio_usb_serial
  • 3packages
  • 160/160pub points
  • 2platforms today: Android and web
  • +4coming soon
  • 0platform channels

Illustration of the calls in the code sample below.

  • ESP32
  • STM32
  • Nordic nRF
  • Arduino
  • CP210x
  • CH340
  • FTDI
  • PL2303
  • CDC-ACM
  • Android USB OTG
  • Web Serial
  • UVC cameras
  • Endoscopes
  • Microscopes
  • USB webcams
  • macOS · Windows · Linux · iPad (coming soon)

Packages

One family, one way of doing things.

Each plugin covers one transport. They share permissions, errors and device matching through skio_core.

Stable · v0.1

skio_usb_serial

Send and receive data with USB serial devices: Arduino and ESP32 boards, USB-to-serial adapters, instruments. Android over USB OTG, and Chrome or Edge with Web Serial.

  • ESP32
  • STM32
  • Nordic nRF
  • Arduino
  • CP210x
  • CH340
  • FTDI
Stable · v0.1

skio_uvc_camera

USB cameras (endoscopes, microscopes, webcams) on Android and the web: live preview, JPEG photos, the camera's snapshot button, and your choice of resolution.

  • Android
  • Web
  • UVC
  • MJPEG
Stable · v0.1

skio_core

The shared building blocks: one permission API, one error family, device filters and opt-in logging for every skio plugin.

  • Pure Dart
  • No Flutter dependency

How it works

From your widget to the wire, in Dart.

skio calls the platform USB APIs through generated bindings. Buffering, framing and timeouts run in Dart, where you can test them. The diagram shows serial; skio_uvc_camera takes the same path to UVCAndroid on Android and getUserMedia in the browser.

Your app
Flutter UI Widgets, state and your device's protocol.
skio · Dart
UsbSerialPort Ordered writes, timeouts, LineReader, one HardwareException type.
Android
jnigen → UsbManager Direct JNI calls, USB OTG.
Web
js_interop → Web Serial Chrome and Edge.
Hardware
Your device CP210x, CH340, FTDI or CDC-ACM over USB.
MethodChannelNo platform channel in between: no message codec, no stringly-typed method names. Typed calls go from Dart to the OS.

What it looks like

A small API that stays out of your way.

Open a port and exchange bytes, or open a camera and take a photo. Errors come from one sealed type, so a switch can handle every case.

  • DeviceFilter to match ports by vendor and product ID
  • SerialConfig for baud rate, data bits, parity, stop bits and flow control
  • dtr / rts set in the config, so ESP32 and Arduino boards don't reset on open
  • LineReader for lines and UTF-8 split across reads
  • UvcSize to choose the camera resolution from what it supports
  • SkioLog opt-in logs, down to every byte, for bug reports
final ports = await UsbSerialPort.list();
final port = await UsbSerialPort.open(ports.first,
    config: const SerialConfig(baudRate: 115200));

port.input.listen((bytes) => print(bytes));
await port.write(utf8.encode('hello\n'));
await port.close();

Platform support

Where each package runs.

All three packages are on pub.dev and have been tested with real hardware on Android and the web. Desktop and iPad support is on the way.

PackageAndroidWebNotes
skio_usb_serial stableUSB OTG, Android 7.0+ stableWeb Serial, Chrome and Edge Tested with ESP32, STM32 and Nordic boards on vivo, OPPO, Samsung and POCO phones, and in Chrome on macOS.
skio_uvc_camera stableUSB OTG, Android 7.0+ stablegetUserMedia; no snapshot button Preview, JPEG photos, snapshot button and resolution choice. Tested with a USB camera on a POCO phone (Android 16).
skio_core pure Dart pure Dart No platform code. Each plugin includes it.

Coming soon

coming soonmacOSUSB serial and USB cameras.
coming soonWindowsUSB serial and USB cameras.
coming soonLinuxUSB serial and USB cameras.
coming sooniPadUSB cameras on iPadOS 17 and later. Apple does not let iPhone or iPad apps use USB serial adapters.
Tested on phones:
  • vivo
  • OPPO
  • Samsung
  • POCO
USB serial boards and chips:
  • ESP32
  • STM32
  • Nordic nRF
  • CP210x
  • CH340 / CH9102
  • FTDI
  • PL2303
  • CDC-ACM

Get started

Add it to your app in one line.

Each package's README on pub.dev explains every feature with examples.

  1. Add a package

    One command each. skio_core comes with them.

    $ flutter pub add skio_usb_serial
    $ flutter pub add skio_uvc_camera
  2. Try the example apps

    A serial terminal and a USB camera viewer, for an Android phone or Chrome.

    $ git clone https://github.com/skio-flutter/skio
    $ cd skio/packages/skio_usb_serial/example
    $ flutter run
  3. On the web, ask from a tap

    Browsers only list serial ports the user has picked. Call request() from a button tap.

    FilledButton(
      onPressed: () => UsbSerialPort.request(),
      child: const Text('Choose port'),
    )
  4. Test without hardware

    Swap the platform for a fake in your tests. Your own logic runs as plain Dart.

    import 'package:skio_usb_serial/platform_interface.dart';
    
    UsbSerialPlatform.instance = MyFakePlatform();

Principles

How skio is built.

A few rules every package follows.

  • Direct native bindingsjnigen, ffigen and js_interop. No MethodChannels, typed calls end to end.
  • Logic in DartQueues, framing, timeouts and retries are Dart code you can unit-test without a device.
  • Same API everywhereOne permission flow and one error type across every skio plugin.
  • Transports, not driversDevice protocols stay in your app, so any compatible device works.
  • No telemetryNo network access, no tracking. Your data stays where your app puts it.
  • Free and openBSD-3-Clause licence, free for personal and commercial use.

Build something that plugs in.

skio is open source and free to use. Stars, bug reports and pull requests all help it grow.