npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@capawesome/capacitor-flic

v0.1.1

Published

Unofficial Capacitor plugin for Flic smart buttons on Android and iOS.

Readme

Capacitor Flic Plugin

Unofficial Capacitor plugin for Flic smart buttons.[^1]

Features

  • 🔍 Pairing wizard: Pair new Flic buttons with a single call using the integrated scan wizard.
  • 🔗 Connection management: Connect, disconnect and forget buttons at any time.
  • 🖱️ Button events: Listen for single click, double click, hold, down and up events.
  • 📥 Queued events: Receive events that occurred while the button was disconnected.
  • 🔋 Battery level: Read the last known battery voltage of each button.
  • 🔐 Permissions: Check and request the required permissions with a single call.
  • 📦 CocoaPods & SPM: Supports CocoaPods and Swift Package Manager for iOS.
  • 🔁 Up-to-date: Always supports the latest Capacitor version.

Missing a feature? Just open an issue and we'll take a look!

Use Cases

The Flic plugin is typically used to trigger app actions with a physical button, for example:

  • Smart home control: Toggle lights, scenes or other devices with a single press.
  • Safety buttons: Send an alert or start a call when the user presses the button.
  • Time tracking: Start and stop timers without opening the app.
  • Accessibility: Provide a simple physical trigger for essential app actions.

Compatibility

| Plugin Version | Capacitor Version | Status | | -------------- | ----------------- | -------------- | | 0.x.x | >=8.x.x | Active support |

Installation

You can use our AI-Assisted Setup to install the plugin. Add the Capawesome Skills to your AI tool using the following command:

npx skills add capawesome-team/skills --skill capacitor-plugins

Then use the following prompt:

 Use the `capacitor-plugins` skill from `capawesome-team/skills` to install the `@capawesome/capacitor-flic` plugin in my project.

If you prefer Manual Setup, install the plugin by running the following commands and follow the platform-specific instructions below:

npm install @capawesome/capacitor-flic
npx cap sync

Android

The plugin already declares all required Bluetooth permissions in its manifest, so no additional configuration is required.

The flic2lib-android library is resolved from JitPack. The plugin already declares the JitPack repository in its build.gradle file. If your project restricts repository declarations to the settings file (e.g. via dependencyResolutionManagement with FAIL_ON_PROJECT_REPOS), add the JitPack repository to your settings.gradle file:

dependencyResolutionManagement {
    repositories {
        maven { url 'https://jitpack.io' }
    }
}

Variables

This plugin will use the following project variables (defined in your app’s variables.gradle file):

  • $flic2libVersion version of com.github.50ButtonsEach:flic2lib-android (default: 2.0.1)

iOS

Add the NSBluetoothAlwaysUsageDescription and NSBluetoothPeripheralUsageDescription keys to the ios/App/App/Info.plist file, which tells the user why the app needs access to Bluetooth:

<key>NSBluetoothAlwaysUsageDescription</key>
<string>The app needs access to Bluetooth to communicate with your Flic buttons.</string>
<key>NSBluetoothPeripheralUsageDescription</key>
<string>The app needs access to Bluetooth to communicate with your Flic buttons.</string>

If you want to receive button events while the app is in the background, you must also enable the Uses Bluetooth LE accessories background mode in the Signing & Capabilities section of your Xcode project and call initialize(...) with the iosBackground option set to true.

Configuration

No configuration required for this plugin.

Usage

Initialize the plugin

Call initialize() as soon as possible after the app has launched to minimize the delay of any pending button events:

import { Flic } from '@capawesome/capacitor-flic';

const initialize = async () => {
  await Flic.initialize({ iosBackground: true });
};

Pair a new button

To pair a new button, start a scan and press and hold the button for at least 6 seconds:

import { Flic, ScanStatus } from '@capawesome/capacitor-flic';

const pairButton = async () => {
  await Flic.addListener('scanStatusChanged', (event) => {
    if (event.status === ScanStatus.Discovered) {
      console.log('Button discovered. Keep holding it...');
    }
  });
  const { button } = await Flic.startScan();
  return button;
};

List paired buttons

import { Flic } from '@capawesome/capacitor-flic';

const getButtons = async () => {
  const { buttons } = await Flic.getButtons();
  return buttons;
};

Connect a button

After an app restart, each paired button must be connected again:

import { Flic } from '@capawesome/capacitor-flic';

