Salta al contenuto principale

Guida ai sensori del dispositivo Capacitor: movimento, bussola, passi

Guida ai sensori del dispositivo Capacitor: leggi accelerometro, barometro, bussola, pedometro, sensori di luce e prossimità su iOS e Android, con i permessi.

Sensori dello smartphone come accelerometro, bussola e barometro utilizzati in un'app Capacitor

I sensori del dispositivo Capacitor sono disponibili tramite plugin piccoli e mirati: @capgo/capacitor-accelerometer per il movimento, @capgo/capacitor-barometer per la pressione atmosferica, @capgo/capacitor-compass per la direzione, @capgo/capacitor-pedometer per i passi, più plugin per luce, prossimità e shake. Ognuno segue lo stesso schema: verifica la disponibilità, richiedi il permesso se necessario, avvia gli aggiornamenti, ascolta e fermati quando hai finito. Questa guida copre ogni sensore con Capacitor 8 code, le differenze tra piattaforme che contano e le regole sulla batteria che tengono le app fuori dai guai.

Panoramica dei sensori

Sensore Plugin iOS Android Permesso
Accelerometro @capgo/capacitor-accelerometer Sì Sì iOS NSMotionUsageDescription
Barometro @capgo/capacitor-barometer Sì, con altitudine relativa Sì, solo pressione, su dispositivi con sensore Stringa utilizzo movimento iOS
Bussola @capgo/capacitor-compass Sì Sì, con eventi di precisione Posizione iOS quando in uso
Contapassi @capgo/capacitor-pedometer Passi, distanza, piani, ritmo, cadenza Passi Movimento iOS, Android ACTIVITY_RECOGNITION
Luce ambientale @capgo/capacitor-light-sensor Nessun API pubblico Sì Nessuna
Prossimità @capgo/capacitor-proximity Sì Sì Nessuna
Gesto shake @capgo/capacitor-shake Sì Sì Nessuna
Giroscopio / orientamento Web DeviceMotionEvent / DeviceOrientationEvent Sì Sì iOS requestPermission() nella WebView

Installa solo ciò che usi. Ogni plugin è leggero e meno stringhe di permesso significano meno domande in App Review.

bun add @capgo/capacitor-accelerometer @capgo/capacitor-compass @capgo/capacitor-pedometer
bunx cap sync

Setup iOS

Aggiungi le stringhe di utilizzo che servono ai tuoi sensori a ios/App/App/Info.plist:

<!-- Accelerometer, pedometer, barometer altitude -->
<key>NSMotionUsageDescription</key>
<string>Counts your steps and detects movement during workouts.</string>

<!-- Compass heading -->
<key>NSLocationWhenInUseUsageDescription</key>
<string>Shows which direction you are facing on the map.</string>

Spiega il vantaggio per l'utente con parole semplici. Testi generici come “Questa app richiede l'accesso al movimento” sono una causa frequente di rifiuto in App Review.

Configurazione Android

La maggior parte dei sensori non richiede permessi. Il plugin pedometer aggiunge ACTIVITY_RECOGNITION al manifest unificato, e su Android 10+ lo richiedi a runtime.

Se un sensore è essenziale, dichiara la feature hardware così Google Play nasconde la tua app ai dispositivi che non la supportano. Se è opzionale, dichiarala con required="false" e controlla la disponibilità a runtime:

<uses-feature android:name="android.hardware.sensor.barometer" android:required="false" />
<uses-feature android:name="android.hardware.sensor.stepcounter" android:required="false" />
<uses-feature android:name="android.hardware.sensor.compass" android:required="false" />

Accelerometro: movimento e inclinazione

L'accelerometro riporta l'accelerazione sugli assi x, y e z in G. Un telefono appoggiato in piano misura circa z = -1 oppure 1 a seconda della convenzione della piattaforma, perché la gravità è inclusa.

import { CapacitorAccelerometer } from '@capgo/capacitor-accelerometer';

