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