之前调查过Android中WIFI模块的使用,也写过两篇学习总结的文章(http://smallwoniu.blog.51cto.com/3911954/1334951),后来发现DEMO里面还是有许多不足之处,前段时间有不少人Q我,问到WIFI模块中的一些细节,小弟这里只能说声抱歉,因为当时的我也还没研究到那个层次呀。。。,后来毕业设计选题干脆直接选择了关于WIFI热点通信方面的题目,调查和整理了一些资料,进行了一段时间的学习算是弥补了自己的短板吧
,主要还是希望自己能够更加全面的掌握这方面的知识。
废话不多说了!今天主要讲解WIFI热点通信的前期准备工作:
1.热点创建:创建指定名称的热点。
2.热点搜索:搜索附近可用热点,生成列表。
3.热点连接:在列表中点击指定名称的WIFI项,进行连接操作。
一.框架搭建
说明:
1.几个权限:
1
2
3
4
5
6
|
<
uses-permission
android:name
=
"android.permission.INTERNET"
/>
<
uses-permission
android:name
=
"android.permission.ACCESS_NETWORK_STATE"
/>
<
uses-permission
android:name
=
"android.permission.CHANGE_NETWORK_STATE"
/>
<
uses-permission
android:name
=
"android.permission.ACCESS_WIFI_STATE"
/>
<
uses-permission
android:name
=
"android.permission.CHANGE_WIFI_STATE"
/>
<
uses-permission
android:name
=
"android.permission.WAKE_LOCK"
/>
|
2.相关类图:
二.模块讲解
接下来通过以下三个部分功能来逐一剖析,在此之前首先看一张最终的效果图加深以下印象:
(由于本章讲解的部分是我的整个项目中的一部分,所以大家不用在意图片素材等其他细节)
2.1热点创建
点击WIFI管理界面中创建热点按钮,首先会检测当前WIFI是否可用,若可用则需将其关闭掉才能创建WIFI热点,因为手机热点把手机的接收GPRS或3G信号转化为WIFI信号再发出去,即你的手机就成了一个WIFI热点,所以共享和接收功能是不能同时进行的。之后就是创建指定名称的热点过程。热点创建时序图如下图所示。
几个核心方法:
-
startApWifiHot()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
/**
* create a hot wifi
*
* @param wifiName
*/
public
boolean
startApWifiHot(String wifiName) {
Log.i(TAG,
"into startApWifiHot(String wifiName) wifiName = "
+ wifiName);
if
(wifiManager.isWifiEnabled()) {
wifiManager.setWifiEnabled(
false
);
}
if
(mWifiHotAdmin !=
null
) {
return
mWifiHotAdmin.startWifiAp(wifiName);
}
Log.i(TAG,
"out startApWifiHot(String wifiName)"
);
return
false
;
}
|
-
createWifiAp()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
/**
* start hot pot
* @param wifiName
* @return
*/
private
boolean
createWifiAp(String wifiName) {
Log.i(TAG,
"into startWifiAp() 启动一个Wifi 热点!"
);
Method method1 =
null
;
boolean
ret =
false
;
try
{
//setWifiApEnabled is @hide, so reflect
method1 = mWifiManager.getClass().getMethod(
"setWifiApEnabled"
,
WifiConfiguration.
class
,
boolean
.
class
);
WifiConfiguration apConfig = createPassHotWifiConfig(wifiName,Global.PASSWORD);
ret = (Boolean) method1.invoke(mWifiManager, apConfig,
true
);
}
catch
(IllegalArgumentException e) {
e.printStackTrace();
Log.d(TAG,
"stratWifiAp() IllegalArgumentException e"
);
}
Log.i(TAG,
"out startWifiAp() 启动一个Wifi 热点!"
);
return
ret;
}
|
2.2热点搜索
点击WIFI管理界面中搜索热点按钮,同创建一样,首先需要检测WIFI热点是否关闭,将其关闭掉后才能打开WIFI搜索功能。在搜索完成后系统会发送WIFI状态变化广播来通知消息栏,这里通过自定义广播接收器接收了搜索成功消息,最后通过回调MainActivity中disPlayWifiScanResult()来显示WIFI列表。
几个核心方法:
-
scanWifiHot()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
/** scan wifi hot **/
public
void
scanWifiHot() {
Log.i(TAG,
"into wifiHotScan()"
);
if
(mWifiHotAdmin.isWifiApEnabled(wifiManager)) {
mWifiHotAdmin.closeWifiAp();
}
if
(!wifiIsOpen()) {
// WIFI is close currently
//listen to the specified SSID wifi state
registerWifiStateBroadcast(
""
);
mWifiStateReceiver.setOperationsType(OperationsType.SCAN);
//open wifi
openWifi();
}
else
{
// WIFI is open currently
scanNearWifiHots();
}
Log.i(TAG,
"out wifiHotScan()"
);
}
|
-
scanNearWifiHots()
1
2
3
4
5
6
|
/** scan near wifi **/
private
void
scanNearWifiHots() {
registerWifiScanBroadcast();
//start scan
wifiManager.startScan();
}
|
说明:这里的扫描实现过程是通过调用系统中WifiManager中扫描功能。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
/**
* Request a scan for access points. Returns immediately. The availability
* of the results is made known later by means of an asynchronous event sent
* on completion of the scan.
* @return {@code true} if the operation succeeded, i.e., the scan was initiated
*/
public
boolean
startScan() {
try
{
mService.startScan(
false
);
return
true
;
}
catch
(RemoteException e) {
return
false
;
}
}
|
2.3热点连接
在搜索完成之后,需要在WIFI列表中找到游戏的热点,点击连接过程会处理一系列逻辑:当前WIFI可用、是否已经连接、注册WIFI状态变化广播等,之后,开启独立线程进行热点匹配连接,热点连接时序图如图所示。
几个核心方法:
-
connectToHotpot()
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
|
/**
* connect to hotpot
*
* @param ssid
* @param wifiList
* @param password
*/
public
void
connectToHotpot(String ssid, List<ScanResult> wifiList, String password) {
if
(ssid ==
null
|| password.equals(
""
) || !ssid.equals(Global.HOTPOT_NAME)) {
Log.d(TAG,
"WIFI ssid is null or "
);
mWifiBroadCastOperator.disPlayWifiConnResult(
false
,
null
);
return
;
}
if
(ssid.equalsIgnoreCase(mSSID) && isConnecting) {
Log.d(TAG,
"same ssid is connecting!"
);
mWifiBroadCastOperator.disPlayWifiConnResult(
false
,
null
);
return
;
}
if
(!checkCoonectHotIsEnable(ssid, wifiList)) {
Log.d(TAG,
"ssid is not in the wifiList!"
);
mWifiBroadCastOperator.disPlayWifiConnResult(
false
,
null
);
return
;
}
if
(!wifiIsOpen()) {
//listen to ssid wifi
registerWifiStateBroadcast(ssid);
mWifiStateReceiver.setOperationsType(OperationsType.CONNECT);
//open wifi
openWifi();
}
else
{
// real connecting
enableNetwork(ssid, password);
}
}
|
-
enableNetwork()
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
|
/**
* connect wifi hot really by thread
*
* @param ssid
* @param password
*/
private
void
enableNetwork(
final
String ssid,
final
String password) {
// delete more conneted wifi
deleteMoreCon(ssid);
registerWifiConnectBroadCast();
new
Thread(
new
Runnable() {
@Override
public
void
run() {
WifiConfiguration config = WifiHotConfigAdmin.createWifiNoPassInfo(ssid, password);
// if connect is successful
isConnecting = connectHotSpot(config);
mSSID = ssid;
if
(!isConnecting) {
Log.i(TAG,
"into enableNetwork(WifiConfiguration wifiConfig) isConnecting ="
+ isConnecting);
return
;
}
}
}).start();
}
|
-
connectHotSpot()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
/**
* connect wifi hot if successful
*
* @param wifiConfig
* @return
*/
private
boolean
connectHotSpot(WifiConfiguration wifiConfig) {
Log.i(TAG,
"into enableNetwork(WifiConfiguration wifiConfig)"
);
//the ID of the newly created network description
int
wcgID = wifiManager.addNetwork(wifiConfig);
Log.i(TAG,
"into enableNetwork(WifiConfiguration wifiConfig) wcID = "
+ wcgID);
if
(wcgID <
0
) {
return
false
;
}
boolean
flag = wifiManager.enableNetwork(wcgID,
true
);
Log.i(TAG,
"out enableNetwork(WifiConfiguration wifiConfig)"
);
return
flag;
}
|
说明:连接热点的过程实质上就是获取热点配置信息,之后将其添加到自己的网络信息中同时使其可用。
至此,WIFI热点通信的前期工作已经完成,连接的手机端已在同一局域网内,若再有手机连接进来会自动为其分配该网段内的IP地址,接下来我们要做的就是在IP地址上实现数据的传输通信。在下一章中准备实现一个多人聊天室功能,希望能够帮助到大家!