const connectButtons = async () => {
  const { buttons } = await Flic.getButtons();
  for (const button of buttons) {
    await Flic.connectButtonById({ id: button.id });
  }
};

Listen for button events

import { Flic } from '@capawesome/capacitor-flic';

const addListeners = async () => {
  await Flic.addListener('buttonSingleClick', (event) => {
    console.log('Button was clicked', event);
  });
  await Flic.addListener('buttonDoubleClick', (event) => {
    console.log('Button was double clicked', event);
  });
  await Flic.addListener('buttonHold', (event) => {
    console.log('Button was held down', event);
  });
};

Forget a button

import { Flic } from '@capawesome/capacitor-flic';

const forgetButton = async (id: string) => {
  await Flic.forgetButtonById({ id });
};

Check and request permissions

import { Flic } from '@capawesome/capacitor-flic';

const checkPermissions = async () => {
  const permissionStatus = await Flic.checkPermissions();
  return permissionStatus;
};

const requestPermissions = async () => {
  const permissionStatus = await Flic.requestPermissions();
  return permissionStatus;
};

API

checkPermissions()

checkPermissions() => Promise<PermissionStatus>

Check the status of the permissions that are required to use Flic buttons.

On iOS, the Bluetooth permission is requested when initialize(...) is called.

Only available on Android and iOS.

Returns: Promise<PermissionStatus>

Since: 0.1.0


connectButtonById(...)

connectButtonById(options: ConnectButtonByIdOptions) => Promise<void>

Connect a button.

The returned promise resolves immediately. The connection is established as soon as the button is available and does not time out. Listen to the buttonConnected and buttonReady events to know when the button is ready to be used.

Only available on Android and iOS.

| Param | Type | | ------------- | ----------------------------------------------------------------------------- | | options | ConnectButtonByIdOptions |

Since: 0.1.0


disconnectButtonById(...)

disconnectButtonById(options: DisconnectButtonByIdOptions) => Promise<void>

Disconnect a button or cancel a pending connection.

Only available on Android and iOS.

| Param | Type | | ------------- | ----------------------------------------------------------------------------------- | | options | DisconnectButtonByIdOptions |

Since: 0.1.0


forgetButtonById(...)

forgetButtonById(options: ForgetButtonByIdOptions) => Promise<void>

Forget a button.

This removes the pairing with the button. To use the button again, it must be paired again using startScan().

Only available on Android and iOS.

| Param | Type | | ------------- | --------------------------------------------------------------------------- | | options | ForgetButtonByIdOptions |

Since: 0.1.0


getButtons()

getButtons() => Promise<GetButtonsResult>

Get all buttons that are currently paired with the app.

Only available on Android and iOS.

Returns: Promise<GetButtonsResult>

Since: 0.1.0


initialize(...)

initialize(options?: InitializeOptions | undefined) => Promise<void>

Initialize the plugin.

This method must be called before any other method. It is recommended to call this method as soon as possible after the app has launched to minimize the delay of any pending button events.

On iOS, this method triggers the Bluetooth permission prompt if the permission has not yet been granted.

Only available on Android and iOS.

| Param | Type | | ------------- | --------------------------------------------------------------- | | options | InitializeOptions |

Since: 0.1.0


requestPermissions()

requestPermissions() => Promise<PermissionStatus>

Request the permissions that are required to use Flic buttons.

On iOS, this method only returns the current permission status since the Bluetooth permission is requested when initialize(...) is called.

Only available on Android and iOS.

Returns: Promise<PermissionStatus>

Since: 0.1.0


startScan()

startScan() => Promise<StartScanResult>

Start scanning for new buttons to pair.

To pair a button, press and hold it for at least 6 seconds while scanning. The returned promise resolves with the paired button once the pairing has completed. Listen to the scanStatusChanged event to keep the user informed about the scan progress.

Only one scan can be running at a time.

Only available on Android and iOS.

Returns: Promise<StartScanResult>

Since: 0.1.0


stopScan()

stopScan() => Promise<void>

Stop an ongoing scan.

This rejects the pending startScan() call.

Only available on Android and iOS.

Since: 0.1.0


addListener('buttonConnected', ...)

addListener(eventName: 'buttonConnected', listenerFunc: (event: ButtonConnectedEvent) => void) => Promise<PluginListenerHandle>

Called when a button establishes a Bluetooth connection.

The button is not ready to be used until the buttonReady event is emitted.

Only available on Android and iOS.

