ble-ion-proxima
v0.0.1
Published
BLE Background Plugin
Readme
ble-ion-proxima
A high-performance Capacitor plugin for dual-role Bluetooth Low Energy (BLE) background proximity detection.
This plugin allows your Ionic/Capacitor app to act as both a BLE Broadcaster (Peripheral) and a BLE Scanner (Central) simultaneously, even when the app is completely killed or running in the background. It is specifically designed to bypass OS limitations and trigger Truecaller-style full-screen overlays (Android) or Local Notifications (iOS) when a specific proximity node is detected.
Features
- Dual Role: Broadcast and Scan simultaneously.
- True Background Execution: Android
BroadcastReceiverwakes up your killed app usingPendingIntent. iOS utilizes State Restoration and Local Notifications. - Custom Payloads: Transmit and receive custom device names directly via the
ServiceDatapayload, bypassing hardware name limitations. - Proximity Distance Estimation: Built-in RSSI-to-distance mathematical conversion.
Install
npm install ble-ion-proxima
npx cap syncSetup Configuration
Android
The plugin automatically injects the necessary permissions and receivers into your AndroidManifest.xml via Capacitor. However, to show popups when the app is in the background, you must explicitly request the Overlay permission from the user in your app:
import { BleDualRolePlugin } from 'ble-ion-proxima';
await BleDualRolePlugin.requestOverlayPermission();iOS
Add the following keys to your ios/App/App/Info.plist file to allow background Bluetooth execution and explain your privacy usages:
<key>NSBluetoothAlwaysUsageDescription</key>
<string>This app requires Bluetooth to detect nearby proximity nodes.</string>
<key>NSBluetoothPeripheralUsageDescription</key>
<string>This app needs to broadcast its presence to nearby devices.</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>Location is required for Bluetooth scanning.</string>
<key>UIBackgroundModes</key>
<array>
<string>bluetooth-central</string>
<string>bluetooth-peripheral</string>
</array>Usage Example
import { BleDualRolePlugin } from 'ble-ion-proxima';
// Request standard runtime permissions first
await BleDualRolePlugin.requestPermissions();
// Start Broadcasting your presence
await BleDualRolePlugin.startBroadcasting({
serviceUuid: '0000180D-0000-1000-8000-00805f9b34fb',
localName: 'Viroj Node'
});
// Start Scanning for other broadcasters in the background
await BleDualRolePlugin.startScanning({
serviceUuid: '0000180D-0000-1000-8000-00805f9b34fb',
notificationTitle: 'Node Found!', // Android Background Notification Title
notificationText: 'A device is nearby.' // Android Background Notification Text
});
// Listen for foreground discoveries (App is open)
BleDualRolePlugin.addListener('onDeviceDiscovered', (result) => {
console.log(`Found ${result.device.name} at ${result.device.distance} meters!`);
});
// Listen for background wakeups (App was killed but woke up due to BLE hit)
BleDualRolePlugin.addListener('onOverlayWakeup', (result) => {
// Show a custom Ionic Alert or modal here!
console.log(`Woke up by ${result.name} (UUID: ${result.uuid})`);
});API
requestPermissions()startScanning(...)stopScanning()startBroadcasting(...)stopBroadcasting()addListener('onDeviceDiscovered', ...)addListener('onOverlayWakeup', ...)requestOverlayPermission()- Interfaces
requestPermissions()
requestPermissions() => Promise<{ scan: string; advertise: string; }>Request necessary Bluetooth and Location runtime permissions (Required for Android 12+).
Returns: Promise<{ scan: string; advertise: string; }>
startScanning(...)
startScanning(options: { serviceUuid: string; environmentalFactor?: number; notificationTitle?: string; notificationText?: string; }) => Promise<void>Arm the native system to scan for peripherals matching a strict Service UUID.
| Param | Type |
| ------------- | -------------------------------------------------------------------------------------------------------------------------- |
| options | { serviceUuid: string; environmentalFactor?: number; notificationTitle?: string; notificationText?: string; } |
stopScanning()
stopScanning() => Promise<void>startBroadcasting(...)
startBroadcasting(options: { serviceUuid: string; localName: string; }) => Promise<void>Manually trigger the device to act as a Peripheral.
| Param | Type |
| ------------- | -------------------------------------------------------- |
| options | { serviceUuid: string; localName: string; } |
stopBroadcasting()
stopBroadcasting() => Promise<void>addListener('onDeviceDiscovered', ...)
addListener(eventName: 'onDeviceDiscovered', listenerFunc: (result: { device: BleDevice; }) => void) => Promise<PluginListenerHandle>Event listener fired when a device is found while the app is in the FOREGROUND.
| Param | Type |
| ------------------ | --------------------------------------------------------------------------------- |
| eventName | 'onDeviceDiscovered' |
| listenerFunc | (result: { device: BleDevice; }) => void |
Returns: Promise<PluginListenerHandle>
addListener('onOverlayWakeup', ...)
addListener(eventName: 'onOverlayWakeup', listenerFunc: (result: { macAddress: string; name?: string; uuid?: string; }) => void) => Promise<PluginListenerHandle>| Param | Type |
| ------------------ | --------------------------------------------------------------------------------------- |
| eventName | 'onOverlayWakeup' |
| listenerFunc | (result: { macAddress: string; name?: string; uuid?: string; }) => void |
Returns: Promise<PluginListenerHandle>
requestOverlayPermission()
requestOverlayPermission() => Promise<void>Interfaces
PluginListenerHandle
| Prop | Type |
| ------------ | ----------------------------------------- |
| remove | () => Promise<void> |
BleDevice
| Prop | Type |
| ------------------ | ------------------- |
| id | string |
| uuid | string |
| macAddress | string |
| name | string |
| rssi | number |
| distance | number |
| txPowerLevel | number |
| timestamp | number |
