完整代码:NetworkMonitor 在网络状态查询场景中,我们往往需要实时感知网络变化 、了解当前网络的带宽和计费状态,并给出智能化建议。本文将实现一个完整的网络工具箱页面,满足这些需求。
一、最终效果
- 自动获取当前默认网络的:网络类型(Wi‑Fi/蜂窝/以太网)、上行/下行带宽(注:部分网络如Wi‑Fi可能无法提供带宽估算,此时显示"未知")、是否计费。
- 实时监听:当网络类型切换(Wi‑Fi ↔ 蜂窝)、网络断开或恢复时,界面自动刷新并更新诊断建议。
- 智能诊断:根据网络带宽和计费状态给出提示(如"当前使用移动数据,请注意流量消耗"或"网速一般")。

二、实现思路
- 获取默认网络 :通过
connection.getDefaultNet()获取当前激活的数据网络句柄。 - 查询网络能力 :利用
connection.getNetCapabilities()获取NetCapabilities对象,包含网络类型、带宽、计费标志等。 - 事件监听 :使用
NetConnection的netAvailable、netLost、netCapabilitiesChange事件实时更新 UI。 - 诊断规则:根据下行带宽数值和是否计费给出文字建议。
三、完整代码
1. 权限声明 (module.json5)
json
"requestPermissions": [
{
"name": "ohos.permission.GET_NETWORK_INFO"
},
{
"name": "ohos.permission.INTERNET"
}
]
2. 网络详情模型 (model/NetworkDetail.ets)
javascript
export interface RouteInfo {
interface: string;
destination: string;
gateway: string;
hasGateway: boolean;
isDefaultRoute: boolean;
}
export interface NetworkDetail {
netId: number;
typeName: string; // Wi-Fi / 蜂窝网络 / 以太网 / VPN / 其他
upBandwidth: number; // 上行带宽 Kbps
downBandwidth: number; // 下行带宽 Kbps
isMetered: boolean; // 是否计费
interfaceName: string; // 网卡名称
mtu: number; // 最大传输单元
ipAddresses: string[]; // 链路 IP 地址列表
routes: RouteInfo[]; // 路由信息列表
}
3. 网络管理器 (manager/NetworkManager.ets)
javascript
import { connection } from '@kit.NetworkKit';
import { NetworkDetail, RouteInfo } from '../model/NetworkDetail';
export class NetworkManager {
private static listeners: Array<(detail: NetworkDetail | null) => void> = [];
private static netConnection: connection.NetConnection | null = null;
static startListening(): void {
if (NetworkManager.netConnection) NetworkManager.stopListening();
NetworkManager.netConnection = connection.createNetConnection();
NetworkManager.netConnection.on('netAvailable', () => NetworkManager.refreshNetwork());
NetworkManager.netConnection.on('netLost', () => NetworkManager.notifyListeners(null));
NetworkManager.netConnection.on('netCapabilitiesChange', (info: connection.NetCapabilityInfo) => {
NetworkManager.fetchDetail(info.netHandle).then((detail: NetworkDetail | null) => {
NetworkManager.notifyListeners(detail);
});
});
NetworkManager.netConnection.register((err: Error | null) => {
if (!err) NetworkManager.refreshNetwork();
});
}
static stopListening(): void {
if (NetworkManager.netConnection) {
NetworkManager.netConnection.unregister(() => {});
NetworkManager.netConnection = null;
}
}
static async refreshNetwork(): Promise<void> {
try {
const netHandle = await connection.getDefaultNet();
if (!netHandle || netHandle.netId === 0) {
NetworkManager.notifyListeners(null);
return;
}
const detail = await NetworkManager.fetchDetail(netHandle);
NetworkManager.notifyListeners(detail);
} catch {
NetworkManager.notifyListeners(null);
}
}
private static async fetchDetail(netHandle: connection.NetHandle): Promise<NetworkDetail | null> {
return new Promise((resolve) => {
connection.getNetCapabilities(netHandle, async (err, caps) => {
if (err) {
resolve(null);
return;
}
// 解析网络类型
const bearer = caps.bearerTypes?.[0];
let typeName = '其他';
if (bearer === connection.NetBearType.BEARER_WIFI) typeName = 'Wi-Fi';
else if (bearer === connection.NetBearType.BEARER_CELLULAR) typeName = '蜂窝网络';
else if (bearer === connection.NetBearType.BEARER_ETHERNET) typeName = '以太网';
else if (bearer === connection.NetBearType.BEARER_VPN) typeName = 'VPN';
let isMetered = false;
if (bearer === connection.NetBearType.BEARER_CELLULAR) {
isMetered = !(caps.networkCap?.includes(connection.NetCap.NET_CAPABILITY_NOT_METERED) ?? false);
}
let props: connection.ConnectionProperties | null = null;
try {
props = connection.getConnectionPropertiesSync(netHandle);
} catch (e) {
console.error('获取连接属性失败', e);
}
const ipAddresses = props?.linkAddresses?.map(addr => addr.address.address) ?? [];
const routes: RouteInfo[] = (props?.routes ?? []).map((route): RouteInfo => ({
interface: route.interface,
destination: route.destination.address.address,
gateway: route.gateway.address,
hasGateway: route.hasGateway,
isDefaultRoute: route.isDefaultRoute,
}));
const detail: NetworkDetail = {
netId: netHandle.netId,
typeName,
upBandwidth: caps.linkUpBandwidthKbps ?? -1,
downBandwidth: caps.linkDownBandwidthKbps ?? -1,
isMetered,
interfaceName: props?.interfaceName ?? '',
mtu: props?.mtu ?? -1,
ipAddresses,
routes,
};
resolve(detail);
});
});
}
static addListener(callback: (detail: NetworkDetail | null) => void): void {
NetworkManager.listeners.push(callback);
}
static removeListener(callback: (detail: NetworkDetail | null) => void): void {
const idx = NetworkManager.listeners.indexOf(callback);
if (idx !== -1) NetworkManager.listeners.splice(idx, 1);
}
private static notifyListeners(detail: NetworkDetail | null): void {
NetworkManager.listeners.forEach(cb => cb(detail));
}
}
4. 主页面 (pages/Index.ets)
javascript
import { NetworkManager } from '../manager/NetworkManager';
import { NetworkDetail } from '../model/NetworkDetail';
interface InfoItem {
label: string,
value: string
}
@Entry
@Component
struct Index {
@State networkDetail: NetworkDetail | null = null;
@State adviceText: string = '';
aboutToAppear(): void {
NetworkManager.addListener(this.onNetworkChanged);
NetworkManager.startListening();
}
aboutToDisappear(): void {
NetworkManager.removeListener(this.onNetworkChanged);
NetworkManager.stopListening();
}
onNetworkChanged = (detail: NetworkDetail | null) => {
this.networkDetail = detail;
this.adviceText = detail ? this.getAdvice(detail) : '无网络连接,请检查网络设置';
};
getAdvice(detail: NetworkDetail): string {
if (detail.isMetered) return '当前使用移动数据,请注意流量消耗。';
if (detail.downBandwidth > 0 && detail.downBandwidth < 1000) return '当前网速较慢 (<1 Mbps),可能影响加载速度。';
if (detail.downBandwidth >= 1000 && detail.downBandwidth < 5000) return '网速一般 (1-5 Mbps),可流畅浏览网页。';
if (detail.downBandwidth >= 5000) return '网速良好 (≥5 Mbps),适合高清视频和游戏。';
return '网络状态正常。';
}
build() {
Column({ space: 16 }) {
Text('网络诊断工具箱')
.fontSize(24)
.fontWeight(FontWeight.Bold)
.margin({ top: 20 })
if (this.networkDetail) {
Column({ space: 12 }) {
this.InfoRow({label:'网络类型', value:this.networkDetail.typeName})
this.InfoRow({label:'网络ID', value:this.networkDetail.netId.toString()})
this.InfoRow({label:'上行带宽', value:this.networkDetail.upBandwidth > 0 ? `${this.networkDetail.upBandwidth} Kbps` : '未知'})
this.InfoRow({label:'下行带宽', value:this.networkDetail.downBandwidth > 0 ? `${this.networkDetail.downBandwidth} Kbps` : '未知'})
this.InfoRow({label:'计费网络', value:this.networkDetail.isMetered ? '是 (移动数据)' : '否'})
Divider()
Text('诊断建议')
.fontWeight(FontWeight.Bold)
.alignSelf(ItemAlign.Start)
Text(this.adviceText)
.fontSize(14)
.fontColor('#007AFF')
.alignSelf(ItemAlign.Start)
}
.width('90%')
.padding(16)
.backgroundColor('#F8F9FA')
.borderRadius(16)
.margin({ top: 20 })
} else {
Text('未检测到网络连接,请连接 Wi-Fi 或开启移动数据')
.margin({ top: 30 })
.fontColor('#FF3B30')
}
}
.width('100%')
.height('100%')
.padding(16)
.alignItems(HorizontalAlign.Center)
}
@Builder
InfoRow(info:InfoItem) {
Row() {
Text(info.label).width('35%').fontSize(16)
Text(info.value).fontSize(16).fontColor('#222')
}
.width('100%')
}
}
四、总结
- 实时监听:网络切换、信号变化时自动刷新,无需手动操作。
- 带宽诊断:根据下行带宽范围给出人性化提示(<1 Mbps / 1-5 Mbps / ≥5 Mbps)。
- 计费提醒:自动识别移动数据网络,提示注意流量消耗。
- 生命周期管理:页面销毁时自动停止监听,避免内存泄漏。
如果觉得本文对你有帮助,请点赞、收藏、转发支持!