| Param | Type | | ------------------ | ----------------------------------------------------------------------------------------- | | eventName | 'buttonConnected' | | listenerFunc | (event: ButtonConnectedEvent) => void |

Returns: Promise<PluginListenerHandle>

Since: 0.1.0


addListener('buttonConnectionFailed', ...)

addListener(eventName: 'buttonConnectionFailed', listenerFunc: (event: ButtonConnectionFailedEvent) => void) => Promise<PluginListenerHandle>

Called when a connection attempt to a button fails.

Only available on Android and iOS.

| Param | Type | | ------------------ | ------------------------------------------------------------------------------------------------------- | | eventName | 'buttonConnectionFailed' | | listenerFunc | (event: ButtonConnectionFailedEvent) => void |

Returns: Promise<PluginListenerHandle>

Since: 0.1.0


addListener('buttonDisconnected', ...)

addListener(eventName: 'buttonDisconnected', listenerFunc: (event: ButtonDisconnectedEvent) => void) => Promise<PluginListenerHandle>

Called when the Bluetooth connection with a button is lost.

Only available on Android and iOS.

| Param | Type | | ------------------ | ----------------------------------------------------------------------------------------------- | | eventName | 'buttonDisconnected' | | listenerFunc | (event: ButtonDisconnectedEvent) => void |

Returns: Promise<PluginListenerHandle>

Since: 0.1.0


addListener('buttonDoubleClick', ...)

addListener(eventName: 'buttonDoubleClick', listenerFunc: (event: ButtonEvent) => void) => Promise<PluginListenerHandle>

Called when a button is double clicked.

Only available on Android and iOS.

| Param | Type | | ------------------ | ----------------------------------------------------------------------- | | eventName | 'buttonDoubleClick' | | listenerFunc | (event: ButtonEvent) => void |

Returns: Promise<PluginListenerHandle>

Since: 0.1.0


addListener('buttonDown', ...)

addListener(eventName: 'buttonDown', listenerFunc: (event: ButtonEvent) => void) => Promise<PluginListenerHandle>

Called when a button is pressed down.

Only available on Android and iOS.

| Param | Type | | ------------------ | ----------------------------------------------------------------------- | | eventName | 'buttonDown' | | listenerFunc | (event: ButtonEvent) => void |

Returns: Promise<PluginListenerHandle>

Since: 0.1.0


addListener('buttonHold', ...)

addListener(eventName: 'buttonHold', listenerFunc: (event: ButtonEvent) => void) => Promise<PluginListenerHandle>

Called when a button is held down.

Only available on Android and iOS.

| Param | Type | | ------------------ | ----------------------------------------------------------------------- | | eventName | 'buttonHold' | | listenerFunc | (event: ButtonEvent) => void |

Returns: Promise<PluginListenerHandle>

Since: 0.1.0


addListener('buttonReady', ...)

addListener(eventName: 'buttonReady', listenerFunc: (event: ButtonReadyEvent) => void) => Promise<PluginListenerHandle>

Called when a button has been cryptographically verified after a connection and is ready to be used.

Only available on Android and iOS.

| Param | Type | | ------------------ | --------------------------------------------------------------------------------- | | eventName | 'buttonReady' | | listenerFunc | (event: ButtonReadyEvent) => void |

Returns: Promise<PluginListenerHandle>

Since: 0.1.0


addListener('buttonSingleClick', ...)

addListener(eventName: 'buttonSingleClick', listenerFunc: (event: ButtonEvent) => void) => Promise<PluginListenerHandle>

Called when a button is clicked once.

Only available on Android and iOS.

| Param | Type | | ------------------ | ----------------------------------------------------------------------- | | eventName | 'buttonSingleClick' | | listenerFunc | (event: ButtonEvent) => void |

Returns: Promise<PluginListenerHandle>

Since: 0.1.0


addListener('buttonUnpaired', ...)

addListener(eventName: 'buttonUnpaired', listenerFunc: (event: ButtonUnpairedEvent) => void) => Promise<PluginListenerHandle>

Called when the pairing with a button is no longer valid, for example because the button has been factory reset. In this case, the button must be forgotten using forgetButtonById(...) and then paired again.

Only available on Android and iOS.

| Param | Type | | ------------------ | --------------------------------------------------------------------------------------- | | eventName | 'buttonUnpaired' | | listenerFunc | (event: ButtonUnpairedEvent) => void |

Returns: Promise<PluginListenerHandle>

Since: 0.1.0


addListener('buttonUp', ...)