const { isAvailable } = await CapacitorAccelerometer.isAvailable();
if (isAvailable) {
  await CapacitorAccelerometer.requestPermissions();

  const listener = await CapacitorAccelerometer.addListener('measurement', ({ x, y, z }) => {
    const tiltX = Math.atan2(x, Math.sqrt(y * y + z * z)) * (180 / Math.PI);
    ball.style.transform = `translateX(${tiltX * 3}px)`;
  });

  await CapacitorAccelerometer.startMeasurementUpdates();

  // later
  await CapacitorAccelerometer.stopMeasurementUpdates();
  await listener.remove();
}

Casi d'uso: controlli di inclinazione nei giochi, UI “lift to wake”, rilevamento cadute o impatti, intensità dell'attività. I dati grezzi sono rumorosi, quindi smussali con un filtro passa-basso prima di usarli:

const alpha = 0.2;
let smoothed = { x: 0, y: 0, z: 0 };

function lowPass(m: { x: number; y: number; z: number }) {
  smoothed = {
    x: smoothed.x + alpha * (m.x - smoothed.x),
    y: smoothed.y + alpha * (m.y - smoothed.y),
    z: smoothed.z + alpha * (m.z - smoothed.z),
  };
  return smoothed;
}

Non aggiornare il DOM a ogni campione. Salva l'ultimo valore e renderizzalo in un requestAnimationFrame loop.

Gesti di scuotimento

Per "scuoti per segnalare un bug" o "scuoti per annullare", non devi calibrare tu le soglie:

import { CapacitorShake } from '@capgo/capacitor-shake';

const handle = await CapacitorShake.addListener('shake', () => openFeedbackForm());

Giroscopio e orientamento del dispositivo

Non serve un plugin separato per la rotazione. La WebView lo espone già:

async function enableMotion() {
  // iOS 13+ requires a user gesture and explicit permission
  const DME = DeviceMotionEvent as unknown as { requestPermission?: () => Promise<'granted' | 'denied'> };
  if (typeof DME.requestPermission === 'function') {
    const result = await DME.requestPermission();
    if (result !== 'granted') return;
  }

  window.addEventListener('devicemotion', (e) => {
    const r = e.rotationRate; // alpha, beta, gamma in degrees per second
    if (r) updateRotation(r.alpha ?? 0, r.beta ?? 0, r.gamma ?? 0);
  });

  window.addEventListener('deviceorientation', (e) => {
    // alpha: 0-360 around z, beta: -180..180 front/back, gamma: -90..90 left/right
    updateOrientation(e.alpha, e.beta, e.gamma);
  });
}

document.querySelector('#enable-motion')!.addEventListener('click', enableMotion);

Chiama requestPermission da un tap su un pulsante, mai al caricamento della pagina, altrimenti iOS rifiuta la richiesta.

Bussola: direzione

import { CapgoCompass, CompassAccuracy } from '@capgo/capacitor-compass';

const status = await CapgoCompass.requestPermissions(); // iOS: location permission
if (status.compass === 'granted') {
  await CapgoCompass.addListener('headingChange', ({ value }) => {
    needle.style.transform = `rotate(${-value}deg)`;
  });

  await CapgoCompass.startListening({
    minInterval: 100,      // ms between events
    minHeadingChange: 2,   // degrees
  });

  // Android only: ask the user to calibrate when accuracy drops
  await CapgoCompass.addListener('accuracyChange', ({ accuracy }) => {
    calibrationHint.hidden = accuracy >= CompassAccuracy.MEDIUM;
  });
  await CapgoCompass.watchAccuracy();
}

// One-off reading
const { value } = await CapgoCompass.getCurrentHeading();

value è in gradi rispetto al nord magnetico, da 0 a 360. Cose da sapere:

  • Il magnetometro viene disturbato dai magneti nelle cover, nei laptop e nei supporti per auto. Mostra un suggerimento di calibrazione (muovi il telefono a forma di otto) quando Android segnala una bassa accuratezza.
  • Applica il throttling con minInterval e minHeadingChange piuttosto che in JavaScript. Risparmia traffico sul bridge.
  • Per una mappa che ruota con l'utente, combina heading e geolocalizzazione. Se ti serve la posizione a app in background, consulta il plugin di geolocalizzazione in background.

