最近在做一个项目,需要设计wifi的网络编程。在此小记一下:
WifiManager类
此类提供了管理wifi的打开或者关闭、连接等所有的功能的API以及Intent。获得此类的一个实例:Context.getSystemService(Context.WIFI_SERVICE)。
WifiCongration
WifiManager wifiManager = (WifiManager)getSystemService(WIFI_SERVICE);
wifiManager.setWifiEnabled(false);
try {
Method method = wifiManager.getClass().getMethod("setWifiApEnabled", WifiConfiguration
.class,Boolean.TYPE);
WifiConfiguration wifiConfiguration = new WifiConfiguration();
wifiConfiguration.preSharedKey = pass_key;
wifiConfiguration.SSID = SSID;
method.invoke(wifiManager,wifiConfiguration,on);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
明确几个IP地址的含义:
firstly
10.0.2.2:此IP地址的含义是本地局域网的IP地址。在android中,当你使用模拟器时,此IP地址代表的是你电脑主机的地址。
127.0.0.1:此IP地址的含义是本机的IP地址。在android中,当你使用模拟器时,此IP地址代表的是模拟器的地址。
192.168.43.1:在android中,当你开启AP wifi热点时,所有的手机开启AP热点,都会是这个地址。
而连接此AP的client端手机,是该IP地址的最后一位经过随机变化,你可以获得client端的IP地址后,然后修改此IP地址的最后一位,从而可以获得server端即AP端的IP地址。
server端:你可以通过socket的方法getInetAddress地址来获得client端的IP地址;
client端:你可以从手机上查看本机的IP地址。你也可以使用WifiInfo类 获得此int型的IP地址,此时你需要转换,你还可以通过DHCPInfo来得到Server端的以及本机的IP地址:
int型的IP地址转化为String 类型的IP:
public static String ipInt2Str(int ip) {
int first = ip>>24;
if(first<0)
first = 0xff+first+1;
int second = ip>>16&0xff;
int third = ip>>8&0xff;
int four = ip&0xff;
StringBuilder sb = new StringBuilder();
sb.append(four).append(".").append(third).append(".").append(second).append(".").append
(first);
return sb.toString();
}
NetWorkInfo
提供了所有网络连接的信息,可以通过ConnectivityManager.getActiveNetworkInfo()得到一个该类的实例,另外在监听WifiManager.NETWORK_STATE_CHANGED_ACTION是时,可以通过getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO),来得到该类的实例,然后可以获得此网络连接的相关状态。如断开连接,正在 连接等。
private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if(action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
final NetworkInfo info = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
if(info.getState().equals(NetworkInfo.State.DISCONNECTED)){
System.out.println("wifi网络连接断开");
}else if(info.getState().equals(NetworkInfo.State.CONNECTED)) {
WifiManager wifiManager = (WifiManager)getSystemService(WIFI_SERVICE);
WifiInfo wifiInfo = wifiManager.getConnectionInfo();
mOwnIP = wifiInfo.getIpAddress();
mCaller = wifiInfo.getSSID();
final DhcpInfo dhcpInfo=wifiManager.getDhcpInfo();
if(D) Log.d(TAG,"ip in DhcpInfo is:\n"+ipInt2Str(dhcpInfo.serverAddress));
new Thread(new Runnable() {
private boolean is_looping = true;
@Override
public void run() {
Socket socket = new Socket();
try {
// socket.setReuseAddress(true);
socket.connect(new InetSocketAddress(ipInt2Str(dhcpInfo.serverAddress), 54321), 10000);
// socket.setTcpNoDelay(true);
mBufferedReader = new BufferedReader(new InputStreamReader(socket
.getInputStream()));
// mPrintWriter = new PrintWriter(socket.getOutputStream());
mBufferedWriter = new BufferedWriter(new OutputStreamWriter
(socket.getOutputStream()));
Thread.sleep(1000);
String line;
while((line = mBufferedReader.readLine())!=null) {
uiHandler.obtainMessage(HANDLER_RECEIVER_MSG,mCaller+": " +line.trim()).sendToTarget();
}
} catch (SocketException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
}
}
}).start();
}
}
}
};
WifiInfo
只提供了管理的connection的信息。
DHCPInfo
管理本地局域网的IP。
secondly
BufferedReader类的readLine()是一种阻塞方法,最好搭配BufferedWriter来使用。另外一个socket可以实现双向通信,但需要在不同的线程中。有空可以好好研究下这些Stream的类。
小记:
我在使用android stdio时,引入Fileupload的Jar包时,发现出现异常 duplicated exception与common-io的LIENCE.txt和NOTICE.txt冲突,在网上搜了下:在build.gradle的android节点中中加入:
packagingOptions {
exclude 'META-INF/LICENSE.txt'
exclude 'META-INF/NOTICE.txt'
}