addListener(eventName: 'buttonUp', listenerFunc: (event: ButtonEvent) => void) => Promise<PluginListenerHandle>

Called when a button is released.

Only available on Android and iOS.

| Param | Type | | ------------------ | ----------------------------------------------------------------------- | | eventName | 'buttonUp' | | listenerFunc | (event: ButtonEvent) => void |

Returns: Promise<PluginListenerHandle>

Since: 0.1.0


addListener('scanStatusChanged', ...)

addListener(eventName: 'scanStatusChanged', listenerFunc: (event: ScanStatusChangedEvent) => void) => Promise<PluginListenerHandle>

Called when the status of an ongoing scan changes.

Only available on Android and iOS.

| Param | Type | | ------------------ | --------------------------------------------------------------------------------------------- | | eventName | 'scanStatusChanged' | | listenerFunc | (event: ScanStatusChangedEvent) => void |

Returns: Promise<PluginListenerHandle>

Since: 0.1.0


removeAllListeners()

removeAllListeners() => Promise<void>

Remove all listeners for this plugin.

Since: 0.1.0


Interfaces

PermissionStatus

| Prop | Type | Description | Since | | ---------------------- | ----------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | ----- | | bluetooth | PermissionState | The permission state of the Bluetooth permission. Only available on iOS. | 0.1.0 | | bluetoothConnect | PermissionState | The permission state of the BLUETOOTH_CONNECT permission. Only required on Android 12 and later. Only available on Android. | 0.1.0 | | bluetoothScan | PermissionState | The permission state of the BLUETOOTH_SCAN permission. Only required on Android 12 and later. Only available on Android. | 0.1.0 | | location | PermissionState | The permission state of the ACCESS_FINE_LOCATION permission. Only required on Android 11 and earlier. Only available on Android. | 0.1.0 |

ConnectButtonByIdOptions

| Prop | Type | Description | Since | | -------- | ------------------- | ----------------------------- | ----- | | id | string | The identifier of the button. | 0.1.0 |

DisconnectButtonByIdOptions

| Prop | Type | Description | Since | | -------- | ------------------- | ----------------------------- | ----- | | id | string | The identifier of the button. | 0.1.0 |

ForgetButtonByIdOptions

| Prop | Type | Description | Since | | -------- | ------------------- | ----------------------------- | ----- | | id | string | The identifier of the button. | 0.1.0 |

GetButtonsResult

| Prop | Type | Description | Since | | ------------- | --------------------- | --------------------------------------------------- | ----- | | buttons | Button[] | The buttons that are currently paired with the app. | 0.1.0 |

Button

| Prop | Type | Description | Since | | --------------------- | ----------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----- | | batteryVoltage | number | The last known battery voltage of the button in volts. If no battery sample has been taken yet, this property is not available. It is recommended to show a "change the battery soon" hint in your app once the voltage goes below 2.65. | 0.1.0 | | connectionState | ButtonConnectionState | The connection state of the button. | 0.1.0 | | firmwareVersion | number | The revision of the firmware currently running on the button. | 0.1.0 | | id | string | The identifier of the button on this device. On Android, this is the Bluetooth address of the button. On iOS, this is an identifier that is guaranteed to be the same for each button paired to a particular device. | 0.1.0 | | isReady | boolean | Whether or not the button has been cryptographically verified after a connection and is ready to be used. | 0.1.0 | | isUnpaired | boolean | Whether or not the pairing with the button is no longer valid, for example because the button has been factory reset. In this case, the button must be forgotten using forgetButtonById(...) and then paired again. | 0.1.0 | | name | string | The human readable name of the button that the user may change in the official Flic app. | 0.1.0 | | pressCount | number | The number of times the button has been clicked since it last booted. | 0.1.0 | | serialNumber | string | The serial number of the button that is printed on the backside of the button inside the battery hatch. | 0.1.0 | | uuid | string | The unique identifier of the button that is the same across devices and apps. | 0.1.0 |

InitializeOptions

| Prop | Type | Description | Default | Since | | ------------------- | -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------ | ----- | | iosBackground | boolean | Whether or not you intend to use the buttons while the app is in the background. If set to true, the Uses Bluetooth LE accessories background mode must be enabled in the app's capabilities. Only available on iOS. | false | 0.1.0 |

StartScanResult

| Prop | Type | Description | Since | | ------------ | ----------------------------------------- | --------------------------- | ----- | | button | Button | The button that was paired. | 0.1.0 |

