iOS stops background location updates because it suspends your app, not because Core Location fails. Unless the app declares the location background mode, enables background updates on its CLLocationManager, and starts them while it is still in the foreground, iOS freezes the process a few seconds after the user leaves and queues or drops the fixes. This guide lists every cause we see in Capacitor apps, with the fix for each, and shows how @capgo/background-geolocation gère les mises à jour.
How iOS traite une application en arrière-plan
Lorsque l'utilisateur fait glisser la page d'accueil ou verrouille le téléphone, iOS accorde à l'application une courte fenêtre, puis la suspend. Une application suspendue n'obtient pas de temps CPU. Pour une application Capacitor cela signifie que la partie native et la WebView s'arrêtent, donc votre callback JavaScript s'arrête également.
Apple fait une exception pour les applications qui utilisent activement la localisation. Si l'application est configurée pour la localisation en arrière-plan et a une session de localisation active démarrée en mode avant-plan, iOS la maintient en cours d'exécution et continue de livrer des mises à jour. Tout ce qui suit concerne le respect de ce contrat, et les cas où le système le brise intentionnellement.
Raison 1 : le mode de localisation en arrière-plan manque
Sans location en UIBackgroundModes, aucune quantité de code ne fera continuer les mises à jour. Ajoutez-l’à ios/App/App/Info.plist:
<key>UIBackgroundModes</key>
<array>
<string>location</string>
</array>
On peut également l'activer dans Xcode sous Signature & Capacités, Modes de fond, Mises à jour de localisation. Il s'agit d'une clé plist, pas d'un droit, donc aucune modification de profil de provisionnement n'est nécessaire.
La propriété native derrière cela est allowsBackgroundLocationUpdates. En la définissant sur true sans le mode de fond dans la plist fait planter l'application. Le plugin Capgo la définit pour vous lorsque vous passez backgroundMessage à start()Alors, la clé plist doit être présente avant la livraison.
La vérification des App Review vérifie que le mode arrière-plan est justifié. Expliquez dans les notes de revue quelles fonctionnalités l'utilisent et assurez-vous que la fonctionnalité est visible pour le réviseur.
Cause 2 : les mises à jour ont été démarrées depuis l'arrière-plan
Apple’s rule: background updates continue if they were started while the app was in the foreground. Trying to start a session from a silent push, a background fetch or a BGTaskScheduler task does not work for standard location updates.
Start tracking from a user action or on app resume:
import { App } from '@capacitor/app';
import { BackgroundGeolocation } from '@capgo/background-geolocation';
let tracking = false;
export async function startTracking() {
if (tracking) return;
tracking = true;
await BackgroundGeolocation.start(
{
backgroundMessage: 'Recording your route',
backgroundTitle: 'Route recording',
requestPermissions: true,
distanceFilter: 10,
url: 'https://api.example.com/v1/points',
},
(location, error) => {
if (error) return console.error(error);
if (location) console.log(location.latitude, location.longitude);
},
);
}
// Re-arm when the user comes back, if the session should be active
App.addListener('appStateChange', ({ isActive }) => {
if (isActive && shouldBeTracking()) startTracking();
});
declare function shouldBeTracking(): boolean;
Raison 3 : backgroundMessage n'a pas été fourni
Ceci est spécifique au plugin Capgo et est le rapport de bug le plus courant. backgroundMessage is undefined, the plugin configures the location manager for foreground use only: allowsBackgroundLocationUpdates stays false Passer un message sur les deux plateformes. Sur Android, il devient également le texte de la notification de service en avant-plan.
La raison 4 : un niveau d'autorisation incorrect, ou Autoriser une fois
Beaucoup de développeurs pensent qu'ils ont besoin de Toujours pour suivre en arrière-plan. Ils n'en ont pas besoin. Apple documente que l'application avec l'autorisation Lorsque en cours d'utilisation continue à fonctionner en arrière-plan tout en ayant des services de localisation actifs, tant que les mises à jour en arrière-plan sont activées.
Il importe toujours pour autre chose : redémarrer une application arrêtée. Seuls les suivi de région, les changements significatifs de localisation et les visites peuvent redémarrer une application, et uniquement avec Toujours.
Deux choix discrets des utilisateurs cassent la traçabilité de fond.
- Autoriser une fois. C'est un accord temporaire Lorsque en cours d'utilisation qui expire lorsque l'application cesse d'être utilisée. La prochaine session commence à partir de « non déterminé » à nouveau.
- Tout en cours d'utilisation, puis Demande toujours non affichée. Lorsque vous demandez Toujours, iOS peut montrer le prompt de mise à niveau plus tard, à un moment qu'il choisit, souvent lorsque l'application n'est pas sur l'écran.
Vérifiez l'état réel avant de démarrer une session :
import { BackgroundGeolocation } from '@capgo/background-geolocation';
const status = await BackgroundGeolocation.checkPermissions();
if (status.location !== 'granted') {
await BackgroundGeolocation.requestPermissions({ permissions: ['location'] });
}
if (status.backgroundLocation === 'when_in_use') {
// Background tracking still works for standard updates.
// Explain why Always helps if you also rely on geofences.
}
Sur iOS, backgroundLocation retourne when_in_use or granted / alwaysPour cela, vous pouvez afficher l'explication appropriée au lieu de deviner.
Cause 5 : Core Location met automatiquement les mises à jour en pause.
CLLocationManager.pausesLocationUpdatesAutomatically par défaut true. Lorsque iOS décide que l'utilisateur ne bouge pas, il met en pause les mises à jour pour économiser la batterie. Pour une application Utilisation en cours, une pause met fin à l'accès à la localisation jusqu'à ce que l'application soit relancée, et Core Location ne reprend pas la charge de lui-même.
Le plugin Capgo défini pausesLocationUpdatesAutomatically = false à l'intérieur de son code natif, donc celui-ci est géré. Si vous écrivez votre propre code natif, ou utilisez un autre plugin, vérifiez cette propriété en premier.
Cause 6 : le dispositif est stationnaire et le filtre est large
Avec un distanceFilter de 50 mètres, un téléphone posé sur un bureau ne produit aucune mise à jour. Cela ressemble à « suivi arrêté » dans vos journaux, mais c'est fonctionnel comme conçu.
- Si vous avez besoin de cœur battant en station, utilisez un petit ou zéro
distanceFilter. - Utilisez
minIntervalMspour limiter la fréquence des POST natifs envoyés, plutôt qu'un grand filtre de distance.
await BackgroundGeolocation.start(
{
backgroundMessage: 'Vehicle tracking active',
distanceFilter: 0,
minIntervalMs: 120_000, // at most one native POST every 2 minutes
url: 'https://api.example.com/v1/vehicle-points',
},
() => {},
);
7ème cause : Localisation précise est désactivée
Since iOS 14 users can turn off Precise Location for your app. You still get updates, but they are approximate (several kilometers) and arrive much less often. Detect this in your data (large accuracy values) and explain to the user why precise location matters for your feature. If you ship a delivery or fitness app, show this in onboarding, not after a bad trip.
La cause 8 : l'utilisateur a terminé l'application
If the user swipes the app away in the app switcher, iOS stops standard location updates. No plugin can keep them running. This is a common surprise for teams coming from Android, where a foreground service can keep running after the task is removed.
Options:
- N'arrêtez pas l'application pendant une session. La plupart des applications de flotte le recommandent lors de l'inscription.
- Envoyez un rappel pour rappeler à l'utilisateur de rouvrir l'application lorsque votre serveur cesse de recevoir des points pour une session.
- Envoyer une notification pour rappeler à l'utilisateur de rouvrir l'application lorsque votre serveur cesse de recevoir des points pour une session.
La raison 9 : Le JavaScript n'est pas exécuté même si le natif est
A subtle one. Native code can receive a location while the WebView is suspended, or while it is still alive but not processing timers or network calls quickly. If you send points with fetch ils peuvent arriver en retard ou pas du tout.
Utilisez l'option du plugin. url Chaque point est envoyé à partir de native code avec le même JSON que le Location le type plus "source": "native", independent of the WebView. Keep the callback for UI updates only. Delivery is best effort with no on-disk queue, so if you cannot lose a point, also store it locally when the callback fires and reconcile later.
Pour les tâches de fond au-delà de la localisation, lisez comment les tâches de fond fonctionnent dans Capacitor et voyez @capgo/capacitor-background-task.
Causes 10 : Mode de faible consommation et état thermique
Le Mode de faible consommation réduit l'activité de fond sur l'ensemble du système. La localisation fonctionne toujours, mais d'autres choses dont votre session dépend (réessaisies de réseau, mise à jour de fond) ralentissent. Testez avec le Mode de faible consommation activé avant de signer un lancement.
Le bleu indicateur
Lorsqu'une application avec autorisation When In Use utilise la localisation en arrière-plan, iOS affiche une pilule bleue dans la barre d'état. Le plugin Capgo défini showsBackgroundLocationIndicator à true Pour les sessions de fond, ce qui est attendu par les utilisateurs et recherché par les réviseurs. N'essayez pas de le cacher, les utilisateurs y ont confiance.
Un plan de test qui attrape ces bogues
Le testage sur simulateur n'est pas suffisant pour la localisation de fond. Utilisez un iPhone réel et :
- Configurez une configuration de version finale, et non seulement de débogage. Les builds de débogage liés à Xcode reçoivent un traitement différent de la durée de vie.
- Démarrez une session en mode avant-plan, verrouillez l'appareil, marchez ou conduisez pendant 20 minutes.
- Répétez avec « Autoriser une fois », avec Localisation précise désactivée, avec le mode économie d'énergie activé.
- Vérifiez vos journaux de serveur pour
source: "native"seulement vos journaux en application. - Fermez l'application et confirmez que vous souhaitez continuer lors du prochain lancement.
Si vous avez besoin d'un ID de device pour des builds ad hoc, le rechercheur d'ID UDID iOS le récupère à partir de Safari. Si vous n'avez pas un Mac avec Xcode 26 pour les builds, Capgo Développement peut produire des builds iOS signés dans le cloud.
Liste de vérification de dépannage
| Symptôme | Cause probable | Réparation |
|---|---|---|
| S'arrête après verrouillage | Non location mode d'arrière-plan ou non backgroundMessage |
Ajoutez la clé plist et passez-la backgroundMessage |
| Crash à l'ouverture | allowsBackgroundLocationUpdates sans mode d'arrière-plan |
Ajoutez UIBackgroundModes → location |
| Marche une fois, puis plus | L'utilisateur a choisi Autoriser une fois | Expliquez et demandez à nouveau, ou envoyez à openSettings() |
| S'arrête quand le véhicule est garé | Élevé distanceFilter |
Réduisez-le, utilisez minIntervalMs |
| Points éloignés, faible précision | Localisation précise désactivée | Demandez à l'utilisateur de l'activer |
| S'arrête après un swipe | L'utilisateur a terminé l'application | Attendu sur iOS, utilisez les géofences pour le redémarrage |
| Native obtient des points, le serveur ne le fait pas | JavaScript fetch en rappel |
Utilisez le url option |
Corrections de livraison
La plupart de ces corrections touchent Info.plist ou la configuration native, elles nécessitent donc une nouvelle mise à jour de l'App Store. Les parties JavaScript, telles que les explications de permission, le contenu de démarrage et la logique de réessai, peuvent être livrées aux utilisateurs existants avec Capgo mises à jour en direct une fois la mise à jour native est sortie.
Si vous vous décidez entre les plugins, notre comparaison de Transistorsoft et le plugin gratuit Capgo abordent les compromis.