Android移动开发:WIFI热点通信(一)
http://tech.techweb.com.cn/thread-635449-1-1.html
(出处: TechWeb-技术社区)
今天主要讲解WIFI热点通信的前期准备工作:
1.热点创建:创建指定名称的热点。
2.热点搜索:搜索附近可用热点,生成列表。
3.热点连接:在列表中点击指定名称的WIFI项,进行连接操作。
一.框架搭建

说明:
1.几个权限:
-
<uses-permission android:name="android.permission.INTERNET" />
-
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />7 q; Y; D3 s: [$ [
-
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />9 L0 C; }; i& `/ V! B% t
-
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />7 S; F1 A# j( n: R) G. ^# @
-
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />9 M0 X( s. a" k' Z* F% e
-
<uses-permission android:name="android.permission.WAKE_LOCK" />
复制代码
2.相关类图:
9
H2 P7 l' H W: R$ O9 W7 p
二.模块讲解
接下来通过以下三个部分功能来逐一剖析,在此之前首先看一张最终的效果图加深以下印象:
/
B: R- U o5 ?8 c! ]( H- O
(由于本章讲解的部分是我的整个项目中的一部分,所以大家不用在意图片素材等其他细节)
2.1热点创建
点击WIFI管理界面中创建热点按钮,首先会检测当前WIFI是否可用,若可用则需将其关闭掉才能创建WIFI热点,因为手机热点把手机的接收GPRS或3G信号转化为WIFI信号再发出去,即你的手机就成了一个WIFI热点,所以共享和接收功能是不能同时进行的。之后就是创建指定名称的热点过程。热点创建时序图如下图所示。

几个核心方法:3
T8 A$ W) n# j
-
/**
-
* create a hot wifi% ^5 S6 S3 A( G) B( L9 {- F/ E6 {" }
-
*
-
* @param wifiName+ K1 E5 _1 \) T4 B
-
*/- ~/ ~2 c: k; _% m5 W/ p
-
public boolean startApWifiHot(String wifiName) {
-
Log.i(TAG, "into startApWifiHot(String wifiName) wifiName = " + wifiName);* ?! I4 T2 K p) G# q
-
if (wifiManager.isWifiEnabled()) {
-
wifiManager.setWifiEnabled(false);7 O7 O' {) K* k# q6 @
-
}% u1 r( F6 [! m8 {
-
if (mWifiHotAdmin != null) {
-
return mWifiHotAdmin.startWifiAp(wifiName);
-
}! l2 q1 }" T! D2 M9 {
-
Log.i(TAG, "out startApWifiHot(String wifiName)");
-
return false;
-
}
复制代码
+ g4 B6 w5 r I3 p4 w3 k
-
createWifiAp()
9 k; W; A' w' [8 w/ ?9 E
-
/**
-
* start hot pot- Q; o" M# [. O; P
-
* @param wifiName
-
* @return; Z# t& d# M/ f7 G
-
*/0 P/ i/ c4 T J; N3 {
-
private boolean createWifiAp(String wifiName) {
-
Log.i(TAG, "into startWifiAp() 启动一个Wifi 热点!");* C* U' y" w+ h9 T; t k5 j( P
-
Method method1 = null;0 q- F# C+ z/ z$ T4 d! K" @$ ^
-
boolean ret = false;5 y* E( t0 c4 n9 l/ }
-
try {( p/ m2 q0 |: ?3 b
-
//setWifiApEnabled is @hide, so reflect
-
method1 = mWifiManager.getClass().getMethod("setWifiApEnabled",
-
WifiConfiguration.class, boolean.class);0 F/ X( w* [; f" K! f# a" i" b
-
WifiConfiguration apConfig = createPassHotWifiConfig(wifiName,Global.PASSWORD); w' p# a3 K+ D
-
ret = (Boolean) method1.invoke(mWifiManager, apConfig, true);
-
} catch (IllegalArgumentException e) {. b# N% q7 b( n
-
e.printStackTrace();1 g( T$ ?+ J& j/ l! A$ l0 E
-
Log.d(TAG, "stratWifiAp() IllegalArgumentException e");
-
}
-
Log.i(TAG, "out startWifiAp() 启动一个Wifi 热点!");' g6 d% Y: V& v7 k& d b0 h
-
return ret;& V* j$ p7 C6 X) p) e8 H
-
}
复制代码
5 y% ]1 H. h( m) u0 k" H5 G
2.2热点搜索
点击WIFI管理界面中搜索热点按钮,同创建一样,首先需要检测WIFI热点是否关闭,将其关闭掉后才能打开WIFI搜索功能。在搜索完成后系统会发送WIFI状态变化广播来通知消息栏,这里通过自定义广播接收器接收了搜索成功消息,最后通过回调MainActivity中disPlayWifiScanResult()来显示WIFI列表。

几个核心方法:
-
scanWifiHot()
! }8 H W: c9 l# ]5 m
-
/** scan wifi hot **/& I5 f/ d0 A: H* V b
-
public void scanWifiHot() {
-
Log.i(TAG, "into wifiHotScan()");# b% M: p+ U( n" C9 [( Z/ {5 G+ D
-
if(mWifiHotAdmin.isWifiApEnabled(wifiManager)) {2 i3 f1 f1 z$ o$ }& _+ `' T& g, f
-
mWifiHotAdmin.closeWifiAp();& B+ R6 ], Y8 N; v3 X0 V
-
}
-
if (!wifiIsOpen()) { // WIFI is close currently
-
//listen to the specified SSID wifi state
-
registerWifiStateBroadcast("");
-
mWifiStateReceiver.setOperationsType(OperationsType.SCAN);% v! C, ?' H$ o# n: ~
-
" z- H$ ] r. g& B9 Y. i( V
-
//open wifi
-
openWifi();; C( w5 p$ p8 Q, W2 u
-
} else { // WIFI is open currently
-
scanNearWifiHots();+ @% j2 e7 c9 q* \
-
}& j! D% x% o/ s! N
-
Log.i(TAG, "out wifiHotScan()");
-
}
复制代码
-
/** scan near wifi **/+ s' N0 P4 d2 E1 N' t
-
private void scanNearWifiHots() {& D- t% M! Y! k/ @! E; M* j7 @! ?" E
-
registerWifiScanBroadcast();
-
//start scan, D, ~* K+ B/ t8 h
-
wifiManager.startScan();
-
}
复制代码
说明:这里的扫描实现过程是通过调用系统中WifiManager中扫描功能。
-
/**6 ~7 p3 D6 A4 P# u' O
-
* Request a scan for access points. Returns immediately. The availability
-
* of the results is made known later by means of an asynchronous event sent8 Z0 F( |4 C8 e% S! ^/ a4 R/ W" L3 S
-
* on completion of the scan.3 b3 v* @0 D5 n! Y7 a. c. ~8 W
-
* @return {@code true} if the operation succeeded, i.e., the scan was initiated
-
*/" S7 a) ?+ b- `9 s2 V
-
public boolean startScan() {
-
try {
-
mService.startScan(false);
-
return true;) i7 U1 f4 h2 W2 J3 u0 \/ F
-
} catch (RemoteException e) {" R1 e& _. T8 b2 @ b$ R2 a( e
-
return false;$ _( K4 a1 a# I9 m! y
-
}
-
}
复制代码
2.3热点连接
在搜索完成之后,需要在WIFI列表中找到游戏的热点,点击连接过程会处理一系列逻辑:当前WIFI可用、是否已经连接、注册WIFI状态变化广播等,之后,开启独立线程进行热点匹配连接,热点连接时序图如图所示。

