ibaobei 发表于 2015-9-30 12:45:11

【移动开发】WIFI热点通信(一)

  之前调查过Android中WIFI模块的使用,也写过两篇学习总结的文章(http://smallwoniu.blog.iyunv.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 isconnecting!");
      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地址上实现数据的传输通信。在下一章中准备实现一个多人聊天室功能,希望能够帮助到大家!
  
  源码下载:http://down.iyunv.com/data/1812897
  
  
  本文出自 “狂奔的蜗牛” 博客,请务必保留此出处http://smallwoniu.blog.iyunv.com/3911954/1536126
页: [1]
查看完整版本: 【移动开发】WIFI热点通信(一)