Noah's Blog

Android APP WiFi开发大坑收录

2017-02-18

转载请保留 本文来自 Noah‘sBlog

最近在开发一整套全端的物联网套件(FreeIOT),由于其中Android客户端的开发是以往从未涉猎过的,所以吃了不少苦头,其中的一些大坑打算整理成文,这是第一篇。
我的基础部分习自Android Wifi 开发相关 - 简书

Android M以上扫描热点列表权限问题

主要涉及文章
http://www.jianshu.com/p/3400ca0deeee
http://stackoverflow.com/questions/35608492/why-does-android-m-requires-location-permissions-to-scan-wifi
http://stackoverflow.com/questions/35054814/wifi-scan-data-is-not-working-in-android-m

在Android M以上版本中,位置信息与WiFiManager有所关联,所以如果应用没有ACCESS_COARSE_LOCATIONACCESS_FINE_LOCATION 权限又或者是位置开关被关闭,扫描到的将会是空列表。
解决:设上这个权限,并进行权限申请,如果列表还是为空就告诉用户打开位置开关

无法连接到指定热点

主要涉及文章
http://bxbxbai.github.io/2014/05/22/android-wifi-connection/

目前Google到的大部分工具类的联网方法大多是这样的:

1
2
3
4
5
public boolean addNetwork(WifiConfiguration wf){
//连接新的连接
int netId = mWifiManager.addNetwork(wf);
return mWifiManager.enableNetwork(netId, true);
}

但是自己怎么调试也不行,最后发现了上面提到的那篇文章。
解决:改用下面提供的工具类中的连接方式,增加两行代码即可。

我重构的工具类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
package net.noahgao.freeiot.util;
import java.util.Iterator;
import java.util.List;
import android.content.Context;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
/**
* WIFI管理工具类
* @author ZHF / Ziheng Gao Refactory on 2017.2
*
*/
public class WifiAdmin {
private static WifiAdmin wifiAdmin = null;

private List<WifiConfiguration> mWifiConfiguration; //无线网络配置信息类集合(网络连接列表)
private List<ScanResult> mWifiList; //检测到接入点信息类 集合

//描述任何Wifi连接状态
private WifiInfo mWifiInfo;

WifiManager.WifiLock mWifilock; //能够阻止wifi进入睡眠状态,使wifi一直处于活跃状态
public WifiManager mWifiManager;

/**
* 获取该类的实例
* @param context
* @return
*/
public static WifiAdmin getInstance(Context context) {
if(wifiAdmin == null) {
wifiAdmin = new WifiAdmin(context);
return wifiAdmin;
} else return wifiAdmin;
}
private WifiAdmin(Context context) {
//获取系统Wifi服务 WIFI_SERVICE
this.mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
//获取连接信息
this.mWifiInfo = this.mWifiManager.getConnectionInfo();
}

/**
* 是否存在网络信息
* @param str 热点名称
* @return
*/
public WifiConfiguration isExsits(String str) {
Iterator<WifiConfiguration> localIterator = this.mWifiManager.getConfiguredNetworks().iterator();
WifiConfiguration localWifiConfiguration;
do {
if(!localIterator.hasNext()) return null;
localWifiConfiguration = localIterator.next();
}while(!localWifiConfiguration.SSID.equals("\"" + str + "\""));
return localWifiConfiguration;
}

/**锁定WifiLock,当下载大文件时需要锁定 **/
public void AcquireWifiLock() {
this.mWifilock.acquire();
}
/**创建一个WifiLock**/
public void CreateWifiLock() {
this.mWifilock = this.mWifiManager.createWifiLock("Test");
}
/**解锁WifiLock**/
public void ReleaseWifilock() {
if(mWifilock.isHeld()) { //判断时候锁定
mWifilock.acquire();
}
}

/**打开Wifi**/
public void OpenWifi() {
if(!this.mWifiManager.isWifiEnabled()){ //当前wifi不可用
this.mWifiManager.setWifiEnabled(true);
}
}
/**关闭Wifi**/
public void closeWifi() {
if(mWifiManager.isWifiEnabled()) {
mWifiManager.setWifiEnabled(false);
}
}

/**
* 添加到指定Wifi网络 /切换到指定Wifi网络
* @param wf
* @return
*/
public void addNetwork(WifiConfiguration wf){

//连接新的连接
int netId = mWifiManager.addNetwork(wf);
mWifiManager.enableNetwork(netId, true);
mWifiManager.saveConfiguration();
mWifiManager.reconnect();
}

/**
* 关闭当前的Wifi网络
* @return
*/
public boolean disconnectCurrentNetwork(){
if(mWifiManager != null && mWifiManager.isWifiEnabled()){
int netId = mWifiManager.getConnectionInfo().getNetworkId();
mWifiManager.disableNetwork(netId);
return mWifiManager.disconnect();
}
return false;
}

/**
* 创建WifiConfiguration
*
* @param SSID
* @param Password
* @param Type
* @return
*/
public WifiConfiguration createWifiCfg(String SSID, String Password, int Type) {
WifiConfiguration config = new WifiConfiguration();
config.allowedAuthAlgorithms.clear();
config.allowedGroupCiphers.clear();
config.allowedKeyManagement.clear();
config.allowedPairwiseCiphers.clear();
config.allowedProtocols.clear();
config.SSID = "\"" + SSID + "\"";

WifiConfiguration tempConfig = isExsits(SSID);
if (tempConfig != null) {
mWifiManager.removeNetwork(tempConfig.networkId);
}

if (Type == 1) //WIFICIPHER_NOPASS
{
/* config.wepKeys[0] = "";//连接无密码热点时加上这两句会出错
config.wepTxKeyIndex = 0;*/
config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
}
if (Type == 2) //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 == 3) //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;
}

/**获取ip地址**/
public int getIPAddress() {
return (mWifiInfo == null) ? 0 : mWifiInfo.getIpAddress();
}
/**获取物理地址(Mac)**/
public String getMacAddress() {
return (mWifiInfo == null) ? "NULL" : mWifiInfo.getMacAddress();
}

/**获取网络id**/
public int getNetworkId() {
return (mWifiInfo == null) ? 0 : mWifiInfo.getNetworkId();
}
/**获取热点创建状态**/
public int getWifiApState() {
try {
return (int) (Integer) this.mWifiManager.getClass()
.getMethod("getWifiApState", new Class[0])
.invoke(this.mWifiManager);
} catch (Exception ignored) {
}
return 4; //未知wifi网卡状态
}
/**获取wifi连接信息**/
public WifiInfo getWifiInfo() {
return this.mWifiManager.getConnectionInfo();
}
/** 得到网络列表**/
public List<ScanResult> getWifiList() {
this.mWifiList = this.mWifiManager.getScanResults();
return this.mWifiList;
}

/**查看扫描结果**/
public StringBuilder lookUpScan() {
StringBuilder localStringBuilder = new StringBuilder();
for (int i = 0; i < mWifiList.size(); i++)
{
localStringBuilder.append("Index_").append(Integer.toString(i + 1)).append(":");
//将ScanResult信息转换成一个字符串包
//其中把包括:BSSID、SSID、capabilities、frequency、level
localStringBuilder.append((mWifiList.get(i)).toString());
localStringBuilder.append("\n");
}
return localStringBuilder;
}

/**开始搜索wifi**/
public boolean startScan() {
return this.mWifiManager.startScan();
}
}