Pedometro: passi, distanza e piani

Il contapassi è un chip a basso consumo che conta in modo continuo, anche quando l'app non è in esecuzione.

import { CapacitorPedometer } from '@capgo/capacitor-pedometer';

const features = await CapacitorPedometer.isAvailable();
// { stepCounting, distance, pace, cadence, floorCounting }

const perm = await CapacitorPedometer.requestPermissions();
if (perm.activityRecognition !== 'granted') {
  // explain why and link to settings
}

// Steps today (start and end are required on iOS)
const startOfDay = new Date();
startOfDay.setHours(0, 0, 0, 0);
const today = await CapacitorPedometer.getMeasurement({
  start: startOfDay.getTime(),
  end: Date.now(),
});
console.log(today.numberOfSteps, today.distance, today.floorsAscended);

// Live updates during a walk
await CapacitorPedometer.addListener('measurement', (m) => {
  stepsEl.textContent = String(m.numberOfSteps ?? 0);
});
await CapacitorPedometer.startMeasurementUpdates();

Differenze tra piattaforme:

  • iOS (Core Motion) risponde a query storiche per circa gli ultimi sette giorni e fornisce anche distanza, piani, ritmo e cadenza sui dispositivi supportati.
  • Android riporta solo i passi. Il contatore hardware si azzera al riavvio, quindi non trattarlo come un totale a vita. Conserva il tuo baseline.

Per la storia a lungo termine, i totali giornalieri tra dispositivi o i dati da un orologio, leggi dal health store con @capgo/capacitor-health invece. Aggrega i passi da tutte le fonti in Apple Health e Health Connect. Il nostro Guida alla migrazione di Health Connect spiega la configurazione.

Barometro: pressione e altitudine

import { CapacitorBarometer } from '@capgo/capacitor-barometer';

const { isAvailable } = await CapacitorBarometer.isAvailable();
if (isAvailable) {
  await CapacitorBarometer.requestPermissions();
  await CapacitorBarometer.addListener('measurement', ({ pressure, relativeAltitude }) => {
    pressureEl.textContent = `${pressure.toFixed(1)} hPa`;
    altitudeEl.textContent = `${relativeAltitude.toFixed(1)} m`;
  });
  await CapacitorBarometer.startMeasurementUpdates();
}

pressure è in ettopascal su entrambe le piattaforme. relativeAltitude è la variazione in metri dall'inizio degli aggiornamenti, fornita solo da iOS. Su Android è sempre 0, quindi calcolala tu con la formula barometrica:

const P0 = 1013.25; // standard sea-level pressure in hPa
const altitudeMeters = (p: number) => 44330 * (1 - Math.pow(p / P0, 1 / 5.255));

let baseline: number | null = null;
function relativeAltitude(pressure: number) {
  baseline ??= altitudeMeters(pressure);
  return altitudeMeters(pressure) - baseline;
}

L'altitudine assoluta ricavata dalla pressione sbaglia di decine di metri, perché il meteo cambia la pressione al livello del mare. Le variazioni relative su pochi minuti sono accurate entro circa un metro, abbastanza per contare piani o salite. Molti Android economici non hanno il barometro, quindi controlla sempre isAvailable.

Sensore di luce ambientale (Android)

import { LightSensor } from '@capgo/capacitor-light-sensor';

const { available } = await LightSensor.isAvailable(); // always false on iOS
if (available) {
  await LightSensor.addListener('lightSensorChange', ({ illuminance }) => {
    document.body.classList.toggle('high-contrast', illuminance > 10_000); // bright sunlight
  });
  await LightSensor.start({ updateInterval: 500 });
}

