最近6.0的盒子的应用开发已经告一段落了,接到的新需求就是想办法让公司以前发出去的4.4的盒子也得兼容应用。把应用装到4.4盒子上,发现也就文件读取,网络(有线无线),蓝牙,恢复出厂设置这几个模块不能用了,也就是用到6.0的jar包的都不行了。
6.0wifi,系统有提供jar包,有 WifiTracker,AccessPoint这两个关键类,具体分析等有机会总结,但4.4是没有WifiTracker,AccessPoint这个类放的路径也不一样,导致系统底层提供jar包开发有点困难。所以应用层模拟一个wifi模块出来。结合了其他人的一些成果,也算鼓捣出来一款
4.4wifi开发的难点:
1.如何判定wifi是否打开
2.在wifi打开后扫描wifi
3.判定wifi扫描成功,或得扫描结果
4.确定wifi的各种状态(保存,连接,密码错误等等)
5.连接wifi(有密码与无密码)
6.忘记wifi
7.如何判定wifi已经连接成功(获得ip,网关,子网掩码)
8.wifi要是重名怎么办也就是(ssid一样)
方案:
1.如何判定wifi是否打开
//获取wifi是否已打开
public boolean isOpen() {
boolean isOpen = mWifiManager.isWifiEnabled();
Log.e(TAG, "wifi是否已打开:" + isOpen);
return isOpen;
}
打开wifi
//打开与关闭wifi
public void openWifi(boolean isOpen) {
mWifiManager.setWifiEnabled(isOpen);
}
2.在wifi打开后扫描wifi
3.判定wifi扫描成功,或得扫描结果
4.确定wifi的各种状态(保存,连接,密码错误等等)
注册一个广播,可以处理这些问题
public void registerReceiver() {
IntentFilter mFilter = new IntentFilter();
mFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
mFilter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
mFilter.addAction(WifiManager.NETWORK_IDS_CHANGED_ACTION);
mFilter.addAction(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION);
mFilter.addAction("android.net.wifi.CONFIGURED_NETWORKS_CHANGE");
mFilter.addAction("android.net.wifi.LINK_CONFIGURATION_CHANGED");
mFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
mFilter.addAction(WifiManager.RSSI_CHANGED_ACTION);
if (mReceiver == null) {
mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
//处理4.4的广播
handleEvent(intent);
}
};
}
Log.e(TAG, "==注册wifi广播==");
context.registerReceiver(mReceiver, mFilter);
}
//wifi是否打开成功的判定
if (WifiManager.WIFI_STATE_CHANGED_ACTION.equals(action)) {
//当WiFi被打开、关闭、正在打开、正在关闭或者位置状态即wifi状态发生改变时系统会自动发送该广播,
// 该广播会附带有两个值,一个是int型表示改变后的state,
// 可通过字段EXTRA_WIFI_STATE获取,
// 还有一个是int型的改变前的state(如果有的话)
// 可通过字段EXTRA_PREVIOUS_WIFI_STATE获取
// int before_state = intent.getIntExtra(WifiManager.EXTRA_PREVIOUS_WIFI_STATE, 0);
int after_state = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, 0);
if (after_state == WifiManager.WIFI_STATE_ENABLED) {
Log.e(TAG, "wifi当前状态:开启");
scanWifi();
} else if (after_state == WifiManager.WIFI_STATE_DISABLED) {
Log.e(TAG, "wifi当前状态:关闭");
Log.e(TAG, "正在打开wifi");
openWifi(true);
}
}
//判定扫描成功,获取扫描结果
else if (WifiManager.SCAN_RESULTS_AVAILABLE_ACTION.equals(action)) {
scanCompleted = true;
//获得扫描结果
List<ScanResult> scanResults = mWifiManager.getScanResults();
// 得到配置好的网络连接
List<WifiConfiguration> configuredNetworks = mWifiManager.getConfiguredNetworks();
if (configuredNetworks != null && configuredNetworks.size() > 0) {
Log.e(TAG, "得到配置好的网络连接::" + configuredNetworks.toString());
} else {
//没有任何配置好的wifi,处理是清空数据库
Log.e(TAG, "没有任何配置好的wifi,处理是清空数据库");
wifiDbManager.clearWifiDb();
}
if (scanResults != null) {
List<ScanResult> scanResultList = sortByLevel(scanResults);
List<Wifi4_0InfoBean> wifiInfoBeanList = new ArrayList<>();
for (ScanResult re : scanResultList) {
//发现扫描的结果出现SSID=""的情况,暂时不清楚原因,过滤这种情况
if (re != null && !TextUtils.isEmpty(re.SSID)) {
Log.e(TAG, "扫描得到的wifi结果::" + re.toString());
Wifi4_0InfoBean wifiInfoBean = new Wifi4_0InfoBean(re);
//判断wifi的加密方式
wifiInfoBean.setSecurity(getWifiSecurity(re));
//设置wifi的强度
wifiInfoBean.setLevel(getSignalLevel(re.level));
//设置连接状态
String state = wifiDbManager.getWifiStatus(re.SSID, re.BSSID);
wifiInfoBean.setWifiStatus(state);
if (state.equals(Wifi4_0State.CONNECTED)){
if (!hasConectWifi(re.SSID,re.BSSID)){
wifiInfoBean.setWifiStatus(Wifi4_0State.STATUS_SAVED);
}
wifiInfoBeanList.add(0,wifiInfoBean);
}else if (!state.equals(Wifi4_0State.STATUS_NONE)){
if (wifiInfoBeanList.size()==0){
wifiInfoBeanList.add(wifiInfoBean);
}else {
wifiInfoBeanList.add(1,wifiInfoBean);
}
}else {
wifiInfoBeanList.add(wifiInfoBean);
}
}
//通过wpa/wpa2进行保护:[WPA-PSK-CCMP][WPA2-PSK-CCMP][ESS]
//通过WPA2进行保护:[WPA2-PSK-CCMP][ESS]
//通过wpa/wpa2进行保护(可使用WPS)[WPA-PSK-CCMP+TKIP][WPA2-PSK-CCMP+TKIP][WPS][ESS]
//获得接入点的数据:
}
Log.e(TAG, "扫描wifi结束:根据强度排序得到wifi的条目" + wifiInfoBeanList.toString());
if (callback != null) {
callback.getWifiList(wifiInfoBeanList);
}
}
}
wifi的状态,因为6.0存在一个accesspoint这个类,这个类封装了wifi的状态,但现在是4.0,4.0底层也有这个类,但一系统层我拿不到,而好像也没封装。所以我就拿了net里的一些状态和自己模拟了一些状态。
package com.ishuidi.boxproject.module.more.network.bean;
/**
* @创建人:hcy
* @创建时间:2018/10/29
* @作用描述:Function
**/
//wifi4_0状态
public interface Wifi4_0State {
//准备开始数据连接设置
static final String IDLE="IDLE";
//扫描中
static final String SCANNING="SCANNING";
//正在连接中
static final String CONNECTING="CONNECTING";
//进行身份验证
static final String AUTHENTICATING="AUTHENTICATING";
//正在获取Ip地址
static final String OBTAINING_IPADDR="OBTAINING_IPADDR";
//已经连接
static final String CONNECTED="CONNECTED";
//IP通信暂停
static final String SUSPENDED="SUSPENDED";
//当前正在断开数据连接
static final String DISCONNECTING="DISCONNECTING";
//已断开
static final String DISCONNECTED="DISCONNECTED";
//连接失败
static final String FAILED="FAILED";
//对这个网络的访问被阻塞
static final String BLOCKED="BLOCKED";
//链接的连通性很差
static final String VERIFYING_POOR_LINK="VERIFYING_POOR_LINK";
//检查网络是否为专用门户
static final String CAPTIVE_PORTAL_CHECK="CAPTIVE_PORTAL_CHECK";
//无状态
static final String STATUS_NONE="STATUS_NONE";
//身份验证出现问题
static final String STATUS_PASSWORD_ERROR="STATUS_PASSWORD_ERROR";
//已保存
static final String STATUS_SAVED="STATUS_SAVED";
//未启用
static final String STATUS_WIFI_UNABLE="STATUS_WIFI_UNABLE";
}
最后四种状态是我模拟的。
如何判定状态:1.一个大前提需要知道:当4.4盒子同时连接有线和wifi的时候,系统默认用有线,wifi是不启用的,及时输了密码
2.状态的保存:我是采取数据库保存wifi的状态的
wifi状态的判定除了输错密码,是通过这个广播判定的:
if (WifiManager.NETWORK_STATE_CHANGED_ACTION.equals(action)) {
//判断wifi是否连接上
NetworkInfo info = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
if (null != info) {
NetworkInfo.DetailedState state = info.getDetailedState();
String ssid = mWifiManager.getConnectionInfo().getSSID().replaceAll("\"", "");
String bssid = mWifiManager.getConnectionInfo().getBSSID();
Toast.makeText(context, "wifi状态变化: " + state.name() + "???" + ssid + "???" + bssid, Toast.LENGTH_LONG).show();
Log.d(TAG, "wifi状态变化: " + state.name() + "???" + ssid + "???" + bssid);
/**
* 4.4如果wifi和有线同时连的话,那么连接wifi会一直卡在CAPTIVE_PORTAL_CHECK,应为安卓系统会选择有线网络
* 如果断掉有线
*/
if (state.name().equals(Wifi4_0State.CAPTIVE_PORTAL_CHECK)) {
//4.4连上还是连不上都会经过这里,当有线和无线同时存在的时候会卡死在这个状态
//https://blog.csdn.net/yoyo460212643/article/details/78021310
//这里处理的是:判断ip地址存不存在
updateDb(ssid, Wifi4_0State.CAPTIVE_PORTAL_CHECK, bssid);
} else if (state.name().equals(Wifi4_0State.CONNECTED)) {
//连上了wifi
updateDb(ssid, Wifi4_0State.CONNECTED, bssid);
} else {
updateDb(ssid, state.name(), bssid);
}
}
/**
* IDLE:空闲
* SCANNING:正在扫描
* CONNECTING:连接中
* AUTHENTICATING:正在进行身份验证...
* OBTAINING_IPADDR:正在获取Ip地址
* CONNECTED:已连接
* SUSPENDED:已暂停
* DISCONNECTING:正在断开连接...
* DISCONNECTED:已断开
* FAILED:失败
* BLOCKED:已阻止
* VERIFYING_POOR_LINK:暂时关闭(网络状况不佳)
*/
}
如何判定已经保存的状态:在获取扫描结果的时候,我采取获取List<ScanResult>和List<WifiConfiguration>,一个是扫描的集合,一个是配置集合,配置的集合指之前连接过的wifi(无论连上还是没有连上),所以可以在扫描结果中根据配置结果,判定含有配置结果的扫描的网络是否连上,连上就给连上状态,没连上就给保存状态。如何判定是否连上wifi:我是通过看此时能否拿到ip地址:
//判断某个wifi是否已经连上
public boolean hasConectWifi(String ssid, String bssid) {
ConnectWifiInfo wifiInfo = getConnectWifiINFo();
boolean flag = false;
if (wifiInfo != null) {
String ipAddress = wifiInfo.getTheIPaddress();
Log.i("WifINfo::", wifiInfo.toString() + "???" + ssid + "???" + bssid + "???" + ipAddress);
if (!ipAddress.equals("0.0.0.0")) {
flag = true;
} else {
flag = false;
}
} else {
flag = false;
}
if (flag) {
Log.e(TAG, "wifi状态监测::" + ssid + "已经连上了");
if (callback != null) {
if (!ssid.equals("0x")) {
callback.updateWifiState(ssid, Wifi4_0State.CONNECTED, bssid);
}
}
} else {
//暂定给一个已保存状态
updateDb(ssid, Wifi4_0State.STATUS_SAVED, bssid);
}
return flag;
}
5.连接wifi(有密码与无密码),抄的网上的:
/**
* 连接wifi
*/
public void connectWifiWithPwd(String SSID, String Password, WifiCipherType Type, String BSSID) {
//显示连接中的状态
//模拟一个正在连接的状态
updateDb(SSID, Wifi4_0State.CONNECTING, BSSID);
//callback.updateWifiState(SSID, Wifi4_0State.CONNECTING, BSSID);
WifiConfiguration tempConfig = this.isExsits(SSID, BSSID);
if (tempConfig != null) {
Log.e(TAG, "之前连接过" + SSID + ",重新连接" + BSSID);
if (!TextUtils.isEmpty(Password)){
//密码错误重新连接
tempConfig.preSharedKey = "\"" + Password + "\"";
}
connect(tempConfig);
} else {
Log.e(TAG, "重来没连接过" + SSID + "");
WifiConfiguration wifiConfig = createWifiInfo(SSID, Password, Type, BSSID);
if (wifiConfig != null) {
connect(wifiConfig);
}
}
}
private void connect(WifiConfiguration config) {
// updateDb(config.SSID, Wifi4_0State.CONNECTING, config.BSSID);
int wcgID = mWifiManager.addNetwork(config);
boolean b = mWifiManager.enableNetwork(wcgID, true);
Log.e(TAG, "wifi重连状态监测:配置信息::" + b + "??" + config);
}
//获取wifi类型,只要根据扫描结果的一个属性
//判断wifi的安全性:获得扫描后wifi的安全性
public int getWifiSecurity(ScanResult scanResult) {
//通过wpa/wpa2进行保护:[WPA-PSK-CCMP][WPA2-PSK-CCMP][ESS]
//通过WPA2进行保护:[WPA2-PSK-CCMP][ESS]
//通过wpa/wpa2进行保护(可使用WPS)[WPA-PSK-CCMP+TKIP][WPA2-PSK-CCMP+TKIP][WPS][ESS]
//获得接入点的数据:
String capabilities = scanResult.capabilities;
if (capabilities.contains("WEP")) {
return SECURITY_WEP;
} else if (capabilities.contains("PSK")) {
return SECURITY_PSK;
} else if (capabilities.contains("EAP")) {
return SECURITY_EAP;
}
return SECURITY_NONE;
}
/**
* 连接wifi需要先形成配置信息
*
* @param SSID
* @param Password
* @param Type
* @return
*/
private WifiConfiguration createWifiInfo(String SSID, String Password,
WifiCipherType Type, String BSSID) {
WifiConfiguration config = new WifiConfiguration();
config.allowedAuthAlgorithms.clear();
config.allowedGroupCiphers.clear();
config.allowedKeyManagement.clear();
config.allowedPairwiseCiphers.clear();
config.allowedProtocols.clear();
config.SSID = "\"" + SSID + "\"";
if (!TextUtils.isEmpty(BSSID)){
config.BSSID = BSSID;
}
if (Type == WifiCipherType.WIFICIPHER_NOPASS) {
//无密码连接wifi一直卡在连接中的状态
// https://blog.csdn.net/akebrt/article/details/80584965
// config.wepKeys[0] = "";
// config.wepTxKeyIndex = 0;
config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
}
if (Type == WifiCipherType.WIFICIPHER_WEP) {
config.preSharedKey = "\"" + Password + "\"";
config.hiddenSSID = true;
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.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);
}
Log.e(TAG, "createWifiInfo: " + config.toString());
return config;
}
6.忘记wifi
//忽略掉指定的wifi
public void ignoreSomeoneWifi(String SSID, String BSSID) {
WifiConfiguration tempConfig = this.isExsits(SSID, BSSID);
if (tempConfig != null) {
mWifiManager.removeNetwork(tempConfig.networkId);
mWifiManager.saveConfiguration();
//mWifiManager.disableNetwork(tempConfig.networkId);
// mWifiManager.disconnect();
Toast.makeText(context,"忽略wifi:::成功 " + SSID + "???" + BSSID,Toast.LENGTH_LONG).show();
Log.e(TAG, "忽略wifi:::成功 " + SSID + "???" + BSSID);
//显示忘记保存的状态
updateDb(SSID, Wifi4_0State.STATUS_NONE, BSSID);
scanWifi();//在扫描一次
} else {
Log.e(TAG, "忽略wifi:::错误 " + SSID + "???" + BSSID);
}
//int netId = getNetworkId();
}
7.如何判定wifi已经连接成功(获得ip,网关,子网掩码)
//获取链接的wifi详细信息
public ConnectWifiInfo getConnectWifiINFo() {
//mConnectivityManager.
ConnectWifiInfo connectWifiInfo = new ConnectWifiInfo();
DhcpInfo dhcpInfo = mWifiManager.getDhcpInfo();
connectWifiInfo.setTheIPaddress(ipIntToString(dhcpInfo.ipAddress));
connectWifiInfo.setSubnetMask(ipIntToString(dhcpInfo.netmask));
connectWifiInfo.setDNSServer(ipIntToString(dhcpInfo.dns1));
connectWifiInfo.setTheDefaultGateway(ipIntToString(dhcpInfo.gateway));
return connectWifiInfo;
}
/**
* Function: 将int类型的IP转换成字符串形式的IP<br>
*
* @param ip
* @author ZYT DateTime 2014-5-14 下午12:28:16<br>
* @return<br>
*/
public String ipIntToString(int ip) {
try {
byte[] bytes = new byte[4];
bytes[0] = (byte) (0xff & ip);
bytes[1] = (byte) ((0xff00 & ip) >> 8);
bytes[2] = (byte) ((0xff0000 & ip) >> 16);
bytes[3] = (byte) ((0xff000000 & ip) >> 24);
return Inet4Address.getByAddress(bytes).getHostAddress();
} catch (Exception e) {
return "";
}
}
8.wifi要是重名怎么办也就是(ssid一样)
6.0wifi判定重名有系统提供的方法,但现在4.0因为某些原因,没有系统的jar包,so,一切从简,我发现ssid一样但bssid不一样。so。
我的思路是判定ssid 和bssid,但貌似还是有些问题
反思:模块缺陷:
1.判定重名的方法不对:bssid相当于mac地址,有些路由器可以设置两个同名(ssid一样)的wifi
2.系统会对此刷新wifi的扫描结果,so,对wifi排序的算法不够好(不好就不展示了)
3.概率性存在扫描卡住的情况。需要关闭,再打开,再扫描,原因正在追踪(妥协:15秒内没结果就重启wifi再扫描,也不展示了)
4.判定是否连接上wifi的方法不够好
5.其他基本达到要求:
附件:
package com.ishuidi.boxproject.module.more.network.model;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.net.ConnectivityManager;
import android.net.DhcpInfo;
import android.net.NetworkInfo;
import android.net.wifi.ScanResult;
import android.net.wifi.SupplicantState;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.text.TextUtils;
import android.util.Log;
import android.widget.Toast;
import com.ishuidi.boxproject.module.more.network.bean.ConnectWifiInfo;
import com.ishuidi.boxproject.module.more.network.bean.Wifi4_0InfoBean;
import com.ishuidi.boxproject.module.more.network.bean.Wifi4_0State;
import com.ishuidi.boxproject.module.more.network.db.DbManager;
import java.net.Inet4Address;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.TimeUnit;
import io.reactivex.Flowable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
/**
* @创建人:hcy
* @创建时间:2018/10/24
* @作用描述:Function 1.当wifi重名的时候也就是SSID是相同的,BSSID是不同的
**/
public class Wifi4_0Helper {
private static final String TAG = "==wifi_test==";
private Context context;
private WifiManager mWifiManager;
private ConnectivityManager mConnectivityManager;
private DbManager wifiDbManager;
public Wifi4_0Helper(Context context, Wifi4_0CallBack callback) {
this.context = context;
this.callback = callback;
mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
mConnectivityManager = (ConnectivityManager) context
.getSystemService(Context.CONNECTIVITY_SERVICE);
wifiDbManager = DbManager.getInstance();
}
public void unregisterReceiver() {
if (mReceiver != null && context != null) {
context.unregisterReceiver(mReceiver);
Log.e(TAG, "==取消wifi广播==");
}
}
//4.0wifi的广播
private BroadcastReceiver mReceiver;
public void registerReceiver() {
IntentFilter mFilter = new IntentFilter();
mFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
mFilter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
mFilter.addAction(WifiManager.NETWORK_IDS_CHANGED_ACTION);
mFilter.addAction(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION);
mFilter.addAction("android.net.wifi.CONFIGURED_NETWORKS_CHANGE");
mFilter.addAction("android.net.wifi.LINK_CONFIGURATION_CHANGED");
mFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
mFilter.addAction(WifiManager.RSSI_CHANGED_ACTION);
if (mReceiver == null) {
mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
//处理4.4的广播
handleEvent(intent);
}
};
}
Log.e(TAG, "==注册wifi广播==");
context.registerReceiver(mReceiver, mFilter);
}
//是否支持wifi直连
public boolean isMP2pSupported() {
boolean mP2pSupported = context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI_DIRECT);
Log.e(TAG, "wifi是否支持直连:" + mP2pSupported);
return mP2pSupported;
}
//获取wifi是否已打开
public boolean isOpen() {
boolean isOpen = mWifiManager.isWifiEnabled();
Log.e(TAG, "wifi是否已打开:" + isOpen);
return isOpen;
}
//打开与关闭wifi
public void openWifi(boolean isOpen) {
mWifiManager.setWifiEnabled(isOpen);
}
static final int SECURITY_NONE = 0;
static final int SECURITY_WEP = 1;
static final int SECURITY_PSK = 2;
static final int SECURITY_EAP = 3;
//判断wifi的安全性:获得扫描后wifi的安全性
public int getWifiSecurity(ScanResult scanResult) {
//通过wpa/wpa2进行保护:[WPA-PSK-CCMP][WPA2-PSK-CCMP][ESS]
//通过WPA2进行保护:[WPA2-PSK-CCMP][ESS]
//通过wpa/wpa2进行保护(可使用WPS)[WPA-PSK-CCMP+TKIP][WPA2-PSK-CCMP+TKIP][WPS][ESS]
//获得接入点的数据:
String capabilities = scanResult.capabilities;
if (capabilities.contains("WEP")) {
return SECURITY_WEP;
} else if (capabilities.contains("PSK")) {
return SECURITY_PSK;
} else if (capabilities.contains("EAP")) {
return SECURITY_EAP;
}
return SECURITY_NONE;
}
//倒计时
public static Flowable<Integer> countDownTime(int time) {
if (time < 0) {
time = 0;
}
final int countTime = time;
return Flowable.interval(0, 1, TimeUnit.SECONDS)
.observeOn(AndroidSchedulers.mainThread())
.map((increaseTime) -> {
//解决八小时的时区问题
return countTime - increaseTime.intValue();
}).take(countTime + 1);
}
private Disposable timeSubscribe;
private void countTimeForScanWifi() {
if (timeSubscribe != null) {
timeSubscribe.dispose();
}
timeSubscribe = countDownTime(15).subscribe((time) -> {
if (time > 0) {
} else if (time == 0) {
if (!scanCompleted) {
//重启wifi
Log.e(TAG, "15秒内没有得到扫描数据: " + "重启wifi");
Log.e(TAG, "正在关闭wifi");
openWifi(false);
if (timeSubscribe != null) {
timeSubscribe.dispose();
}
}
}
});
}
private void updateDb(String ssid, String wifi_state, String bssid) {
//插入wifi状态记录
if (ssid.equals("0x") || ssid.equals("<unknown ssid>") && bssid == null) {
} else {
Log.e(TAG, "wifi状态监测::" + wifi_state + "??" + ssid + "???" + bssid);
wifiDbManager.insertOrUpdateWifi(ssid, wifi_state, bssid);
if (callback != null) {
if (!ssid.equals("0x")) {
callback.updateWifiState(ssid, wifi_state, bssid);
}
}
}
}
public void handleEvent(Intent intent) {
String action = intent.getAction();
if (WifiManager.WIFI_STATE_CHANGED_ACTION.equals(action)) {
//当WiFi被打开、关闭、正在打开、正在关闭或者位置状态即wifi状态发生改变时系统会自动发送该广播,
// 该广播会附带有两个值,一个是int型表示改变后的state,
// 可通过字段EXTRA_WIFI_STATE获取,
// 还有一个是int型的改变前的state(如果有的话)
// 可通过字段EXTRA_PREVIOUS_WIFI_STATE获取
// int before_state = intent.getIntExtra(WifiManager.EXTRA_PREVIOUS_WIFI_STATE, 0);
int after_state = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, 0);
if (after_state == WifiManager.WIFI_STATE_ENABLED) {
Log.e(TAG, "wifi当前状态:开启");
scanWifi();
} else if (after_state == WifiManager.WIFI_STATE_DISABLED) {
Log.e(TAG, "wifi当前状态:关闭");
Log.e(TAG, "正在打开wifi");
openWifi(true);
}
} else if (WifiManager.SCAN_RESULTS_AVAILABLE_ACTION.equals(action)) {
scanCompleted = true;
//获得扫描结果
List<ScanResult> scanResults = mWifiManager.getScanResults();
// 得到配置好的网络连接
List<WifiConfiguration> configuredNetworks = mWifiManager.getConfiguredNetworks();
if (configuredNetworks != null && configuredNetworks.size() > 0) {
Log.e(TAG, "得到配置好的网络连接::" + configuredNetworks.toString());
} else {
//没有任何配置好的wifi,处理是清空数据库
Log.e(TAG, "没有任何配置好的wifi,处理是清空数据库");
wifiDbManager.clearWifiDb();
}
if (scanResults != null) {
List<ScanResult> scanResultList = sortByLevel(scanResults);
List<Wifi4_0InfoBean> wifiInfoBeanList = new ArrayList<>();
for (ScanResult re : scanResultList) {
//发现扫描的结果出现SSID=""的情况,暂时不清楚原因,过滤这种情况
if (re != null && !TextUtils.isEmpty(re.SSID)) {
Log.e(TAG, "扫描得到的wifi结果::" + re.toString());
Wifi4_0InfoBean wifiInfoBean = new Wifi4_0InfoBean(re);
//判断wifi的加密方式
wifiInfoBean.setSecurity(getWifiSecurity(re));
//设置wifi的强度
wifiInfoBean.setLevel(getSignalLevel(re.level));
//设置连接状态
String state = wifiDbManager.getWifiStatus(re.SSID, re.BSSID);
wifiInfoBean.setWifiStatus(state);
if (state.equals(Wifi4_0State.CONNECTED)){
if (!hasConectWifi(re.SSID,re.BSSID)){
wifiInfoBean.setWifiStatus(Wifi4_0State.STATUS_SAVED);
}
wifiInfoBeanList.add(0,wifiInfoBean);
}else if (!state.equals(Wifi4_0State.STATUS_NONE)){
if (wifiInfoBeanList.size()==0){
wifiInfoBeanList.add(wifiInfoBean);
}else {
wifiInfoBeanList.add(1,wifiInfoBean);
}
}else {
wifiInfoBeanList.add(wifiInfoBean);
}
}
//通过wpa/wpa2进行保护:[WPA-PSK-CCMP][WPA2-PSK-CCMP][ESS]
//通过WPA2进行保护:[WPA2-PSK-CCMP][ESS]
//通过wpa/wpa2进行保护(可使用WPS)[WPA-PSK-CCMP+TKIP][WPA2-PSK-CCMP+TKIP][WPS][ESS]
//获得接入点的数据:
}
Log.e(TAG, "扫描wifi结束:根据强度排序得到wifi的条目" + wifiInfoBeanList.toString());
if (callback != null) {
callback.getWifiList(wifiInfoBeanList);
}
}
} /*else if (WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION.equals(action) ||
WifiManager.LINK_CONFIGURATION_CHANGED_ACTION.equals(action)) {
}*/ else if (WifiManager.SUPPLICANT_STATE_CHANGED_ACTION.equals(action)) {
int error = intent.getIntExtra(WifiManager.EXTRA_SUPPLICANT_ERROR, 0);
int err2 = intent.getIntExtra(WifiManager.EXTRA_NEW_STATE, 0);
Log.d(TAG, "wifi错误分析::" + error + "???" + err2);
if (WifiManager.ERROR_AUTHENTICATING == error) {
//密码错误,认证失败
String ssid = mWifiManager.getConnectionInfo().getSSID().replaceAll("\"", "");
String bssid = mWifiManager.getConnectionInfo().getBSSID();
Log.e(TAG, "wifi状态监测::身份验证失败(密码错误)" + ssid);
updateDb(ssid, Wifi4_0State.STATUS_PASSWORD_ERROR, bssid);
}
} else if (WifiManager.NETWORK_STATE_CHANGED_ACTION.equals(action)) {
//判断wifi是否连接上
NetworkInfo info = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
if (null != info) {
NetworkInfo.DetailedState state = info.getDetailedState();
String ssid = mWifiManager.getConnectionInfo().getSSID().replaceAll("\"", "");
String bssid = mWifiManager.getConnectionInfo().getBSSID();
Toast.makeText(context, "wifi状态变化: " + state.name() + "???" + ssid + "???" + bssid, Toast.LENGTH_LONG).show();
Log.d(TAG, "wifi状态变化: " + state.name() + "???" + ssid + "???" + bssid);
/**
* 4.4如果wifi和有线同时连的话,那么连接wifi会一直卡在CAPTIVE_PORTAL_CHECK,应为安卓系统会选择有线网络
* 如果断掉有线
*/
if (state.name().equals(Wifi4_0State.CAPTIVE_PORTAL_CHECK)) {
//4.4连上还是连不上都会经过这里,当有线和无线同时存在的时候会卡死在这个状态
//https://blog.csdn.net/yoyo460212643/article/details/78021310
//这里处理的是:判断ip地址存不存在
updateDb(ssid, Wifi4_0State.CAPTIVE_PORTAL_CHECK, bssid);
} else if (state.name().equals(Wifi4_0State.CONNECTED)) {
//连上了wifi
updateDb(ssid, Wifi4_0State.CONNECTED, bssid);
} else {
updateDb(ssid, state.name(), bssid);
}
}
/**
* IDLE:空闲
* SCANNING:正在扫描
* CONNECTING:连接中
* AUTHENTICATING:正在进行身份验证...
* OBTAINING_IPADDR:正在获取Ip地址
* CONNECTED:已连接
* SUSPENDED:已暂停
* DISCONNECTING:正在断开连接...
* DISCONNECTED:已断开
* FAILED:失败
* BLOCKED:已阻止
* VERIFYING_POOR_LINK:暂时关闭(网络状况不佳)
*/
} else if (WifiManager.RSSI_CHANGED_ACTION.equals(action)) {
//强度变化的广播
}
}
private boolean scanCompleted = false;
/**
* 扫描
*/
private void scanWifi() {
Log.e(TAG, "开始扫描wifi");
scanCompleted = false;
mWifiManager.startScan();
countTimeForScanWifi();
}
/**
* 将扫描到的wifi的结果根据强度由高到低排序
*
* @param list
* @return
*/
private List<ScanResult> sortByLevel(List<ScanResult> list) {
Collections.sort(list, new Comparator<ScanResult>() {
@Override
public int compare(ScanResult scanResult, ScanResult t1) {
int i = mWifiManager.calculateSignalLevel(t1.level, 4) - mWifiManager.calculateSignalLevel(scanResult.level, 4);
return i;
}
});
return list;
}
/**
* 根据ScanResult.level 算出三个级别的信号强度
*
* @param level
* @return
*/
public int getSignalLevel(int level) {
if (Math.abs(level) >= 70) {
return 1;
} else if (Math.abs(level) >= 60) {
return 2;
} else {
return 3;
}
}
private Wifi4_0CallBack callback;
// 查看以前是否也配置过这个网络
//
public WifiConfiguration isExsits(String SSID, String BSSID) {
List<WifiConfiguration> existingConfigs = mWifiManager
.getConfiguredNetworks();
Log.e(TAG, "2222===" + SSID + "???" + BSSID);
List<WifiConfiguration> list=new ArrayList<WifiConfiguration>();
if (existingConfigs != null) {
for (WifiConfiguration existingConfig : existingConfigs) {
Log.e(TAG, "1111===" + existingConfig.SSID + "???" + existingConfig.BSSID);
if (BSSID == null) {
if (existingConfig != null && existingConfig.SSID.equals("\"" + SSID + "\"")) {
return existingConfig;
}
} else {
if (existingConfig != null && existingConfig.SSID.equals("\"" + SSID + "\"") &&
existingConfig.BSSID != null && existingConfig.BSSID.equals(BSSID)) {
return existingConfig;
}else {
if (existingConfig!=null&&existingConfig.SSID.equals("\"" + SSID + "\"")){
list.add(existingConfig);
}
}
}
}
}
if (list.size()==1){
return list.get(0);
}
return null;
}
private void connect(WifiConfiguration config) {
// updateDb(config.SSID, Wifi4_0State.CONNECTING, config.BSSID);
int wcgID = mWifiManager.addNetwork(config);
boolean b = mWifiManager.enableNetwork(wcgID, true);
Log.e(TAG, "wifi重连状态监测:配置信息::" + b + "??" + config);
}
/**
* 连接wifi
*/
public void connectWifiWithPwd(String SSID, String Password, WifiCipherType Type, String BSSID) {
//显示连接中的状态
//模拟一个正在连接的状态
updateDb(SSID, Wifi4_0State.CONNECTING, BSSID);
//callback.updateWifiState(SSID, Wifi4_0State.CONNECTING, BSSID);
WifiConfiguration tempConfig = this.isExsits(SSID, BSSID);
if (tempConfig != null) {
Log.e(TAG, "之前连接过" + SSID + ",重新连接" + BSSID);
if (!TextUtils.isEmpty(Password)){
//密码错误重新连接
tempConfig.preSharedKey = "\"" + Password + "\"";
}
connect(tempConfig);
} else {
Log.e(TAG, "重来没连接过" + SSID + "");
WifiConfiguration wifiConfig = createWifiInfo(SSID, Password, Type, BSSID);
if (wifiConfig != null) {
connect(wifiConfig);
}
}
}
public void connectAddWifi(String SSID, String Password, WifiCipherType Type){
WifiConfiguration wifiConfig = createWifiInfo(SSID, Password, Type,"");
if (wifiConfig != null) {
Log.e(TAG, "connectAddWifi: "+wifiConfig.toString());
connect(wifiConfig);
}
}
/**
* 连接wifi需要先形成配置信息
*
* @param SSID
* @param Password
* @param Type
* @return
*/
private WifiConfiguration createWifiInfo(String SSID, String Password,
WifiCipherType Type, String BSSID) {
WifiConfiguration config = new WifiConfiguration();
config.allowedAuthAlgorithms.clear();
config.allowedGroupCiphers.clear();
config.allowedKeyManagement.clear();
config.allowedPairwiseCiphers.clear();
config.allowedProtocols.clear();
config.SSID = "\"" + SSID + "\"";
if (!TextUtils.isEmpty(BSSID)){
config.BSSID = BSSID;
}
if (Type == WifiCipherType.WIFICIPHER_NOPASS) {
//无密码连接wifi一直卡在连接中的状态
// https://blog.csdn.net/akebrt/article/details/80584965
// config.wepKeys[0] = "";
// config.wepTxKeyIndex = 0;
config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
}
if (Type == WifiCipherType.WIFICIPHER_WEP) {
config.preSharedKey = "\"" + Password + "\"";
config.hiddenSSID = true;
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.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);
}
Log.e(TAG, "createWifiInfo: " + config.toString());
return config;
}
public interface Wifi4_0CallBack {
void getWifiList(List<Wifi4_0InfoBean> wifiInfoBeanList);
void updateWifiState(String ssid, String name, String BSSID);
}
// 定义几种加密方式,一种是WEP,一种是WPA,还有没有密码的情况
public enum WifiCipherType {
WIFICIPHER_WEP, WIFICIPHER_WPA, WIFICIPHER_NOPASS, WIFICIPHER_INVALID
}
//获取链接的wifi详细信息
public ConnectWifiInfo getConnectWifiINFo() {
//mConnectivityManager.
ConnectWifiInfo connectWifiInfo = new ConnectWifiInfo();
DhcpInfo dhcpInfo = mWifiManager.getDhcpInfo();
connectWifiInfo.setTheIPaddress(ipIntToString(dhcpInfo.ipAddress));
connectWifiInfo.setSubnetMask(ipIntToString(dhcpInfo.netmask));
connectWifiInfo.setDNSServer(ipIntToString(dhcpInfo.dns1));
connectWifiInfo.setTheDefaultGateway(ipIntToString(dhcpInfo.gateway));
return connectWifiInfo;
}
/**
* Function: 将int类型的IP转换成字符串形式的IP<br>
*
* @param ip
* @author ZYT DateTime 2014-5-14 下午12:28:16<br>
* @return<br>
*/
public String ipIntToString(int ip) {
try {
byte[] bytes = new byte[4];
bytes[0] = (byte) (0xff & ip);
bytes[1] = (byte) ((0xff00 & ip) >> 8);
bytes[2] = (byte) ((0xff0000 & ip) >> 16);
bytes[3] = (byte) ((0xff000000 & ip) >> 24);
return Inet4Address.getByAddress(bytes).getHostAddress();
} catch (Exception e) {
return "";
}
}
//忽略掉指定的wifi
public void ignoreSomeoneWifi(String SSID, String BSSID) {
WifiConfiguration tempConfig = this.isExsits(SSID, BSSID);
if (tempConfig != null) {
mWifiManager.removeNetwork(tempConfig.networkId);
mWifiManager.saveConfiguration();
//mWifiManager.disableNetwork(tempConfig.networkId);
// mWifiManager.disconnect();
Toast.makeText(context,"忽略wifi:::成功 " + SSID + "???" + BSSID,Toast.LENGTH_LONG).show();
Log.e(TAG, "忽略wifi:::成功 " + SSID + "???" + BSSID);
//显示忘记保存的状态
updateDb(SSID, Wifi4_0State.STATUS_NONE, BSSID);
scanWifi();//在扫描一次
} else {
Log.e(TAG, "忽略wifi:::错误 " + SSID + "???" + BSSID);
}
//int netId = getNetworkId();
}
/* public void forgetWifi() {
int networkId = mWifiManager.getConnectionInfo().getNetworkId();
mWifiManager.disableNetwork(networkId);
mWifiManager.disconnect();
Log.d(TAG, "systemForget:--> systemForget: " + networkId);
}*/
//判断某个wifi是否已经连上
public boolean hasConectWifi(String ssid, String bssid) {
ConnectWifiInfo wifiInfo = getConnectWifiINFo();
boolean flag = false;
if (wifiInfo != null) {
String ipAddress = wifiInfo.getTheIPaddress();
Log.i("WifINfo::", wifiInfo.toString() + "???" + ssid + "???" + bssid + "???" + ipAddress);
if (!ipAddress.equals("0.0.0.0")) {
flag = true;
} else {
flag = false;
}
} else {
flag = false;
}
if (flag) {
Log.e(TAG, "wifi状态监测::" + ssid + "已经连上了");
if (callback != null) {
if (!ssid.equals("0x")) {
callback.updateWifiState(ssid, Wifi4_0State.CONNECTED, bssid);
}
}
} else {
//暂定给一个已保存状态
updateDb(ssid, Wifi4_0State.STATUS_SAVED, bssid);
}
return flag;
}
//保存状态下的链接
public void connectHasSavedWifi(String SSID, String BSSID) {
WifiConfiguration tempConfig = this.isExsits(SSID, BSSID);
if (tempConfig != null) {
Log.e(TAG, "之前连接过>>>" + SSID + ",重新连接");
//模拟个正在连接的状态
updateDb(SSID, Wifi4_0State.CONNECTING, BSSID);
// callback.updateWifiState(SSID, Wifi4_0State.CONNECTING, BSSID);
connect(tempConfig);
} else {
Log.e(TAG, "之前没连接过>>>" + SSID + ",重新连接");
callback.updateWifiState(SSID, Wifi4_0State.STATUS_NONE, BSSID);
}
}
public boolean wifiHasConnected(String ssid, String bssid) {
WifiInfo mWifiManagerConnectionInfo = mWifiManager.getConnectionInfo();
if (mWifiManagerConnectionInfo.getSupplicantState() == SupplicantState.COMPLETED) {
if (mWifiManagerConnectionInfo.getSSID().replaceAll("\"", "").equals(ssid) &&
mWifiManagerConnectionInfo.getBSSID().equals(bssid)) {
return true;
}
}
return false;
}
}