几个核心方法:
-
connectToHotpot()
9 X) B$ E! k3 _% ~, k1 ^
-
/**
-
* connect to hotpot
-
* - i G. r; c! h; _- f+ s! c
-
* @param ssid
-
* @param wifiList
-
* @param password
-
*/" |+ u& k4 V7 u4 Q! u# t
-
public void connectToHotpot(String ssid, List<ScanResult> wifiList, String password) {
-
if (ssid == null || password.equals("") || !ssid.equals(Global.HOTPOT_NAME)) {4 \- d2 h# W0 h
-
Log.d(TAG, "WIFI ssid is null or ");; a) L$ D8 o8 J: M% {
-
mWifiBroadCastOperator.disPlayWifiConnResult(false, null);
-
return;
-
}5 y- s+ a2 Y2 C) M+ s2 V
-
if (ssid.equalsIgnoreCase(mSSID) && isConnecting) {# @" o6 d/ j0 R6 F+ Q* B- a
-
Log.d(TAG, "same ssid is connecting!");
-
mWifiBroadCastOperator.disPlayWifiConnResult(false, null); u7 t5 q8 ~3 n }5 G
-
return;/ P/ E/ D9 l+ {
-
}
-
if (!checkCoonectHotIsEnable(ssid, wifiList)) {; p7 ?- I) \* _* l, R/ D* V8 [
-
Log.d(TAG, "ssid is not in the wifiList!");
-
mWifiBroadCastOperator.disPlayWifiConnResult(false, null);
-
return;; D+ F: I& F" V9 v" d
-
}2 L: Q8 ~2 S9 H
-
if (!wifiIsOpen()) {
-
//listen to ssid wifi! Y" a% j+ h; H( { v O% d; D
-
registerWifiStateBroadcast(ssid);
-
mWifiStateReceiver.setOperationsType(OperationsType.CONNECT);. s7 [+ J. F. P% `6 t( u8 G
-
& H a: P4 ^ w. r! g
-
//open wifi+ V) C5 ^! P& D: N" g+ u, A1 F
-
openWifi();
-
} else {
-
// real connecting( j9 E3 A: V" ]% z- e
-
enableNetwork(ssid, password);
-
}
-
}
复制代码
( h- a- N! ]; t' a: }8 H
-
enableNetwork()
- r5 t8 K$ C+ L! s3 \/ f0 G
-
/**
-
* connect wifi hot really by thread4 B1 j" z. e( g+ V8 R' N1 E1 E) M
-
* 7 K3 ~* Y. p* R" g% T2 F, z
-
* @param ssid, L- T7 I' G) o
-
* @param password3 D) h$ m: |5 X+ u( y
-
*/
-
private void enableNetwork(final String ssid, final String password) {
-
// delete more conneted wifi! _& b5 c' B. }* v5 N7 u
-
deleteMoreCon(ssid);
-
registerWifiConnectBroadCast();: m, d( D4 `, f; q
-
-
new Thread(new Runnable() {
-
@Override* G* Q' p4 Z$ v
-
public void run() {; H, ~' ^/ f# R2 p
-
WifiConfiguration config = WifiHotConfigAdmin.createWifiNoPassInfo(ssid, password);( V4 R) x% s9 {8 \0 P# Q5 u
-
// if connect is successful
-
isConnecting = connectHotSpot(config);
-
mSSID = ssid;- z& o, a* e+ T& L
-
if (!isConnecting) {8 Q' e$ K0 ^1 k2 `
-
Log.i(TAG, "into enableNetwork(WifiConfiguration wifiConfig) isConnecting =" + isConnecting);) ^- b1 F2 C9 w4 ]% d3
z, S
-
return;. f+ a( o7 q6 Y# H' z# W+ r* p+ m
-
}+ T: \9 K) R9 e
-
}
-
}).start();( P- `& P$ M4 W3 {1 X
-
}
复制代码
M0 z# _. c' e& X& P7 o
-
connectHotSpot()
+ b: V" L$ J7 q4 Q2 h/ Y7 l$ Y
-
/**5 D* R; y2 l. A Z4 R( Z5 l
-
* connect wifi hot if successful
-
* + R9 Z! _0 Q. ?5 p0 j* }
-
* @param wifiConfig( A7 i/ S- V4 z
-
* @return0 I% j) ~1 T. [& Y+ g8 e
-
*/6 P* m) T1 S' z
-
private boolean connectHotSpot(WifiConfiguration wifiConfig) {" j' [. e: b) B, E3 a9 q/ Q' s
-
Log.i(TAG, "into enableNetwork(WifiConfiguration wifiConfig)");
-
-
//the ID of the newly created network description5 h: R) } [* [! I
-
int wcgID = wifiManager.addNetwork(wifiConfig);$ y j1 a, H" e; I. x
-
Log.i(TAG, "into enableNetwork(WifiConfiguration wifiConfig) wcID = "+ wcgID);
-
if (wcgID < 0) {3 _3 @* R/ d3 G
-
return false;/ Q y" a$ I6 Z4 P9 a4 R- c# b
-
}( _* j) z: _0 Z! k5 @# a8 C
-
boolean flag = wifiManager.enableNetwork(wcgID, true);8 @6 R' T# {: f; c( D
-
Log.i(TAG, "out enableNetwork(WifiConfiguration wifiConfig)");, C) w$ N( n4 t5 p0 D& _8 w
-
return flag;
-
}
复制代码
说明:连接热点的过程实质上就是获取热点配置信息,之后将其添加到自己的网络信息中同时使其可用。
;
N, z* ~0 E: L& M
5
j4 T! a/ I" i% f
至此,WIFI热点通信的前期工作已经完成,连接的手机端已在同一局域网内,若再有手机连接进来会自动为其分配该网段内的IP地址,接下来我们要做的就是在IP地址上实现数据的传输通信。在下一章中准备实现一个多人聊天室功能,希望能够帮助到大家!