在HarmonyOS应用中,App启动阶段需要判断网络是否可用。当前网络连接逻辑要求如下:
该机制可保证在弱网或网络切换场景下,App能快速切换至可用地址,保障功能可用性。
在ArkTS开发中,NetworkKit提供了基于TCP的socket接口,可用于检测目标地址是否连通,而不依赖于上层HTTP请求。
相比传统的方式,TCP连接判断具有更低的延迟和更明确的网络连通性判定结果,适合用于冷启动时的网络环境选择。
此外,BusinessError接口定义了连接失败的错误信息结构,可以通过错误码或错误信息进行异常判断与处理。
该方案通过以下三步实现目标地址的连通性检测和优选逻辑:
// 仅供展示,请根据需要替换真实地址 const PRIORITY_TARGETS: CheckTarget[] = [ { name: '主地址', host: 'app.xxx.cn', port: 8443 }, { name: '备用地址1', host: 'app1.xxx.cn', port: 8443 }, { name: '备用地址2', host: 'app2.xxx.cn', port: 8443 }, ];
private async checkNetworkConnectivity(host: string, port: number): Promise<NetWorkResult> { return new Promise((resolve) => { let tcpSocket = socket.constructTCPSocketInstance(); const connectOptions: ConnectOptions = { address: { address: host, port: port } as NetAddress, timeout: 2000 }; tcpSocket.connect(connectOptions, (error: BusinessError) => { if (!error) { tcpSocket.close(); resolve({ isReachable: true }); } else { resolve({ isReachable: false, errorCode: `ERROR_${error.code}`, errorMessage: error.message }); } }); }); }
private async checkWithPriority(): Promise<void> { this.isChecking = true; for (const target of PRIORITY_TARGETS) { hilog.error(0x0000, TAG, `正在检测 ${target.name} (${target.host}:${target.port})...`); const result = await this.checkNetworkConnectivity(target.host, target.port); if (result.isReachable) { hilog.error(0x0000, TAG, `✅ ${target.name} 连通!`); Constants.DOMAIN = `${target.host}:${target.port}`; break; } else { hilog.error(0x0000, TAG, `❌ ${target.name} 不可达: ${result.errorMessage}`); } } this.isChecking = false; }
通过以上实现,预期效果如下:
此方案可广泛应用于HarmonyOS Next版本App的冷启动初始化阶段,提高App网络初始化成功率和稳定性。运行本示例需要在工程的module.json5文件中添加网络权限ohos.permission.INTERNET。
完整示例代码如下:
import { socket } from '@kit.NetworkKit'; import { BusinessError } from '@kit.BasicServicesKit'; import { Constants } from '../constants/Constants'; import { hilog } from '@kit.PerformanceAnalysisKit'; import { NetWorkResult, ConnectOptions, NetAddress, CheckTarget } from '../model/DataModel'; const TAG = 'NetworkTest'; // 仅供展示,请根据需要替换真实地址 const PRIORITY_TARGETS: CheckTarget[] = [ { name: '主地址', host: 'app.xxx.cn', port: 8443 }, { name: '备用地址1', host: 'app1.xxx.cn', port: 8443 }, { name: '备用地址2', host: 'app2.xxx.cn', port: 8443 }, ]; @Entry @Component struct Index { @State isChecking: boolean = false; private async checkWithPriority(): Promise<void> { this.isChecking = true; for (const target of PRIORITY_TARGETS) { hilog.error(0x0000, TAG, `正在检测 ${target.name} (${target.host}:${target.port})...`); const result = await this.checkNetworkConnectivity(target.host, target.port); if (result.isReachable) { hilog.error(0x0000, TAG, `✅ ${target.name} 连通!`); Constants.DOMAIN = `${target.host}:${target.port}`; break; } else { hilog.error(0x0000, TAG, `❌ ${target.name} 不可达: ${result.errorMessage}`); } } this.isChecking = false; } private async checkNetworkConnectivity(host: string, port: number): Promise<NetWorkResult> { return new Promise((resolve) => { let tcpSocket = socket.constructTCPSocketInstance(); const connectOptions: ConnectOptions = { address: { address: host, port: port } as NetAddress, timeout: 2000 }; tcpSocket.connect(connectOptions, (error: BusinessError) => { if (!error) { tcpSocket.close(); resolve({ isReachable: true }); } else { resolve({ isReachable: false, errorCode: `ERROR_${error.code}`, errorMessage: error.message }); } }); }); } build() { Column() { Text('网络连通性检测') .fontSize(24) .margin(16) .fontWeight(FontWeight.Bold); Button(this.isChecking ? '检测中...' : '开始检测') .width(100) .margin(10) .onClick(async () => { if (!this.isChecking) { this.checkWithPriority(); } }); } .width('100%') .height('100%'); } }
export interface CheckTarget { name: string; host: string; port: number; } // 网络地址类型 export interface NetAddress { address: string; port: number; } export interface ConnectOptions { address: NetAddress; timeout: number; } export interface NetWorkResult { isReachable: boolean; errorCode?: string; errorMessage?: string; }
export class Constants { static DOMAIN: string = ''; }