与WIFI扫描类似,WIFI的连接同样是一个耗时的过程,所以需要放到线程中执行,通过回调来通知调用者连接结果。该回调接口的定义如下:
1
2
3
|
public
interface
WifiConnectListener {
public
void
OnWifiConnectCompleted(
boolean
isConnected );
}
|
从Android的WIFI Setting可以看出,一般添加一个新的WIFI连接,需要给出三个信息,一个是WIFI的SSID,一个是WIFI的密码,另一个是WIFI的加密类型,不同的加密方式,连接时程序中的配置是不同的,这里定义一个枚举,给出四种常见的加密类型:
1
2
3
|
public
enum
SecurityMode {
OPEN, WEP, WPA, WPA2
}
|
Android的WIFI连接过程,总体上分为三步,第一步,添加网络配置,第二步,根据网络配置连接WIFI,第三步,监听系统的WIFI连接状态消息。下面就直接给出示例代码,关键的地方都在代码中注释了。
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
|
package
com.example.testwifi;
import
java.util.List;
import
java.util.concurrent.TimeUnit;
import
java.util.concurrent.locks.Condition;
import
java.util.concurrent.locks.Lock;
import
java.util.concurrent.locks.ReentrantLock;
import
android.content.BroadcastReceiver;
import
android.content.Context;
import
android.content.Intent;
import
android.content.IntentFilter;
import
android.net.wifi.SupplicantState;
import
android.net.wifi.WifiConfiguration;
import
android.net.wifi.WifiInfo;
import
android.net.wifi.WifiManager;
public
class
WifiConnector {
private
static
final
int
WIFI_CONNECT_TIMEOUT =
20
;
//连接WIFI的超时时间
private
Context mContext;
private
WifiManager mWifiManager;
private
Lock mLock;
private
Condition mCondition;
private
WiFiConncetReceiver mWifiConnectReceiver;
private
WifiConnectListener mWifiConnectListener;
private
boolean
mIsConnnected =
false
;
private
int
mNetworkID = -
1
;
//网络加密模式
public
enum
SecurityMode {
OPEN, WEP, WPA, WPA2
}
//通知连接结果的监听接口
public
interface
WifiConnectListener {
public
void
OnWifiConnectCompleted(
boolean
isConnected );
}
public
WifiConnector( Context context , WifiConnectListener listener ) {
mContext = context;
mLock =
new
ReentrantLock();
mCondition = mLock.newCondition();
mWifiManager=(WifiManager)mContext.getSystemService(Context.WIFI_SERVICE);
mWifiConnectReceiver =
new
WiFiConncetReceiver();
mWifiConnectListener = listener;
}
public
void
connect(
final
String ssid,
final
String password,
final
SecurityMode mode ) {
new
Thread(
new
Runnable() {
@Override
public
void
run() {
//如果WIFI没有打开,则打开WIFI
if
( !mWifiManager.isWifiEnabled() ) {
mWifiManager.setWifiEnabled(
true
);
}
//注册连接结果监听对象
mContext.registerReceiver(mWifiConnectReceiver,
new
IntentFilter(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION));
//连接指定SSID
if
( !onConnect(ssid,password,mode) ) {
mWifiConnectListener.OnWifiConnectCompleted(
false
);
}
else
{
mWifiConnectListener.OnWifiConnectCompleted(
true
);
}
//删除注册的监听类对象
mContext.unregisterReceiver(mWifiConnectReceiver);
}
}).start();
}
protected
boolean
onConnect( String ssid, String password, SecurityMode mode ) {
//添加新的网络配置
WifiConfiguration cfg =
new
WifiConfiguration();
cfg.SSID =
"\""
+ ssid +
"\""
;
if
( password !=
null
&& !
""
.equals(password) ) {
//这里比较关键,如果是WEP加密方式的网络,密码需要放到cfg.wepKeys[0]里面
if
( mode == SecurityMode.WEP ) {
cfg.wepKeys[
0
] =
"\""
+ password +
"\""
;
cfg.wepTxKeyIndex =
0
;
}
else
{
cfg.preSharedKey =
"\""
+ password +
"\""
;
}
}
cfg.status = WifiConfiguration.Status.ENABLED;
//添加网络配置
mNetworkID = mWifiManager.addNetwork(cfg);
mLock.lock();
mIsConnnected =
false
;
//连接该网络
if
( !mWifiManager.enableNetwork(mNetworkID ,
true
) ) {
mLock.unlock();
return
false
;
}
try
{
//等待连接结果
mCondition.await(WIFI_CONNECT_TIMEOUT, TimeUnit.SECONDS);
}
catch
(InterruptedException e) {
e.printStackTrace();
}
mLock.unlock();
return
mIsConnnected;
}
//监听系统的WIFI连接消息
protected
class
WiFiConncetReceiver
extends
BroadcastReceiver {
@Override
public
void
onReceive(Context context, Intent intent) {
if
(!WifiManager.SUPPLICANT_STATE_CHANGED_ACTION.equals(intent.getAction())) {
return
;
}
mLock.lock();
WifiInfo info = mWifiManager.getConnectionInfo();
if
( info.getNetworkId()==mNetworkID && info.getSupplicantState() == SupplicantState.COMPLETED ) {
mIsConnnected =
true
;
mCondition.signalAll();
}
mLock.unlock();
}
}
}
|
与WIFI扫描的封装代码类似,这里也用到了Lock和Condition,就是为了阻塞地等待WIFI连接的结果,保证正确的registerReceiver和unregisterReceiver网络连接状态监听对象,同时,设置了WIFI连接超时,防止由于WIFI模块的问题导致界面收不到回调而长时间“卡死”。
另外,AndroidManifest.xml文件中记得添加权限支持哦:
1
2
3
|
<uses-permission android:name=
"android.permission.CHANGE_WIFI_STATE"
></uses-permission>
<uses-permission android:name=
"android.permission.ACCESS_WIFI_STATE"
></uses-permission>
<uses-permission android:name=
"android.permission.ACCESS_NETWORK_STATE"
></uses-permission>
|
本文转自 Jhuster 51CTO博客,原文链接:http://blog.51cto.com/ticktick/1410080,如需转载请自行联系原作者