-
Notifications
You must be signed in to change notification settings - Fork 0
Background Sync
wklm edited this page Mar 18, 2026
·
1 revision
Background Sync lets your web app register BLE work that continues through the iOS companion app when Safari is not in the foreground.
This page covers the public API and usage model only.
navigator.webble.backgroundSync- keep a granted BLE device connected in the background
- show iOS notifications when a characteristic value changes
- show iOS notifications when matching BLE beacons are detected
- manage active registrations for the current origin
Request notification permission from a direct user gesture:
button.addEventListener('click', async () => {
const permission = await navigator.webble.backgroundSync.requestPermission();
if (permission === 'granted') {
console.log('Notifications enabled');
}
});requestPermission() must be called from a user gesture.
const keepAlive = await navigator.webble.backgroundSync.requestBackgroundConnection({
deviceId: device.id,
});Use this when you want the companion app to maintain the BLE connection for future background work.
const alerts = await navigator.webble.backgroundSync.registerCharacteristicNotifications({
deviceId: device.id,
serviceUUID: 'heart_rate',
characteristicUUID: 'heart_rate_measurement',
cooldownSeconds: 30,
template: {
title: 'Heart rate update',
body: '{{device.name}} sent {{value.hex}} at {{timestamp}}',
url: 'https://example.com/monitor',
},
});const beacons = await navigator.webble.backgroundSync.registerBeaconScanning({
filters: [{ services: ['0000fee0-0000-1000-8000-00805f9b34fb'] }],
template: {
title: 'Nearby BLE beacon',
body: '{{device.name}} is advertising nearby',
url: 'https://example.com/beacons',
},
});At least one services filter is required.
const registrations = await navigator.webble.backgroundSync.getRegistrations();
for (const registration of registrations) {
console.log(registration.id, registration.type);
}
await alerts.update({
body: 'Latest payload from {{device.name}}: {{value.hex}}',
});
await beacons.unregister();BackgroundRegistration.update() is supported for notification and beacon registrations. Connection registrations do not support update().
{{value.utf8}}{{value.hex}}{{value.int16be}}{{value.int32be}}{{timestamp}}{{device.name}}{{device.id}}
Interpolated values are sanitized before delivery.
-
template.urlmust usehttps:// -
template.urlmust stay on the same origin as the page that created the registration -
deviceIdmust come from a device previously granted through your site flow - quotas: 50 intents per origin, 200 global registrations
- registrations expire after 30 days
- notification cooldown defaults to 5 seconds where supported
const permission = await navigator.webble.backgroundSync.requestPermission();
if (permission !== 'granted') {
throw new Error('Enable notifications to use background BLE alerts');
}
const device = await navigator.bluetooth.requestDevice({
filters: [{ services: ['heart_rate'] }],
});
await device.gatt.connect();
const keepAlive = await navigator.webble.backgroundSync.requestBackgroundConnection({
deviceId: device.id,
});
const heartRateAlerts = await navigator.webble.backgroundSync.registerCharacteristicNotifications({
deviceId: device.id,
serviceUUID: 'heart_rate',
characteristicUUID: 'heart_rate_measurement',
cooldownSeconds: 30,
template: {
title: 'Heart rate update',
body: '{{device.name}} sent {{value.hex}} at {{timestamp}}',
url: 'https://example.com/monitor',
},
});
const activeRegistrations = await navigator.webble.backgroundSync.getRegistrations();
console.log(activeRegistrations.map(({ id, type }) => ({ id, type })));
await heartRateAlerts.update({
body: 'Latest payload from {{device.name}}: {{value.hex}}',
});- Hosted docs: https://ioswebble.com/docs#api-background-sync
- Public API reference source: https://github.com/wklm/ioswebble-sdk/blob/main/README.md