最近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

    //打开与关闭wifipublic 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() {@Overridepublic 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)) {//连上了wifiupdateDb(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

//忽略掉指定的wifipublic 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() {@Overridepublic 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;}//打开与关闭wifipublic 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) {//重启wifiLog.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)) {//连上了wifiupdateDb(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>() {@Overridepublic 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 "";}}//忽略掉指定的wifipublic 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;}
}

解决重新开机无法自动连上的问题

1.最近发现我连上了wifi,但是每次重启,都需要再次输入密码的bug。只需要在连接的时候加上

 mWifiManager.saveConfiguration();//为让用户重新开机自动连上wifi加上此句

android 4.4 wifi 模块开发总结(电视盒子)相关推荐

  1. Android开发之ApiCloud模块开发之模块引用第三方库的问题

    因为现在第三方库比较多,所以很多人为了快速开发导致库用烂大街了,但是在模块开发中本人不建议使用第三方库的依赖会有很多问题,要么是资源图片找不到,要么是布局找不到啥的,但是有的需求只有第三方库怎么办呢? ...

  2. Android开发之ApiCloud模块开发步骤

    看图操作,简单明了: 好了apicloud模块开发完成,你可以打包arr文件压缩zip后上传到自定义模块然后别人用js就可以引用你开发的这个模块里面的内容了 打包arr文件压缩zip步骤如下图: 上传 ...

  3. Android开发之ApiCloud模块开发的注意事项

    经过本人多次模块制作打包上传基本总结模块开发的以下坑: 一.模块开发SDK最小版本必须为9,不然就算你SDK模块开发完毕正常运行你在后台云编译也无法通过会报错,提示 minSdkVersion9小于你 ...

  4. 用wifi模块开发项目

    一.写在前面 继上次的文章wifi模块esp8266的学习后,我们就可以利用自己手上的esp8266-01 模块做一些小项目啦.网上有关利用wifi模块来开发项目的资料,我百度了,但是觉得很少,大多是 ...

  5. android EasyLink给wifi模块配网

    相关文章 博客 http://blog.csdn.net/u010924834/article/details/49491349 本文使用的是庆科wifi模块 http://developer.mic ...

  6. android学习-仿Wifi模块实现

    最近研究android内核-系统关键服务的启动解析,然而我也不知道研究wifi的作用,就当兴趣去做吧(其实是作业-_-) 系统原生WiFI功能大概有:启动WiFI服务,扫描WiFi信息(这个好像已经被 ...

  7. 基于ZigBee的智能家居设计与实现—WiFi模块开发

    目录 ESP8266简介 ESP_01引脚图 ESP_01引脚介绍 ESP_01 AT指令简介 MQTT简介 MQTT协议部分报文格式 请求连接报文 确认链接报文 订阅消息报文 订阅确认报文 发表消息 ...

  8. WIFI模块开发教程之W600网络篇6:Airkiss配网

    前言 本文研究如何使用微信Airkiss协议对模块进行配网,所谓配网即是说通知模块需要连接的路由器ssid和password的一种机制. 一.理论基础 1.Airkiss原理 设备处于混杂模式监听无线 ...

  9. Wifi模块—源码分析Wifi热点扫描(Android P)

    一 前言 这次接着讲Wifi工程流程中的Wifi热点查找过程,也是Wifi启动的过程延续,Wifi启动过程中会更新Wifi的状态,框架层也有相应广播发出,应用层接收到广播后开始进行热点的扫描.可以先看 ...

最新文章

  1. 时间序列(二)数据重采样
  2. 眼球网站经济学之我见——在网站上建立现代的经济体系
  3. 盘 点 | 2015年红极一时又遭遇了滑铁卢的APP
  4. PHP算法基于相同键合并数组
  5. web前端超出两行用省略号表示
  6. 每天一点点之vue框架开发 - vue组件之间传值(父向子传值)
  7. 科学证明夜猫子都死得早?稳住,事情不是这样的
  8. SpringBoot项目Docker化并上传DockerHub的使用过程
  9. DotCMS安装步骤
  10. 目标检测---数据集格式转化及训练集和验证集划分
  11. 数字图像处理MFC程序设计之灰度图像的线性变换
  12. html标签嵌套规则
  13. H5前端实现微信分享(处理二次分享问题)
  14. 红帽子linux返回上层目录,【IT技术分享】红帽RHCSA/RHCE/RHCA Linux常用目录、命令、权限技术学习...
  15. 汇编语言上机考试三星题——负数变成绝对值,并以十进制方式输出。
  16. 快排及其优化(C语言)
  17. 当使用curl 下载压缩包时报解压格式错误
  18. 解决FIFO读写位宽不等的问题
  19. 如何选择股票投资的行业和公司
  20. Windows系统盘清理

热门文章

  1. nginx部署ssl转发https协议请求
  2. 俞敏洪:三件让人幸福的事情:有人爱,有事做,有所期待——经典的人生需要效仿
  3. 【EI会议推荐】第三届机器学习与智能系统工程国际学术会议(MLISE 2023)
  4. unity导出fbx模型_Unity批量合并Animation工具/根据已有的Animation文件批量生成带FBX动画工具...
  5. 【原创】清除、删除、重置AD账户、OU属性值往AD的OU属性添加值
  6. XP桌面上伪IE图标删除方法
  7. 他从锅盔小贩到拉闸大亨,举步维艰终于发家致富
  8. ctfshow——超级玛丽
  9. electron vue 模仿qq登录界面
  10. 用PS的照片申请理赔,保险公司能过吗?