Pour détecter l'état de réseau dans une application Capacitor , installez @capacitor/networkappeler Network.getStatus() pour l'état actuel, et vous abonner à networkStatusChange pour les mises à jour. Cela vous indique si le dispositif a une connexion et si elle est Wi-Fi ou cellulaire. Pour savoir si l'internet fonctionne vraiment, ou si la connexion est facturée, ajoutez une vérification de disponibilité ou @capgo/capacitor-network-diagnosticsCe guide couvre les trois couches avec Capacitor 8 code.
Les trois questions derrière « l'utilisateur est-il en ligne ? »
| Question | API | Remarques |
|---|---|---|
| Y a-t-il une interface réseau active ? | Network.getStatus().connected |
Rapide, événementiel, dit rien sur l'accès à l'internet |
| Quel genre de lien est-ce ? | connectionType |
wifi, cellular, none, unknown dans le plugin officiel |
| L’internet fonctionne-t-il vraiment ? | Vérification HTTP ou internetReachable |
Exige une requête ou une validation du système d'exploitation |
| Devrais-je éviter les téléchargements importants ? | expensive, constrained |
Réseaux à tarification et mode faible données sur iOS |
La plupart des bogues hors ligne proviennent de traiter la première ligne comme la troisième. Un Wi-Fi hôtel avec une page de connexion signalant connected: true while chaque API appelle le temps limite.
Installez le plugin Réseau
bun add @capacitor/network
bunx cap sync
Aucune configuration n'est nécessaire. Sur Android, le plugin ajoute ACCESS_NETWORK_STATE à l'ensemble du manifeste, une permission normale accordée à l'installation. iOS n'exige rien.
Lisez le statut actuel
import { Network } from '@capacitor/network';
const status = await Network.getStatus();
console.log(status.connected); // true or false
console.log(status.connectionType); // 'wifi' | 'cellular' | 'none' | 'unknown'
Appelez-l’au démarrage de l'application avant de décider de charger depuis la cache ou le réseau. Il retourne en quelques millisecondes car il lit l'état du système, il ne renvoie pas de trafic.
Écoutez les changements de réseau
import { Network, type ConnectionStatus } from '@capacitor/network';
import type { PluginListenerHandle } from '@capacitor/core';
let handle: PluginListenerHandle | undefined;
export async function watchNetwork(onChange: (s: ConnectionStatus) => void) {
onChange(await Network.getStatus());
handle = await Network.addListener('networkStatusChange', onChange);
}
export async function stopWatchingNetwork() {
await handle?.remove();
}
Deux détails pratiques :
- Annulez le déclenchement de l'événement. Quand on passe de Wi-Fi à réseau cellulaire, les deux plateformes peuvent signaler brièvement
noneAvant que le nouveau lien soit disponible. Un décalage de 1 à 2 seconde avant de montrer un "bannière hors ligne" évite les clignotements. - Supprimez les écouteurs lorsqu'un composant se démonte, ou vous exécuterez le callback plusieurs fois après les rechargements de chaud et les navigations.
hook de React
import { useEffect, useState } from 'react';
import { Network, type ConnectionStatus } from '@capacitor/network';
export function useNetworkStatus() {
const [status, setStatus] = useState<ConnectionStatus>({ connected: true, connectionType: 'unknown' });
useEffect(() => {
let timer: ReturnType<typeof setTimeout>;
const listener = Network.addListener('networkStatusChange', (s) => {
clearTimeout(timer);
timer = setTimeout(() => setStatus(s), s.connected ? 0 : 1500);
});
Network.getStatus().then(setStatus);
return () => {
clearTimeout(timer);
listener.then((l) => l.remove());
};
}, []);
return status;
}
Se connecter en ligne est appliqué immédiatement, se déconnecter attend 1,5 seconde. Le même modèle fonctionne comme un composant Vue ou un service Angular avec un BehaviorSubject.
Pourquoi « connecté » ne signifie pas en ligne
connected: true provenant de la pile de réseau de l'OS. Il reste vrai quand :
- le réseau Wi-Fi a un portail captif (aéroports, hôtels, trains)
- le routeur n'a pas de connexion en amont
- le DNS est cassé ou filtré
- un pare-feu ou VPN d'une entreprise bloque votre domaine API
- votre propre backend est en panne
La solution est une vérification d'accessibilité contre quelque chose que vous contrôlez :
export async function canReachApi(timeoutMs = 4000): Promise<boolean> {
const controller = new AbortController();
const timer = setTimeout(() => controller.abort(), timeoutMs);
try {
const res = await fetch('https://api.example.com/health', {
method: 'HEAD',
cache: 'no-store',
signal: controller.signal,
});
return res.ok;
} catch {
return false;
} finally {
clearTimeout(timer);
}
}
Exécutez-l’au démarrage de l'application, lorsque networkStatusChange rapports connected: trueet après qu'une requête a échoué. N'effectuez pas une requête toutes les quelques secondes, cela consomme la batterie et les données. Assurez-vous que l'endpoint de santé autorise l'origine de votre application dans CORS (capacitor://localhost sur iOS, https://localhost par défaut sur Android), ou utilisez CapacitorHttp pour l'envoyer depuis le code natif.
Obtenez un statut plus riche avec les diagnostics de réseau
@capgo/capacitor-network-diagnostics lit plus d'informations que l'OS connaît et peut exécuter des vérifications natives qui contournent CORS de WebView :
bun add @capgo/capacitor-network-diagnostics
bunx cap sync
import { NetworkDiagnostics } from '@capgo/capacitor-network-diagnostics';
const status = await NetworkDiagnostics.getNetworkStatus();
// {
// connected: true,
// connectionType: 'wifi' | 'cellular' | 'ethernet' | 'vpn' | 'other' | 'unknown' | 'none',
// internetReachable: true,
// expensive: false, // metered / cellular
// constrained: false, // iOS Low Data Mode
// captivePortal: false, // Android only
// details: { ... }
// }
Comment les champs correspondent au système d'exploitation :
| Champ | Android | iOS |
|---|---|---|
internetReachable |
NET_CAPABILITY_VALIDATED (Android a sondé Internet) |
Réfléchit à NWPathMonitor état de chemin |
expensive |
isActiveNetworkMetered() |
NWPath.isExpensive |
constrained |
Toujours false |
NWPath.isConstrained (Mode de données faible) |
captivePortal |
NET_CAPABILITY_CAPTIVE_PORTAL |
Non signalé |
vpn type |
Oui | Oui |
Sur Android, internetReachable C'est un signal fort car l'OS a déjà testé la connexion. Sur iOS, il est plus proche de connected, gardez donc la vérification HTTP pour les flux critiques.
Vérifications de disponibilité natives
const api = await NetworkDiagnostics.testUrl({
url: 'https://api.example.com/health',
method: 'HEAD',
timeoutMs: 4000,
});
// api.reachable, api.statusCode, api.durationMs, api.errorCode
const socket = await NetworkDiagnostics.testWebSocket({ url: 'wss://realtime.example.com' });
const port = await NetworkDiagnostics.testPort({ host: 'mqtt.example.com', port: 8883 });
Les requêtes natives ne sont pas soumises à CORS, vous pouvez donc tester les hôtes tiers également.
Un écran de "rapport de réseau" de support
Adaptez-vous aux connexions à tarification et à la mode de données faible
const report = await NetworkDiagnostics.runDiagnostics({
urls: [{ url: 'https://api.example.com/health' }, { url: 'https://cdn.example.com/ping' }],
websockets: [{ url: 'wss://realtime.example.com' }],
download: { url: 'https://cdn.example.com/1mb.bin', maxBytes: 1_048_576 },
packetLoss: { url: 'https://api.example.com/health', count: 5 },
});
console.log(report.issues); // human-readable list of problems
console.log(report.download?.mbps);
console.log(report.packetLoss?.lossPercent);
Respecter les limites de données est un gain rapide pour les évaluations dans les marchés où les données mobiles sont coûteuses :
Réagir aux connexions à tarification et à l'économie de données
Respecter les limites de données est un gain rapide pour les évaluations dans les marchés où les données mobiles sont chères.
export async function shouldPrefetchMedia() {
const s = await NetworkDiagnostics.getNetworkStatus();
if (!s.connected) return false;
if (s.constrained) return false; // user asked iOS to save data
if (s.expensive) return false; // cellular or metered Wi-Fi
return true;
}
Use it to decide on video autoplay, image quality, background sync, and large downloads. On Android, users can mark a Wi-Fi network as metered, so do not assume Wi-Fi is free.
Vérifiez la disponibilité du réseau
Un petit bandeau est plus clair que les requêtes qui échouent. En utilisant l'hook ci-dessus :
export function OfflineBanner() {
const { connected } = useNetworkStatus();
if (connected) return null;
return (
<div role="status" aria-live="polite" className="offline-banner">
You are offline. Changes will sync when you reconnect.
</div>
);
}
role="status" avec aria-live="polite" annonce la modification aux lecteurs d'écran. Pour les interfaces utilisateur spécifiques au framework, consultez notre guide à la création d'une écran hors ligne dans Vue, Angular et React.
Travail en file d'attente en ligne.
La détection est seulement la moitié du support hors ligne. Lorsque le statut devient hors ligne :
- Serve lit depuis le stockage local. Un base de données SQLite comme
@capgo/capacitor-fast-sqlgère mieux les grandes quantités de données quelocalStorage. - Enregistrer les actions de l'utilisateur dans une table d'outbox avec une date et une clé d'idempotence.
- Sur
networkStatusChangepasser à connecté, exécutezcanReachApi(), puis videz l'outbox dans l'ordre. - Réessayez les requêtes échouées avec un recul exponentiel, limité à quelques minutes.
Pour les téléchargements qui doivent survivre à la fermeture de l'application, les confiez à un téléchargeur natif plutôt qu'à fetch.
fallback réseau
@capacitor/network est également exécuté dans le navigateur, où il repose sur navigator.onLine et le online et offline événements. Cela signifie que votre code fonctionne en bun run dev et dans une PWA sans modifications, mais connectionType sera souvent unknown sur le web. Chrome's navigator.connection exposes effectiveType et saveData, Safari does not, so treat them as optional hints.
Troubleshooting
Le listener ne déclenche jamais sur iOS Simulator: le simulateur partage le réseau du Mac. Activez ou désactivez le Wi-Fi sur le Mac ou testez sur un appareil avec le mode avion.
connectionType est unknown sur un VPN: le plugin officiel ne signale que wifi, cellular, none et unknownUtilisez le plugin de diagnostics, qui renvoie vpn et ethernet.
. Utilisez le plugin de diagnostics, qui renvoie: déboguez la transition hors ligne comme indiqué ci-dessus.
La vérification de santé échoue sur le dispositif mais fonctionne dans le navigateur.: CORS. Autoriser capacitor://localhost et https://localhost, ou utilisez NetworkDiagnostics.testUrl, qui fonctionne nativement.
navigator.onLine est vrai tandis que le plugin indique hors ligne: confiez-vous au plugin. Certains Android WebViews ne se mettent pas à jour. navigator.onLine reliably.
Envoyer des correctifs hors ligne par voie aérienne
Gestion hors ligne est principalement du JavaScript : seuils, bannières, logique de réessai, règles de cache. , vous pouvez ajuster ceux-ci pour chaque utilisateur le même jour. Capgo télécharge les ensembles de mise à jour en arrière-plan et conserve la version actuelle si une téléchargement échoue, afin qu'une mauvaise connexion ne laisse jamais les utilisateurs avec une mise à jour partiellement installée., you can tune those for every user the same day. Capgo downloads update bundles in the background and keeps the current version if a download fails, so a bad connection never leaves users with a half-installed update. The docs de diagnostics réseau liste toutes les options.