公司业务是APP通过连接智能锁临时开启的AP热点,与智能锁进行通信,然后把可用的WIFI名称,密码传输到锁端,智能锁通过WiFi名与密码进行联网。在实际的使用过程中发现有部分手机(vivo y51s)虽然已经连接上智能锁开启的AP热点,但是Socket连接会报错,导致整个流程无法继续,设备AP配网失败,无法连接可用WiFi。
通过日志分析,是在这一行报错的
这一行是Android系统原始的API,这一行报错并没有什么办法可以解决。百思无果,决定试一下手机到底能不能ping通设备。
通过 adb shell ping 192.168.1.1命令发现,手机在部分时间是可以ping通智能锁的。这意味着还是有一定概率可以连上的,我们的业务场景只需要连接成功一次,那就可以了。
接下来对连接流程进行优化
/**
* 尝试连接socket
*/
private Socket connectSocket(InetAddress address, int port) {
Socket mSocket = null;
while (!isStop && mSocket == null) {
try {
mSocket = new Socket(address, port);
continue;
} catch (Exception e) {
LogUtils.i(TAG, "Socket 连接失败... address: " + address);
}
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return mSocket;
}
try {
if (mSocket != null) {
mSocket.close();
mSocket = null;
}
LogUtils.e(TAG, "111");
InetAddress ipAddress = InetAddress.getByName(ip);
LogUtils.e(TAG, "222");
mSocket = connectSocket(ipAddress, port);
LogUtils.e(TAG, "333");
if (isConnect()) {
LogUtils.e(TAG, "444 socket 连接成功");
mOutputStream = mSocket.getOutputStream();
mInputStream = mSocket.getInputStream();
isStop = false;
uiHandler.sendEmptyMessage(1);
LogUtils.e(TAG, "555");
}
/* 此处这样做没什么意义不大,真正的socket未连接还是靠心跳发送,等待服务端回应比较好,一段时间内未回应,则socket未连接成功 */
else {
LogUtils.e(TAG, "666 socket 连接失败");
uiHandler.sendEmptyMessage(-1);
LogUtils.e(TAG, "777");
return;
}
} catch (IOException e) {
uiHandler.sendEmptyMessage(-1);
LogUtils.e(TAG, "888 SocketThread connect io exception = " + e.getMessage());
e.printStackTrace();
return;
}
简单来说就是,以前只试一次,现在只要还在超时时间内就不断的进行尝试,直到成功为止,经过测试,大概在重试16次左右时能够成功。可能是因为手机本身自带的WiFi是否可用的检测机制,导致手机虽然连接上了WiFi,但是还在检测,导致并不能真正的连接上,导致bug。