Saltar al contenido

Empezando

  1. Instalar el paquete

    Ventana de terminal
    npm i @capgo/capacitor-ibeacon
  2. Sincronización con proyectos nativos

    Ventana de terminal
    npx cap sync

Agregue lo siguiente a su Info.plist:

<key>NSLocationWhenInUseUsageDescription</key>
<string>This app needs location access to detect nearby beacons</string>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>This app needs location access to monitor beacons in the background</string>
<key>NSBluetoothAlwaysUsageDescription</key>
<string>This app uses Bluetooth to detect nearby beacons</string>
<key>UIBackgroundModes</key>
<array>
<string>location</string>
</array>

Agregue lo siguiente a su AndroidManifest.xml:

<manifest>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
</manifest>

Importante: Para Android, debe integrar la biblioteca AltBeacon en su proyecto para que funcione la detección de balizas.

Agregue al build.gradle de su aplicación:

dependencies {
implementation 'org.altbeacon:android-beacon-library:2.20+'
}
import { CapacitorIbeacon } from '@capgo/capacitor-ibeacon';
// Define your beacon region
const beaconRegion = {
identifier: 'MyStore',
uuid: 'B9407F30-F5F8-466E-AFF9-25556B57FE6D',
major: 1, // Optional
minor: 2 // Optional
};
// Request "When In Use" permission
const requestPermission = async () => {
const { status } = await CapacitorIbeacon.requestWhenInUseAuthorization();
console.log('Permission status:', status);
// status: 'not_determined' | 'restricted' | 'denied' | 'authorized_always' | 'authorized_when_in_use'
};
// Request "Always" permission (for background monitoring)
const requestAlwaysPermission = async () => {
const { status } = await CapacitorIbeacon.requestAlwaysAuthorization();
console.log('Always permission status:', status);
};
// Check current authorization status
const checkPermission = async () => {
const { status } = await CapacitorIbeacon.getAuthorizationStatus();
console.log('Current status:', status);
};
// Check if Bluetooth is enabled
const checkBluetooth = async () => {
const { enabled } = await CapacitorIbeacon.isBluetoothEnabled();
if (!enabled) {
console.log('Please enable Bluetooth');
}
};
// Check if ranging is available
const checkRanging = async () => {
const { available } = await CapacitorIbeacon.isRangingAvailable();
console.log('Ranging available:', available);
};

El monitoreo detecta cuando ingresa o sale de una región de baliza. Esto funciona en segundo plano.

// Start monitoring
const startMonitoring = async () => {
await CapacitorIbeacon.startMonitoringForRegion({
identifier: 'MyStore',
uuid: 'B9407F30-F5F8-466E-AFF9-25556B57FE6D',
major: 1,
minor: 2
});
console.log('Started monitoring for beacons');
};
// Stop monitoring
const stopMonitoring = async () => {
await CapacitorIbeacon.stopMonitoringForRegion({
identifier: 'MyStore',
uuid: 'B9407F30-F5F8-466E-AFF9-25556B57FE6D'
});
};

La medición de distancia proporciona actualizaciones continuas sobre las balizas cercanas y sus distancias. Esto requiere que la aplicación esté en primer plano.

// Start ranging
const startRanging = async () => {
await CapacitorIbeacon.startRangingBeaconsInRegion({
identifier: 'MyStore',
uuid: 'B9407F30-F5F8-466E-AFF9-25556B57FE6D'
});
console.log('Started ranging beacons');
};
// Stop ranging
const stopRanging = async () => {
await CapacitorIbeacon.stopRangingBeaconsInRegion({
identifier: 'MyStore',
uuid: 'B9407F30-F5F8-466E-AFF9-25556B57FE6D'
});
};
import { PluginListenerHandle } from '@capacitor/core';
// Listen for ranging events (continuous distance updates)
const rangingListener: PluginListenerHandle = await CapacitorIbeacon.addListener(
'didRangeBeacons',
(data) => {
console.log('Beacons detected:', data.beacons);
data.beacons.forEach(beacon => {
console.log(`UUID: ${beacon.uuid}`);
console.log(`Major: ${beacon.major}, Minor: ${beacon.minor}`);
console.log(`Distance: ${beacon.accuracy}m`);
console.log(`Proximity: ${beacon.proximity}`); // immediate, near, far, unknown
console.log(`RSSI: ${beacon.rssi}`);
});
}
);
// Listen for region enter events
const enterListener: PluginListenerHandle = await CapacitorIbeacon.addListener(
'didEnterRegion',
(data) => {
console.log('Entered region:', data.region.identifier);
// Show welcome notification or trigger action
}
);
// Listen for region exit events
const exitListener: PluginListenerHandle = await CapacitorIbeacon.addListener(
'didExitRegion',
(data) => {
console.log('Exited region:', data.region.identifier);
// Trigger goodbye action
}
);
// Listen for region state changes
const stateListener: PluginListenerHandle = await CapacitorIbeacon.addListener(
'didDetermineStateForRegion',
(data) => {
console.log(`Region ${data.region.identifier}: ${data.state}`);
// state: 'inside' | 'outside' | 'unknown'
}
);
// Clean up listeners when done
const cleanup = () => {
rangingListener.remove();
enterListener.remove();
exitListener.remove();
stateListener.remove();
};

