九、热点模式(SoftAp):SoftApManager、热点配置、客户端管理
热点模式,说白了就是把手机变成一台小路由器。我刚开始接触 Android Wi-Fi 时,觉得这功能不就是开个热点嘛,有什么难的?直到自己动手写代码才发现,这里面的门道还真不少。
今天我们就来聊聊 SoftAp 的核心实现。我会从 SoftApManager 说起,再到热点配置,最后聊聊客户端管理。嗯,这些都是我在实际项目中踩过坑的地方。
9.1 SoftApManager:热点的总指挥
SoftApManager 是 Android 系统中管理热点模式的核心类。它负责启动、关闭热点,以及处理各种状态回调。
我个人习惯把 SoftApManager 看作一个状态机。它主要有这么几个状态:
- IDLE:空闲状态,热点未启动
- STARTING:正在启动中
- RUNNING:热点已启动,正常运行
- STOPPING:正在关闭中
来看看它的核心接口长什么样:
// SoftApManager 的核心接口
public class SoftApManager {
// 启动热点
public void startSoftAp(WifiConfiguration config);
// 关闭热点
public void stopSoftAp();
// 更新热点配置
public void updateSoftApConfig(WifiConfiguration config);
// 获取当前客户端列表
public List<WifiClient> getConnectedClients();
// 注册状态回调
public void registerCallback(SoftApCallback callback);
}
这里要注意一点:startSoftAp 和 stopSoftAp 都是异步操作。你不能调完 startSoftAp 就立刻认为热点已经启动了。我曾经犯过这个错误,在启动热点后马上尝试获取客户端列表,结果当然是空列表。
9.2 热点配置:SSID、密码与频段
热点配置主要涉及三个东西:SSID(热点名称)、密码、频段。Android 提供了 WifiConfiguration 类来封装这些信息。
来看看一个典型的热点配置:
// 创建一个热点配置
WifiConfiguration config = new WifiConfiguration();
config.SSID = "MyHotspot_5G";
config.preSharedKey = "password123";
config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA2_PSK);
// 设置频段(5GHz)
config.apBand = WifiConfiguration.AP_BAND_5GHZ;
config.apChannel = 149; // 指定信道
这里有几个坑,我一个个说:
- SSID 不要用中文:虽然 Android 支持 UTF-8 编码的 SSID,但很多旧设备不兼容。我建议只用 ASCII 字符。
- 密码长度至少 8 位:WPA2-PSK 要求密码长度在 8-63 位之间。短了会直接报错。
- 频段选择要谨慎:5GHz 频段速度快但穿墙差,2.4GHz 覆盖广但干扰多。我一般会根据场景动态选择。
9.3 客户端管理:谁连了我的热点?
热点启动后,我们需要知道有哪些设备连接了上来。Android 提供了 WifiClient 类来表示每个连接的客户端。
获取客户端列表的方式:
// 获取已连接的客户端
List<WifiClient> clients = softApManager.getConnectedClients();
for (WifiClient client : clients) {
String macAddress = client.getMacAddress();
String deviceName = client.getDeviceName();
Log.d(TAG, "客户端: " + deviceName + " (" + macAddress + ")");
}
这里有个问题:getMacAddress 在 Android 10 之后被限制了。系统不再返回真实的 MAC 地址,而是返回一个随机化的地址。这是为了保护用户隐私。
我曾经在做一个企业级热点管理应用时,就因为这个限制折腾了好几天。最后我们换了个思路:用 IP 地址 + 设备名称来标识客户端。
- 客户端管理依赖回调机制,不要轮询
- MAC 地址在 Android 10+ 被随机化,别太依赖它
- 客户端断开连接时,系统会回调 onClientDisconnected
9.4 状态回调与生命周期
SoftApManager 通过回调来通知外部状态变化。典型的回调接口长这样:
public interface SoftApCallback {
// 热点状态变化
void onStateChanged(int state, int reason);
// 有客户端连接
void onClientConnected(WifiClient client);
// 有客户端断开
void onClientDisconnected(WifiClient client);
// 热点配置变化
void onConfigChanged(WifiConfiguration config);
}
嗯,这里要特别注意 onStateChanged 的 reason 参数。它告诉你热点为什么状态变化。比如:
- REASON_START_FAILURE:启动失败,可能是硬件不支持
- REASON_INTERNAL_ERROR:内部错误,比如 Wi-Fi 芯片挂了
- REASON_CONCURRENT_CONNECTION:同时连接数超限
我建议你在开发时把这些 reason 都打日志记录下来。排查问题时会非常有帮助。
9.5 知识体系总览
下面这张图展示了 SoftAp 模式的核心知识结构:
9.6 避坑指南
最后,我把自己在项目中踩过的坑总结一下:
- 不要在主线程操作热点:热点启动和关闭都是耗时操作,一定要在后台线程执行。
- 注意权限声明:Android 10 之后需要
ACCESS_FINE_LOCATION权限才能扫描和连接热点。 - 处理并发场景:如果同时有多个应用在操作热点,可能会出现冲突。我建议用单线程的 Handler 来串行化操作。
- 测试要覆盖异常场景:比如飞行模式、Wi-Fi 关闭、硬件不支持等情况。
好了,关于 SoftAp 模式的核心内容就这些。热点管理看似简单,但要做好其实不容易。多测试、多打日志、多考虑边界情况,这是我一直以来的习惯。
公众号:蓝海资料掘金营,微信deep3321