Android Wifi热点通信和蓝牙通信类似,一般都是物联网中应用很多的技术,通信起来比较简单,
首先封装一个wfif 工具类用来切换手机连接的wifi ,与设备在同一局域网下
public class WifiUtil {
private WifiManager mWifiManager;
private Context mContext;
private final String TAG = "===WifiUtil===";
public WifiUtil(Context context){
this.mContext=context;
mWifiManager=(WifiManager)context.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
}
/**
* 创建热点
* @param mSSID 热点名称
* @param mPasswd 热点密码
* @param isOpen 是否是开放热点
*/
public void startWifiAp(String mSSID,String mPasswd,boolean isOpen){
Method method1=null;
try {
method1=mWifiManager.getClass().getMethod("setWifiApEnabled",
WifiConfiguration.class,boolean.class);
WifiConfiguration netConfig=new WifiConfiguration();
netConfig.SSID=mSSID;
netConfig.preSharedKey=mPasswd;
netConfig.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
netConfig.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
netConfig.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
if (isOpen) {
netConfig.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
}else {
netConfig.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
}
netConfig.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
netConfig.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
netConfig.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
netConfig.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
method1.invoke(mWifiManager,netConfig,true);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
/**获取热点名**/
public String getApSSID() {
try {
Method localMethod = this.mWifiManager.getClass().getDeclaredMethod("getWifiApConfiguration", new Class[0]);
if (localMethod == null) return null;
Object localObject1 = localMethod.invoke(this.mWifiManager,new Object[0]);
if (localObject1 == null) return null;
WifiConfiguration localWifiConfiguration = (WifiConfiguration) localObject1;
if (localWifiConfiguration.SSID != null) return localWifiConfiguration.SSID;
Field localField1 = WifiConfiguration.class .getDeclaredField("mWifiApProfile");
if (localField1 == null) return null;
localField1.setAccessible(true);
Object localObject2 = localField1.get(localWifiConfiguration);
localField1.setAccessible(false);
if (localObject2 == null) return null;
Field localField2 = localObject2.getClass().getDeclaredField("SSID");
localField2.setAccessible(true);
Object localObject3 = localField2.get(localObject2);
if (localObject3 == null) return null;
localField2.setAccessible(false);
String str = (String) localObject3;
return str;
} catch (Exception localException) {
}
return null;
}
/**
* 检查是否开启Wifi热点
* @return
*/
public boolean isWifiApEnabled(){
try {
Method method=mWifiManager.getClass().getMethod("isWifiApEnabled");
method.setAccessible(true);
return (boolean) method.invoke(mWifiManager);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return false;
}
/**
* 关闭热点
*/
public void closeWifiAp(){
WifiManager wifiManager= (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
if (isWifiApEnabled()){
try {
Method method=wifiManager.getClass().getMethod("getWifiApConfiguration");
method.setAccessible(true);
WifiConfiguration config= (WifiConfiguration) method.invoke(wifiManager);
Method method2=wifiManager.getClass().getMethod("setWifiApEnabled",WifiConfiguration.class,boolean.class);
method2.invoke(wifiManager,config,false);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
/**
* 开热点手机获得其他连接手机IP的方法
* @return 其他手机IP 数组列表
*/
public ArrayList getConnectedIP(){
ArrayList connectedIp=new ArrayList();
try {
BufferedReader br=new BufferedReader(new FileReader(
"/proc/net/arp"));
String line;
while ((line=br.readLine())!=null){
String[] splitted=line.split(" +");
if (splitted !=null && splitted.length>=4){
String ip=splitted[0];
if (!ip.equalsIgnoreCase("ip")){
connectedIp.add(ip);
}
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return connectedIp;
}
// 定义几种加密方式,一种是WEP,一种是WPA,还有没有密码的情况
public enum WifiCipherType {
WIFICIPHER_WEP, WIFICIPHER_WPA, WIFICIPHER_NOPASS, WIFICIPHER_INVALID
}
// 打开wifi功能
private boolean OpenWifi() {
boolean bRet = true;
if (!mWifiManager.isWifiEnabled()) {
bRet = mWifiManager.setWifiEnabled(true);
}
return bRet;
}
// 提供一个外部接口,传入要连接的无线网
public boolean Connect(String SSID, String Password, WifiCipherType Type) {
if (!this.OpenWifi()) {
return false;
}
// 开启wifi功能需要一段时间(我在手机上测试一般需要1-3秒左右),所以要等到wifi
// 状态变成WIFI_STATE_ENABLED的时候才能执行下面的语句
while (mWifiManager.getWifiState() == WifiManager.WIFI_STATE_ENABLING) {
try {
// 为了避免程序一直while循环,让它睡个100毫秒在检测……
Thread.currentThread();
Thread.sleep(100);
} catch (InterruptedException ie) {
ie.printStackTrace();
}
}
WifiConfiguration wifiConfig = CreateWifiInfo(SSID, Password, Type);
//
if (wifiConfig == null) {
Log.e(TAG,"====wifiConfig == null====");
return false;
}
WifiConfiguration tempConfig = this.IsExsits(SSID);
if (tempConfig != null) {
mWifiManager.removeNetwork(tempConfig.networkId);
}
int netID = mWifiManager.addNetwork(wifiConfig);
boolean bRet = mWifiManager.enableNetwork(netID, true);
return bRet;
}
// 查看以前是否也配置过这个网络
private WifiConfiguration IsExsits(String SSID) {
List existingConfigs = mWifiManager.getConfiguredNetworks();
for (WifiConfiguration existingConfig : existingConfigs) {
if (existingConfig.SSID.equals("\"" + SSID + "\"")) {
return existingConfig;
}
}
return null;
}
/**
* 配置连接
* @param SSID
* @param Password
* @param Type
* @return
*/
private WifiConfiguration CreateWifiInfo(String SSID, String Password, WifiCipherType Type) {
// WifiConfiguration config = new WifiConfiguration();
// config.allowedAuthAlgorithms.clear();
// config.allowedGroupCiphers.clear();
// config.allowedKeyManagement.clear();
// config.allowedPairwiseCiphers.clear();
// config.allowedProtocols.clear();
// config.SSID = "\"" + SSID + "\"";
//// config.SSID = SSID;
// if (Type == WifiCipherType.WIFICIPHER_NOPASS) {
// config.wepKeys[0] = "";
// config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
// config.wepTxKeyIndex = 0;
// }
// if (Type == WifiCipherType.WIFICIPHER_WEP) {
// // config.preSharedKey = "\"" + Password + "\"";
// config.hiddenSSID = true;
// config.wepKeys[0] = "\"" + Password + "\"";
// config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.SHARED);
// config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
// config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
// config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40);
// config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104);
// config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
// config.wepTxKeyIndex = 0;
// }
// if (Type == WifiCipherType.WIFICIPHER_WPA) {
// config.preSharedKey = "\"" + Password + "\"";
// config.status = WifiConfiguration.Status.ENABLED;
// } else {
// return null;
// }
// return config;
WifiConfiguration config = new WifiConfiguration();
config.allowedAuthAlgorithms.clear();
config.allowedGroupCiphers.clear();
config.allowedKeyManagement.clear();
config.allowedPairwiseCiphers.clear();
config.allowedProtocols.clear();
config.SSID = "\"" + SSID + "\"";
WifiConfiguration tempConfig = this.IsExsits(SSID);
if (tempConfig != null) {
mWifiManager.removeNetwork(tempConfig.networkId);
}
if (Type == WifiCipherType.WIFICIPHER_NOPASS) // WIFICIPHER_NOPASS
{
// config.wepKeys[0] = "";
config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
// config.wepTxKeyIndex = 0;
}
if (Type == WifiCipherType.WIFICIPHER_WEP) // WIFICIPHER_WEP
{
config.hiddenSSID = true;
config.wepKeys[0] = "\"" + Password + "\"";
config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.SHARED);
config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40);
config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104);
config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
config.wepTxKeyIndex = 0;
}
if (Type == WifiCipherType.WIFICIPHER_WPA) // WIFICIPHER_WPA
{
config.preSharedKey = "\"" + Password + "\"";
config.hiddenSSID = true;
config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
config.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
// config.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
config.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
config.status = WifiConfiguration.Status.ENABLED;
}
return config;
}
/**
* 切换到指定wifi
* @param wifiName 指定的wifi名字
* @param wifiPwd wifi密码,如果已经保存过密码,可以传入null
* @return
*/
public boolean changeToWifi(String wifiName, String wifiPwd ,boolean back){
if(mWifiManager == null){
Log.e(TAG, "===wifiManager初始化失败===");
return false;
}
List wifiList = mWifiManager.getConfiguredNetworks();
WifiConfiguration wfc = null;
for (int i = 0; i < wifiList.size(); ++i) {
WifiConfiguration wifiInfo0 = (WifiConfiguration) wifiList.get(i);
if (wifiInfo0.SSID.contains(wifiName)) {
Log.e(TAG, "===wifi已连接过===" + wifiInfo0.SSID);
// return doChange2Wifi(wifiInfo0.networkId);
wfc = wifiInfo0;
int anInt = SpUtils.getInt(ConsKeys.CONNECT_TIMES, 0);
if (anInt <2 && !back){
SpUtils.putInt(ConsKeys.CONNECT_TIMES,++anInt);
return false;
}
}
}
Log.e(TAG,"====wificonfig为空====="+(wfc!=null));
if (wfc!=null) {
if (mWifiManager.startScan()) {
List scanResults = mWifiManager.getScanResults();
for (ScanResult s : scanResults) {
Log.e(TAG,"====扫描到wifi名称====="+s.SSID);
if (s.SSID.contains(wifiName)) {
Log.e(TAG,"====正好扫描到该wifi,现在去连接=====");
return doChange2Wifi(wfc.networkId);
}
}
}
}
Log.e(TAG,"======建立新的wifi连接=====");
if (mWifiManager.startScan()){
List scanResults = mWifiManager.getScanResults();
Log.e(TAG,"======扫描得到wifi个数====="+scanResults.size());
for (ScanResult s:scanResults){
Log.e(TAG,"======扫描到wifi名称===="+s.SSID);
if (s.SSID.contains(wifiName)){
Log.e(TAG,"====开始连接指定wifi==="+s.SSID);
WifiConfiguration wifiNewConfiguration = CreateWifiInfo(s.SSID, wifiPwd,WifiCipherType.WIFICIPHER_NOPASS);
int newNetworkId = mWifiManager.addNetwork(wifiNewConfiguration);
if (newNetworkId == -1) {
Log.e(TAG, "=====操作失败,需要您到手机wifi列表中取消对设备连接的保存====");
removeWifi(s.SSID,null);
} else {
return doChange2Wifi(newNetworkId);
}
}
}
return false;
}else {
Log.e(TAG,"======开启wifi扫描失败=====");
return false;
}
}
private boolean doChange2Wifi(int newNetworkId) {
Log.e(TAG,"=====开始切换wifi=====");
// 如果wifi权限没打开(1、先打开wifi,2,使用指定的wifi)
if(!mWifiManager.isWifiEnabled()){
mWifiManager.setWifiEnabled(true);
}
boolean enableNetwork = mWifiManager.enableNetwork(newNetworkId, true);
if (!enableNetwork) {
Log.e(TAG, "===切换到指定wifi失败===");
SpUtils.putInt(ConsKeys.CONNECT_TIMES,0);
return false;
} else {
Log.e(TAG, "===切换到指定wifi成功===");
SpUtils.putInt(ConsKeys.CONNECT_TIMES,0);
return true;
}
}
public void removeWifi(String wifiName,String wifiPwd){
if (wifiPwd == null) {
WifiConfiguration wifiNewConfiguration = CreateWifiInfo(wifiName, wifiPwd, WifiCipherType.WIFICIPHER_NOPASS);
if (wifiNewConfiguration != null) {
mWifiManager.removeNetwork(wifiNewConfiguration.networkId);
}
}
}
// 查看以前是否也配置过这个网络
public WifiConfiguration isExsits(String SSID) {
List existingConfigs = mWifiManager
.getConfiguredNetworks();
for (WifiConfiguration existingConfig : existingConfigs) {
if (existingConfig.SSID.equals("\"" + SSID + "\"")) {
return existingConfig;
}
}
return null;
}
}
连接上设备wifi后,使用Socket与设备进行通信,一般放在workthread中:
public Socket socket;
public Runnable socketRunnable = new Runnable() {
@Override
public void run() {
try {
if (socket != null) {
if (socket.isConnected()) socket.close();
if (bReader != null) bReader.close();
if (os != null) os.close();
}
isReceivedNoData = true;
socket = new Socket();
socket.connect(new InetSocketAddress("192.168.4.1", 5120), 5000);
socket.getKeepAlive();
os = socket.getOutputStream();
InputStream is = socket.getInputStream();
//解析服务器返回的数据
bReader = new BufferedInputStream(is);
getData();
sendData();
} catch (Exception e) {
socketConthread = null;
isReceivedNoData = true;
socket = null;
Log.e(TAG, "======SOCKET连接异常======");
h.sendEmptyMessageDelayed(CONNECTED_SOCKET, 2000);
e.printStackTrace();
}
}
};
socket地址由设备放提供,一般客户的设备地址是一样的。
socket通信建立后则是读写通信内容,读写单独放到子线程中执行,使用eventbus或者接口回调处理通信内容:
public void getData(){
new Runnable() {
@Override
public void run() {
h.sendEmptyMessageDelayed(CONNECTED_SOCKET, 8000);
while (!readErr && !isTimeOut) {
try {
Thread.sleep(1000);
if (bReader != null) {
int available = bReader.available();
byte[] b = new byte[available];
int len = bReader.read(b);
String strRec = HexUtil.bytesToHexString(b);
Log.e(TAG, "====读取socket消息=====" + strRec);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}.start();
public void sendData(){
new Runnable() {
@Override
public void run() {
try {
Log.e(TAG, "===向服务器发送数据流====");
os.write("aa".getBytes());
os.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}.start();
最好将这两个线程定义出来,方便在退出是销毁,特别是如果接触了刷新view的操作,更需要谨慎使用,否则容易内粗溢出。
欢迎大家指点错误!!!