Convierta su dispositivo en un transmisor iBeacon.

// Start advertising
const startAdvertising = async () => {
await CapacitorIbeacon.startAdvertising({
uuid: 'B9407F30-F5F8-466E-AFF9-25556B57FE6D',
major: 1,
minor: 2,
identifier: 'MyBeacon',
measuredPower: -59 // Optional: calibrated power at 1 meter
});
console.log('Started advertising as iBeacon');
};
// Stop advertising
const stopAdvertising = async () => {
await CapacitorIbeacon.stopAdvertising();
};
import { CapacitorIbeacon } from '@capgo/capacitor-ibeacon';
import { PluginListenerHandle } from '@capacitor/core';
export class BeaconService {
private listeners: PluginListenerHandle[] = [];
async init() {
// Request permissions
const { status } = await CapacitorIbeacon.requestWhenInUseAuthorization();
if (status !== 'authorized_when_in_use' && status !== 'authorized_always') {
throw new Error('Location permission denied');
}
// Check Bluetooth
const { enabled } = await CapacitorIbeacon.isBluetoothEnabled();
if (!enabled) {
throw new Error('Bluetooth is not enabled');
}
// Set up event listeners
this.setupListeners();
}
private setupListeners() {
this.listeners.push(
await CapacitorIbeacon.addListener('didEnterRegion', (data) => {
console.log('Welcome! Entered:', data.region.identifier);
this.onEnterRegion(data.region);
})
);
this.listeners.push(
await CapacitorIbeacon.addListener('didExitRegion', (data) => {
console.log('Goodbye! Left:', data.region.identifier);
this.onExitRegion(data.region);
})
);
this.listeners.push(
await CapacitorIbeacon.addListener('didRangeBeacons', (data) => {
this.onRangeBeacons(data.beacons);
})
);
}
async startMonitoring(uuid: string, identifier: string, major?: number, minor?: number) {
await CapacitorIbeacon.startMonitoringForRegion({
identifier,
uuid,
major,
minor
});
}
async startRanging(uuid: string, identifier: string) {
await CapacitorIbeacon.startRangingBeaconsInRegion({
identifier,
uuid
});
}
private onEnterRegion(region: any) {
// Handle region entry (e.g., show notification, trigger content)
console.log('Entered beacon region:', region);
}
private onExitRegion(region: any) {
// Handle region exit
console.log('Left beacon region:', region);
}
private onRangeBeacons(beacons: any[]) {
// Process beacon distances
const nearestBeacon = beacons.reduce((nearest, beacon) => {
return beacon.accuracy < nearest.accuracy ? beacon : nearest;
}, beacons[0]);
if (nearestBeacon) {
console.log('Nearest beacon:', nearestBeacon);
this.handleProximity(nearestBeacon);
}
}
private handleProximity(beacon: any) {
switch (beacon.proximity) {
case 'immediate': // < 0.5m
console.log('Very close to beacon');
break;
case 'near': // 0.5m - 3m
console.log('Near beacon');
break;
case 'far': // > 3m
console.log('Far from beacon');
break;
case 'unknown':
console.log('Distance unknown');
break;
}
}
cleanup() {
this.listeners.forEach(listener => listener.remove());
this.listeners = [];
}
}

Inicie el monitoreo de una región de baliza. Activa eventos al entrar/salir.

interface BeaconRegion {
identifier: string;
uuid: string;
major?: number;
minor?: number;
notifyEntryStateOnDisplay?: boolean;
}
await CapacitorIbeacon.startMonitoringForRegion(options);

Detener el monitoreo de una región de baliza.

await CapacitorIbeacon.stopMonitoringForRegion(options);

Comience a localizar balizas en una región para obtener actualizaciones continuas de distancia.

await CapacitorIbeacon.startRangingBeaconsInRegion(options);

Detener el alcance de las balizas en una región.

await CapacitorIbeacon.stopRangingBeaconsInRegion(options);

Comience a anunciar el dispositivo como un iBeacon (solo iOS).

interface BeaconAdvertisingOptions {
uuid: string;
major: number;
minor: number;
identifier: string;
measuredPower?: number; // Calibrated power at 1 meter
}
await CapacitorIbeacon.startAdvertising(options);

Deje de anunciar el dispositivo como un iBeacon.

await CapacitorIbeacon.stopAdvertising();

Solicite autorización de ubicación “Cuando esté en uso”.

const result = await CapacitorIbeacon.requestWhenInUseAuthorization();
// Returns: { status: string }

Solicite autorización de ubicación “Siempre” (requerida para el monitoreo en segundo plano).

const result = await CapacitorIbeacon.requestAlwaysAuthorization();
// Returns: { status: string }