Valori tipici: sotto i 10 lux è una stanza buia, qualche centinaio di lux è un ufficio, decine di migliaia è luce solare diretta. Usalo per una modalità lettura che si adatti alla stanza o per aumentare il contrasto all'aperto. Per cambiare la luminosità dello schermo vera e propria, abbinalo a @capgo/capacitor-brightness.

Sensore di prossimità

Il sensore di prossimità ti segnala quando qualcosa copre la parte superiore dello schermo, di solito l'orecchio dell'utente durante una chiamata.

import { CapacitorProximity } from '@capgo/capacitor-proximity';

const status = await CapacitorProximity.getStatus();
if (status.available) {
  await CapacitorProximity.enable();  // screen turns off when covered
}

// when the call or voice message ends
await CapacitorProximity.disable();

Su iOS questo attiva UIDevice.isProximityMonitoringEnabled, che spegne il display quando è coperto. Su Android il plugin ascolta il sensore di prossimità e abbassa la luminosità della finestra dell'app. Attivalo solo mentre è attiva una chiamata vocale, un messaggio vocale o la modalità walkie-talkie, così la guancia dell'utente non preme i tasti.

Regole pratiche per le app con sensori

  1. Verifica prima la disponibilità. I tablet spesso non hanno contapassi o barometro, e gli emulatori simulano quasi tutti i sensori. Nascondi le funzioni che non puoi supportare.
  2. Ferma gli aggiornamenti quando l'app non è visibile. Usa @capacitor/app, il cui appStateChange per fermare i listener quando l'app va in background e riavviarli al resume. I sensori attivi consumano la batteria e causano recensioni a una stella.
  3. Applica il throttling nel code nativo se il plugin lo permette (bussola minInterval, sensore di luce updateInterval), non in JavaScript.
  4. Chiedi il permesso nel giusto contesto. Richiedi l'accesso al movimento quando l'utente inizia un allenamento, non al primo avvio.
  5. Testa su hardware reale. I simulatori restituiscono valori costanti o sintetici. Testa almeno un telefono Android economico, dove i sensori sono assenti o rumorosi.
  6. Rispetta le regole sulla privacy. I dati di movimento e posizione sono considerati sensibili nelle etichette privacy dell'App Store e nel modulo Data safety di Play. Dichiara cosa raccogli.

Risoluzione problemi

Nessun evento su iOS: manca la stringa di utilizzo in Info.plist, oppure il permesso è stato negato. Controlla Impostazioni, Privacy e sicurezza, Movimento e fitness.

Pedometer restituisce 0 su Android: ACTIVITY_RECOGNITION è stato negato, oppure il dispositivo non ha un contapassi. Controlla isAvailable().stepCounting.

La bussola salta a caso: interferenza magnetica o mancata calibrazione. Monitora l'accuratezza su Android e mostra un suggerimento per la calibrazione.

relativeAltitude è sempre 0: previsto su Android. Calcolalo dalla pressione come mostrato sopra.

DeviceMotionEvent.requestPermission lancia: non è stato chiamato da un gesto dell'utente.

Report sul consumo della batteria: i listener continuano a girare in background. Fermali su appStateChange.

Rilascia in fretta le feature dei sensori

Soglie, fattori di smoothing e UI per i sensori richiedono di solito diversi cicli di tuning con utenti reali. Quella logica sta in JavaScript, quindi puoi regolarla con Live updates di Capgo senza una revisione dello store, mentre i nuovi plugin e le stringhe dei permessi passano da un build regolare. Se stai collegando sensori esterni come le fasce cardio, continua con la nostra guida per creare un monitor della frequenza cardiaca con Capacitor.

Live updates per le app Capacitor

Quando un bug nel web-layer è live, rilascia la fix tramite Capgo invece di aspettare giorni l'approvazione degli store. Gli utenti ricevono l'update in background, mentre le modifiche native restano nel normale processo di review.

Ultimi articoli dal blog

Capgo ti offre gli insight migliori che ti servono per creare un'app mobile davvero professionale.