最近在一能开启多网络上网的Android系统中遇到连接认证WIFI问题,通过http://connectivitycheck.gstatic.com/generate_204不能完成认证。
可能原因为以下几种:
1、在wifi和移动网络同时开启的情况下,网络通过移动网络请求,返回的结果为204,不需要认证;
2、使用bindProcessToNetwork绑定wifi网络发送请求,网络请求结果为DNS解析失败(该定制Android平台特有);
为了解决这个问题,决定自己解析DNS并使用Socket发送Http
DNS解析关键代码:
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
byteBuffer.put(dnsHead);
String[] strs = domin.split("\\.");
for (String s : strs) {
byteBuffer.put((byte) s.length());
byteBuffer.put(s.getBytes());
}
byteBuffer.put((byte) 0);
byteBuffer.put(queries_end);
byteBuffer.flip();
int len = byteBuffer.limit() - byteBuffer.position();
byte[] sendData = new byte[len];
byteBuffer.get(sendData);
FlyLog.d("send:%s", ByteTools.bytes2HexString(sendData));
DatagramSocket socket = new DatagramSocket();
socket.setSoTimeout(5000);
DatagramPacket sendpack = new DatagramPacket(sendData, sendData.length, InetAddress.getByName(dns), 53);
socket.send(sendpack);
final byte[] recvBuffer = new byte[1024];
DatagramPacket recvpack = new DatagramPacket(recvBuffer, recvBuffer.length);
socket.receive(recvpack);
byte[] recvData = recvpack.getData();
FlyLog.d(recvpack.getAddress().getHostAddress() + ":" + recvpack.getPort() + "--len" + recvpack.getData().length);
FlyLog.d("recv:%s", ByteTools.bytes2HexString(recvData, 64));
int answer = ByteTools.bytes2Short2(recvData, 4);
if (answer > 0) {
ByteBuffer answerBuffer = ByteBuffer.wrap(recvData);
answerBuffer.position(len);
for (; ; ) {
short name = answerBuffer.getShort();
if (name == 0) break;
short type = answerBuffer.getShort();
short _cls = answerBuffer.getShort();
int ttl = answerBuffer.getInt();
short length = answerBuffer.getShort();
byte[] content = new byte[length];
answerBuffer.get(content);
if (type == 1) {
String ip = (content[0] & 0xff) + "." + (content[1] & 0xff) + "." + (content[2] & 0xff) + "." + (content[3] & 0xff);
FlyLog.d("get ip address=%s", ip);
return ipCheck(ip) ? ip : null;
}
}
}
Socket发送HTTP请求关键代码:
SocketAddress socketAddress = new InetSocketAddress(ip, 80);
socket = new Socket();
socket.setSoTimeout(5000);
socket.connect(socketAddress);
FlyLog.d("localAddress:"+socket.getLocalAddress());
OutputStreamWriter streamWriter = new OutputStreamWriter(socket.getOutputStream());
bufferedWriter = new BufferedWriter(streamWriter);
bufferedWriter.write("GET /generate_204 HTTP/1.1\r\n");
bufferedWriter.write("Host: " + host + "\r\n");
bufferedWriter.write("\r\n");
bufferedWriter.flush();
BufferedInputStream streamReader = new BufferedInputStream(socket.getInputStream());
bufferedReader = new BufferedReader(new InputStreamReader(streamReader, StandardCharsets.UTF_8));
String statusLine = bufferedReader.readLine();
if (TextUtils.isEmpty(statusLine)) {
FlyLog.d("Http result empty");
return 204;
} else {
FlyLog.d(statusLine);
if (statusLine.startsWith("HTTP/1.")) {
int codePos = statusLine.indexOf(' ');
if (codePos > 0) {
int phrasePos = statusLine.indexOf(' ', codePos + 1);
if (phrasePos < 0)
phrasePos = statusLine.length();
try {
return Integer.parseInt(statusLine.substring(codePos + 1, phrasePos));
} catch (NumberFormatException e) {
return 204;
}
}
}
}
bufferedReader.close();
bufferedWriter.close();
socket.close();
进程绑定Wifi网络代码:
Network defaultNetwork = cm.getActiveNetwork();
FlyLog.d("Active Network:" + defaultNetwork);
Network[] networks = cm.getAllNetworks();
for (Network network : networks) {
NetworkInfo netInfo = cm.getNetworkInfo(network);
if (netInfo != null && (netInfo.getType() == ConnectivityManager.TYPE_WIFI)) {
if(!network.equals(defaultNetwork)){
setNetwork = cm.bindProcessToNetwork(network);
FlyLog.d("Bind Network:" + network);
FlyLog.d("Active Network:" + cm.getActiveNetwork());
break;
}
}
}