Obtenga el estado de autorización de ubicación actual.

const result = await CapacitorIbeacon.getAuthorizationStatus();
// Returns: { status: 'not_determined' | 'restricted' | 'denied' | 'authorized_always' | 'authorized_when_in_use' }

Compruebe si Bluetooth está habilitado.

const result = await CapacitorIbeacon.isBluetoothEnabled();
// Returns: { enabled: boolean }

Compruebe si el alcance está disponible en el dispositivo.

const result = await CapacitorIbeacon.isRangingAvailable();
// Returns: { available: boolean }

Habilite el filtrado ARMA para cálculos de distancia (solo Android).

await CapacitorIbeacon.enableARMAFilter({ enabled: true });

Se dispara cuando se detectan balizas durante el alcance.

interface RangingEvent {
region: BeaconRegion;
beacons: Beacon[];
}
interface Beacon {
uuid: string;
major: number;
minor: number;
rssi: number; // Signal strength
proximity: 'immediate' | 'near' | 'far' | 'unknown';
accuracy: number; // Distance in meters
}

Se dispara al ingresar a una región de baliza monitoreada.

interface RegionEvent {
region: BeaconRegion;
}

Se dispara al salir de una región de baliza monitoreada.

interface RegionEvent {
region: BeaconRegion;
}

Se activa cuando se determina el estado de la región.

interface StateEvent {
region: BeaconRegion;
state: 'inside' | 'outside' | 'unknown';
}
  • inmediato: Muy cerca (< 0.5 meters)
  • near: Relatively close (0.5 - 3 meters)
  • far: Further away (> 3 metros)
  • desconocido: No se puede determinar la distancia
  1. Solicite los permisos adecuados

    • Utilice “Cuando esté en uso” para funciones de primer plano
    • Solicite “Siempre” solo si necesita monitoreo en segundo plano
    • Explique claramente por qué necesita acceso a la ubicación.2. Manejar el estado de Bluetooth
    const { enabled } = await CapacitorIbeacon.isBluetoothEnabled();
    if (!enabled) {
    // Prompt user to enable Bluetooth
    }
  2. Optimización de la batería

    • Use monitoreo en lugar de rango cuando sea posible (más eficiencia de batería)
    • Dejar de realizar rangos cuando no sea necesario activamente
    • Considere el uso de rangos mayores/menores más grandes para reducir el procesamiento
  3. Manejo de errores

    try {
    await CapacitorIbeacon.startMonitoringForRegion(region);
    } catch (error) {
    console.error('Failed to start monitoring:', error);
    }
  4. Limpiar a los oyentes Elimine siempre los detectores de eventos cuando el componente se desmonte para evitar pérdidas de memoria.

  • Requiere iOS 10.0+
  • Utiliza el marco nativo CoreLocation
  • Admite monitoreo en segundo plano con permiso “Siempre”
  • Puede anunciarse como iBeacon usando CoreBluetooth
  • El rango requiere que la aplicación esté en primer plano
  • Requiere Android 6.0 (API 23)+
  • Utiliza la biblioteca AltBeacon
  • Requiere permisos de ubicación aunque las balizas usen Bluetooth
  • La supervisión en segundo plano requiere ACCESS_BACKGROUND_LOCATION (Android 10+)
  • No se puede anunciar como iBeacon (limitación de hardware en la mayoría de los dispositivos)
  • No compatible con la plataforma web
  1. Marketing de proximidad: active notificaciones o contenido cuando los usuarios se acerquen a su tienda.
  2. Navegación interior: guía a los usuarios a través de edificios utilizando puntos de referencia de balizas
  3. Seguimiento de asistencia: regístrese automáticamente cuando los usuarios ingresan a una ubicación
  4. Seguimiento de activos: monitorear el movimiento de equipos o inventario
  5. Visitas a museos: proporcione información contextual a medida que los visitantes se acerquen a las exhibiciones.
  6. Hogar inteligente: activa automatizaciones según la presencia de la habitación
  • Asegúrese de que Bluetooth esté habilitado
  • Verificar que se concedan los permisos de ubicación
  • Verifique que el UUID de la baliza coincida exactamente (distingue entre mayúsculas y minúsculas)
  • Confirmar que la baliza esté encendida y transmitiendo.
  • Pruebe primero sin filtros mayores/menores

La supervisión en segundo plano no funciona

Section titled “La supervisión en segundo plano no funciona”
  • Asegúrese de que se conceda el permiso de ubicación “Siempre”
  • Agregue location a UIBackgroundModes (iOS)
  • Solicitar ACCESS_BACKGROUND_LOCATION (Android 10+)
  • Nota: iOS puede retrasar las devoluciones de llamadas en segundo plano para ahorrar batería
  • La baliza RSSI varía según el entorno (paredes, interferencias)
  • Utilice múltiples balizas para la triangulación.
  • Calibrar la potencia medida a 1 metro de la baliza.
  • Habilite el filtrado ARMA en Android para valores más suaves