1. Android Wi-Fi连接基础与常见场景
在移动开发中,Wi-Fi连接功能几乎是每个Android应用的标配能力。不同于简单的网络请求,完整的Wi-Fi功能实现涉及系统API调用、权限管理、状态监听和兼容性处理等多个技术环节。许多开发者第一次接触这个功能时,往往会被各种连接状态码和配置参数搞得晕头转向。
我经历过一个典型场景:在一个智能家居控制App中,需要让设备在本地网络通过Wi-Fi直连进行快速配网。最初版本直接调用WifiManager的API,结果在不同厂商设备上出现了连接成功率差异巨大的问题。通过分析发现,某些国产ROM对标准Wi-Fi API做了定制修改,而有些设备则需要额外配置扫描参数才能稳定发现目标热点。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. Wi-Fi连接的核心实现流程
2.1 权限声明与基本配置
在AndroidManifest.xml中必须声明以下权限:
xml复制<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <!-- Android 6.0+需要-->
<uses-permission android:name="android.permission.NEARBY_WIFI_DEVICES" /> <!-- Android 12+新增-->
特别注意:从Android 10开始,即使只是获取Wi-Fi列表也需要位置权限,这是很多新手容易忽略的点。如果缺少权限,
getScanResults()将返回空列表。
2.2 Wi-Fi管理器核心API使用
获取WifiManager实例:
java复制WifiManager wifiManager = (WifiManager)
context.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
启用/禁用Wi-Fi:
java复制wifiManager.setWifiEnabled(true); // 开启Wi-Fi
扫描网络:
java复制wifiManager.startScan();
List<ScanResult> results = wifiManager.getScanResults();
2.3 连接指定热点
创建Wi-Fi配置并连接:
java复制WifiConfiguration config = new WifiConfiguration();
config.SSID = "\"" + networkSSID + "\""; // 必须加引号
config.preSharedKey = "\"" + password + "\"";
config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
int netId = wifiManager.addNetwork(config);
wifiManager.enableNetwork(netId, true);
3. 不同Android版本的兼容性处理
3.1 Android 10+的特殊要求
从Android 10开始:
- 必须开启GPS才能获取Wi-Fi扫描结果
- 需要在运行时动态申请
ACCESS_FINE_LOCATION权限 - 每次调用
startScan()前需要检查位置服务是否启用
代码示例:
java复制if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
LocationManager lm = (LocationManager)context.getSystemService(Context.LOCATION_SERVICE);
if (!lm.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
// 引导用户开启位置服务
Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivity(intent);
}
}
3.2 Android 12的Wi-Fi权限变更
Android 12引入了新的NEARBY_WIFI_DEVICES权限,用于替代部分场景下的位置权限。需要根据实际功能选择声明:
xml复制<uses-permission android:name="android.permission.NEARBY_WIFI_DEVICES"
android:usesPermissionFlags="neverForLocation" /> <!-- 当不需要位置信息时 -->
4. 高级功能实现
4.1 Wi-Fi直连(P2P)开发
实现设备间直接通信:
java复制WifiP2pManager manager = (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE);
Channel channel = manager.initialize(this, getMainLooper(), null);
// 发现对等设备
manager.discoverPeers(channel, new WifiP2pManager.ActionListener() {
@Override
public void onSuccess() {
// 发现成功
}
@Override
public void onFailure(int reason) {
// 处理失败
}
});
4.2 企业级Wi-Fi连接(EAP)
配置企业网络连接参数:
java复制WifiConfiguration config = new WifiConfiguration();
config.SSID = "\"corp_wifi\"";
config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP);
config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.IEEE8021X);
config.enterpriseConfig.setIdentity("username");
config.enterpriseConfig.setPassword("password");
config.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.PEAP);
config.enterpriseConfig.setPhase2Method(WifiEnterpriseConfig.Phase2.MSCHAPV2);
5. 常见问题排查指南
5.1 连接失败错误码分析
| 错误码 | 含义 | 解决方案 |
|---|---|---|
| WIFI_STATE_DISABLED | Wi-Fi未启用 | 先调用setWifiEnabled(true) |
| ERROR_AUTHENTICATING | 认证失败 | 检查密码/加密方式是否匹配 |
| NETWORK_ALREADY_EXISTS | 网络已存在 | 先移除旧配置再添加 |
| INVALID_NETWORK_ID | 无效网络ID | 确保addNetwork成功后再enable |
5.2 厂商定制ROM问题处理
针对华为/小米等定制系统:
- 在后台白名单中添加应用
- 关闭电池优化设置
- 检查是否开启了"WLAN+"等增强功能
- 部分机型需要额外申请悬浮窗权限才能显示网络选择对话框
6. 性能优化建议
-
扫描策略优化:
- 避免频繁扫描(间隔建议≥30秒)
- 在屏幕点亮时再启动扫描
- 使用
WifiManager.getConfiguredNetworks()缓存已知网络
-
连接超时处理:
java复制Handler handler = new Handler();
handler.postDelayed(() -> {
if(!wifiManager.getConnectionInfo().getSSID().contains(targetSSID)){
// 超时处理
}
}, 15000); // 15秒超时
- 多网络切换优化:
- 使用
WifiNetworkSpecifier(Android 10+)指定精确连接要求 - 对于企业网络,预装CA证书到用户证书存储
- 使用
我在实际项目中总结出一个经验:在连接企业Wi-Fi时,很多设备需要手动确认证书。可以通过代码预装证书来避免这个交互步骤:
java复制KeyChain.createInstallIntent().putExtra(KeyChain.EXTRA_CERTIFICATE, certificateBytes);
startActivityForResult(installIntent, INSTALL_CERT_REQUEST);
对于需要支持Wi-Fi 6/6E的新设备,要特别注意检查WifiManager.isWifi6Supported()和isWifi6ESupported(),并在配置中设置相应的频段偏好参数。