PluginListenerHandle

| Prop | Type | | ------------ | ----------------------------------------- | | remove | () => Promise<void> |

ButtonConnectedEvent

| Prop | Type | Description | Since | | -------------- | ------------------- | ----------------------------- | ----- | | buttonId | string | The identifier of the button. | 0.1.0 |

ButtonConnectionFailedEvent

| Prop | Type | Description | Since | | -------------- | ------------------- | ------------------------------------------------------------- | ----- | | buttonId | string | The identifier of the button. | 0.1.0 | | message | string | The message that describes why the connection attempt failed. | 0.1.0 |

ButtonDisconnectedEvent

| Prop | Type | Description | Since | | -------------- | ------------------- | ----------------------------- | ----- | | buttonId | string | The identifier of the button. | 0.1.0 |

ButtonEvent

| Prop | Type | Description | Since | | --------------- | -------------------- | ---------------------------------------------------------------------------------------- | ----- | | buttonId | string | The identifier of the button. | 0.1.0 | | timestamp | number | The timestamp of the event in milliseconds since the Unix epoch. | 0.1.0 | | wasQueued | boolean | Whether or not the event was queued because it occurred before the button was connected. | 0.1.0 |

ButtonReadyEvent

| Prop | Type | Description | Since | | -------------- | ------------------- | ----------------------------- | ----- | | buttonId | string | The identifier of the button. | 0.1.0 |

ButtonUnpairedEvent

| Prop | Type | Description | Since | | -------------- | ------------------- | ----------------------------- | ----- | | buttonId | string | The identifier of the button. | 0.1.0 |

ScanStatusChangedEvent

| Prop | Type | Description | Since | | ------------ | ------------------------------------------------- | ----------------------- | ----- | | status | ScanStatus | The status of the scan. | 0.1.0 |

Type Aliases

PermissionState

'prompt' | 'prompt-with-rationale' | 'granted' | 'denied'

Enums

ButtonConnectionState

| Members | Value | Description | Since | | ------------------- | ---------------------------- | -------------------------------------------------------------------------------------------------------------------- | ----- | | Connected | 'CONNECTED' | The button is connected. | 0.1.0 | | Connecting | 'CONNECTING' | The button is disconnected but a pending connection is set. The button will connect as soon as it becomes available. | 0.1.0 | | Disconnected | 'DISCONNECTED' | The button is disconnected and no pending connection is set. | 0.1.0 | | Disconnecting | 'DISCONNECTING' | The button is connected but is attempting to disconnect. Only available on iOS. | 0.1.0 |

ScanStatus

| Members | Value | Description | Since | | ---------------------------- | ----------------------------------------- | -------------------------------------------------------------------------------------- | ----- | | AskToAcceptPairRequest | 'ASK_TO_ACCEPT_PAIR_REQUEST' | The user must accept the system pairing dialog to continue. Only available on Android. | 0.1.0 | | Connected | 'CONNECTED' | A button was found and a connection is being established. | 0.1.0 | | Discovered | 'DISCOVERED' | A button was discovered. | 0.1.0 | | Verified | 'VERIFIED' | The button has been cryptographically verified. Only available on iOS. | 0.1.0 |

FAQ

Which Flic buttons are supported?

The plugin supports Flic 2 buttons. For the Flic Duo, only the events of the big button are currently delivered.

Does the plugin receive button events while the app is in the background?

On Android, events are delivered as long as the app process is alive. Consider using the Android Foreground Service plugin to keep the app process alive. On iOS, enable the Uses Bluetooth LE accessories background mode and call initialize(...) with the iosBackground option set to true (see Installation).

Can I use this plugin with Ionic, React, Vue or Angular?

Yes, the plugin is framework-agnostic. It works in any Capacitor app regardless of the web framework, including Ionic with Angular, React, or Vue, as well as plain JavaScript projects.

Related Plugins

Newsletter

Stay up to date with the latest news and updates about the Capawesome, Capacitor, and Ionic ecosystem by subscribing to our Capawesome Newsletter.

Changelog

See CHANGELOG.md.

License

See LICENSE.

The bundled flic2lib binary is distributed under its own license from Shortcut Labs AB (see flic2lib-LICENCE.txt).

[^1]: This project is not affiliated with, endorsed by, sponsored by, or approved by Shortcut Labs AB or any of its affiliates or subsidiaries. "Flic" is a trademark of Shortcut Labs AB.