要检测 Capacitor 应用程序的网络状态,请安装 @capacitor/network调用 Network.getStatus() 获取当前状态,并订阅 networkStatusChange 为了获取更新。它告诉你设备是否有连接,并且是否是Wi-Fi还是蜂窝网络。要知道互联网是否实际工作,还是连接是计量的,需要添加可达性检查或 @capgo/capacitor-network-diagnostics本指南涵盖了所有三个层次,包括Capacitor 8 code。
“用户是否在线?”背后的三个问题
| 问题 | API | 注意 |
|---|---|---|
| 是否有活动的网络接口? | Network.getStatus().connected |
快速、事件驱动的,但没有说到互联网访问 |
| 是什么类型的连接? | connectionType |
wifi, cellular, none, unknown 在官方插件中 |
| 互联网是否实际工作? | HTTP检查或 internetReachable |
需要请求或操作系统验证 |
| 是否应该避免大型下载? | expensive, constrained |
带有计量的网络和 iOS 低数据模式 |
大多数离线错误来自于将第一行视为第三行。一个需要登录的酒店 Wi-Fi 网络会报告 connected: true 每次 API 调用都会超时。
安装网络插件
bun add @capacitor/network
bunx cap sync
不需要任何配置。 在 Android 上,插件会添加 ACCESS_NETWORK_STATE 到合并的清单中,一个正常的权限在安装时被授予。 iOS 不需要任何配置。
读取当前状态
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'
在应用启动时调用它,决定是否从缓存或网络加载。它在几毫秒内返回,因为它读取操作系统状态,而不发送流量。
监听网络变化
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();
}
两个实用细节:
- 延迟事件。 切换到蜂窝网络时,两种平台可能会在新连接建立之前短暂地报告网络状态。为了避免闪烁,延迟1到2秒后再显示“离线”提示 banner。
none移除监听器 - 当组件卸载时,移除监听器,否则在热重载和导航后会多次调用回调函数。 React hook
React hook
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;
}
为什么“已连接”不等同于在线 BehaviorSubject.
源于操作系统网络堆栈。它保持真实状态的情况包括:
connected: true Wi-Fi网络有一个捕获门户(机场、酒店、火车)
- 路由器没有上游连接
- DNS已被破坏或过滤
- 原因是操作系统网络堆栈。它保持真实状态的情况包括:
- 公司防火墙或 VPN 阻止了您的 API 域名
- 您的后端服务不可用
修复方法是对您控制的内容进行可达性检查:
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);
}
}
在应用启动时 networkStatusChange 报告 connected: true, 并在请求失败后。不要每几秒钟轮询一次,否则会耗尽电池和数据。确保健康端点允许您的应用的源站在 CORS 中 (capacitor://localhost 在 iOS 上 https://localhost 在 Android 上默认情况下),或使用 CapacitorHttp 从本机 code 发送它
通过网络诊断获得更丰富的状态
@capgo/capacitor-network-diagnostics 读取操作系统知道的更多内容,并可以在 WebView CORS 中绕过的本机检查:
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: { ... }
// }
这些字段如何映射到操作系统:
| Field | Android | iOS |
|---|---|---|
internetReachable |
NET_CAPABILITY_VALIDATED (Android 检测到网络) |
镜像 NWPathMonitor 路径状态 |
expensive |
isActiveNetworkMetered() |
NWPath.isExpensive |
constrained |
始终 false |
NWPath.isConstrained (低数据模式) |
captivePortal |
NET_CAPABILITY_CAPTIVE_PORTAL |
未报告 |
vpn 类型 |
是 | 是 |
在 Android 上 internetReachable 是因为 Android 系统已经测试了连接,所以信号很强。 connected在 iOS 上,它更接近于
所以对于关键流程,仍然需要 HTTP 检查。
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 });
原生可达性检查
原生请求不受 CORS 影响,所以可以测试第三方主机。
一个支持“网络报告”屏幕
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);
当用户说“应用程序不工作”,一个一键诊断报告可以节省数小时的往返时间:
将 JSON 附加到支持票中。您会立即看到问题是否出在 DNS、阻塞的 WebSocket、捕获门户或慢速连接上。
适应计量和低数据模式连接
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;
}
尊严数据限制是快速获得市场上昂贵移动数据的好评:
使用它来决定视频自动播放、图像质量、背景同步和大型下载。Android 上,用户可以标记一个 Wi-Fi 网络为计量网络,所以不要假设 Wi-Fi 是免费的。
一个小的横幅比失败的请求更清晰。使用上面的钩子:
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" with aria-live="polite" 使屏幕阅读器宣布更改。对于框架特定的UI,请参见我们的指南到 在Vue、Angular和React中构建一个离线屏幕.
在离线时进行队列工作
检测仅是离线支持的一半。当状态变为离线时:
- Serve从本地存储读取。一个SQLite数据库,如
@capgo/capacitor-fast-sql比localStorage. - 将用户操作写入一个带有时间戳和幂等性键的出箱表中。
- 在
networkStatusChange连接时运行canReachApi(),然后按照顺序清空出箱。 - 使用指数退避重试失败的请求,最大时间限制几分钟。
对于必须在应用程序关闭时存活的上传,应将它们交给一个本机上传器,而不是 fetch.
网络回退
@capacitor/network 也在浏览器中运行,基于 navigator.onLine 和 online 在 offline 事件。因此您的code在 bun run dev 和 connectionType 中有效,但 unknown 通常会 navigator.connection 在web上。Chrome的 effectiveType 在 saveData,Safari 不支持,所以将它们视为可选提示。
故障排除
iOS Simulator 上的监听器永远不会触发:模拟器共享 Mac 的网络。将 Mac 的 Wi-Fi 打开或在飞行模式下测试设备。
connectionType 在 VPN 上 unknown :官方插件仅报告和 wifi, cellular, none and unknown切换网络时应用会在一秒钟内显示离线状态 vpn and ethernet.
:请像上面所示那样延迟离线过渡。故障排除
设备上健康检查失败,但在浏览器中正常工作: CORS 允许 capacitor://localhost 并且 https://localhost, 或使用 NetworkDiagnostics.testUrl,它可以在本机运行
navigator.onLine 是 true,而插件显示离线: 信任插件。一些 Android WebViews 不可靠地更新 navigator.onLine 通过空中将离线修复
离线处理主要是 JavaScript:阈值、横幅、重试逻辑、缓存规则。使用
__CAPGO_KEEP_0__ Capgo 实时更新,您可以为每个用户在同一天调整这些设置。Capgo 在后台下载更新包并在下载失败时保留当前版本,因此,连接不佳的情况下,用户不会因为下载失败而留下半装的更新。 网络诊断文档 列出所有选项。