最近在做Android的WiFi部分的开发,连接的工具类参照了这个文章的工具类。

  http://www.cnblogs.com/zhuqiang/p/3566686.html

  开发中碰上的一些问题,在这里对一些解决办法做了些记录。

  1.对于WiFi加密方式的识别

  1. String capabilities = scanResult.capabilities;
  1. if (capabilities.contains("WPA") || capabilities.contains("wpa")) {
    ((WifiHolder) holder).setType(WifiConnector.WifiCipherType.WIFICIPHER_WPA);
    } else if (capabilities.contains("WEP") || capabilities.contains("wep")) {
    ((WifiHolder) holder).setType(WifiConnector.WifiCipherType.WIFICIPHER_WEP);
    } else {
    ((WifiHolder) holder).setType(WifiConnector.WifiCipherType.WIFICIPHER_NOPASS);
    }
  2.  
  3. 通过获取scanResultcapabilities来判断WiFi的加密方式

2.连接WiFi的成功率

开发中发现当我输入密码正确时,没能连接到我的指定wifi。目前发现原因是由于WifiManager会保存历史的WiFi配置造成了影响。

  1. public List<WifiConfiguration> cleanWifiConfiguredNetworks(String ssid) {
    List<WifiConfiguration> configuredNetworks = wifiManager
    .getConfiguredNetworks();
  2.  
  3. for (int i = 0; i < configuredNetworks.size(); i++) {
    wifiManager.removeNetwork(configuredNetworks.get(i).networkId);
    }
    return configuredNetworks;
    }
    很简单直接清空了历史配置或者设置其他为不可用。

3.wifi连接成功的监听

不太喜欢广播监听,各种问题很多,我直接对当前连接wifi信息进行判断。

先通过wifiManager.getConnectionInfo() 获取当前的连接WiFi信息,

  1. connectionInfo.getSSID().contains(ssid) ||
    connectionInfo.getSupplicantState() != SupplicantState.COMPLETED
  2.  
  3. 再判断wifissid以及wifimanager的状态,两条件都满足时则WiFi连接成功。
    项目需求我这接下来要进行socket通信,这种状态下获取的IP地址存在延迟增加了新的条件判断,对于wifiinfo中的MeteredHint参数额外的判断。当这变为true
    时,获取了正确IP。这个参数获取方法给hide,不能调用需反射才能成功使用代码如下:
  4.  
  5. //通过反射方法调用hide方法
    public boolean getWifiInfoHint(WifiInfo connectionInfo) throws InstantiationException {
    Class aClass = connectionInfo.getClass();
    try {
    Method getMeteredHint = aClass.getDeclaredMethod("getMeteredHint");
    getMeteredHint.setAccessible(true);
    Object invoke = getMeteredHint.invoke(connectionInfo);
    return (boolean) invoke;
    } catch (NoSuchMethodException e) {
    e.printStackTrace();
    } catch (IllegalAccessException e) {
    e.printStackTrace();
    } catch (InvocationTargetException e) {
    e.printStackTrace();
    }
    return false;
    }
  6.  
  7. 获取服务器的IP地址方法:
    DhcpInfo info = wifiManage.getDhcpInfo();
    String serverAddress = intToIp(info.serverAddress);
  8.  
  9. // 将获取的int转为真正的ip地址,参考的网上的,修改了下
    private String intToIp(int i) {
    return (i & 0xFF) + "." + ((i >> 8) & 0xFF) + "." + ((i >> 16) & 0xFF) + "." + ((i >> 24) & 0xFF);
    }

  1.  
  2. OK 结束 修改过后的全部代码如下:
  3.  
  4. package com.dopool.usersystem.hotspot;
  5.  
  6. import android.content.Context;
    import android.net.wifi.ScanResult;
    import android.net.wifi.SupplicantState;
    import android.net.wifi.WifiConfiguration;
    import android.net.wifi.WifiConfiguration.AuthAlgorithm;
    import android.net.wifi.WifiConfiguration.KeyMgmt;
    import android.net.wifi.WifiInfo;
    import android.net.wifi.WifiManager;
    import android.os.Handler;
    import android.os.Message;
    import android.text.TextUtils;
    import android.util.Log;
  7.  
  8. import com.dopool.usersystem.Constant;
    import com.zhy.http.okhttp.utils.L;
  9.  
  10. import java.lang.reflect.Field;
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    import java.util.ArrayList;
    import java.util.List;
  11.  
  12. public class WifiConnector {
    public Handler mHandler;
    WifiManager wifiManager;
  13.  
  14. /**
    * 向UI发送消息
    *
    * @param info 消息
    */
    public void sendMsg(String info) {
    if (mHandler != null) {
    Message msg = new Message();
    msg.obj = info;
    mHandler.sendMessage(msg);// 向Handler发送消息
    } else {
    Log.e("wifi", info);
    }
    }
  15.  
  16. //WIFICIPHER_WEP是WEP ,WIFICIPHER_WPA是WPA,WIFICIPHER_NOPASS没有密码
    public enum WifiCipherType {
    WIFICIPHER_WEP, WIFICIPHER_WPA, WIFICIPHER_NOPASS, WIFICIPHER_INVALID
    }
  17.  
  18. // 构造函数
    public WifiConnector(Context context) {
    // 取得WifiManager对象
    this.wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
    }
  19.  
  20. // 提供一个外部接口,传入要连接的无线网
    public void connect(String ssid, String password, WifiCipherType type) {
    Thread thread = new Thread(new ConnectRunnable(ssid, password, type));
    thread.start();
    }
  21.  
  22. // 查看以前是否也配置过这个网络
    private WifiConfiguration isExsits(String SSID) {
    List<WifiConfiguration> existingConfigs = wifiManager
    .getConfiguredNetworks();
    for (WifiConfiguration existingConfig : existingConfigs) {
    if (existingConfig.SSID.equals("\"" + SSID + "\"")) {
    return existingConfig;
    }
    }
    return null;
    }
  23.  
  24. private WifiConfiguration createWifiInfo(String SSID, String Password,
    WifiCipherType Type) {
    WifiConfiguration config = new WifiConfiguration();
    config.allowedAuthAlgorithms.clear();
    config.allowedGroupCiphers.clear();
    config.allowedKeyManagement.clear();
    config.allowedPairwiseCiphers.clear();
    config.allowedProtocols.clear();
    config.SSID = "\"" + SSID + "\"";
    // nopass
    if (Type == WifiCipherType.WIFICIPHER_NOPASS) {
    config.allowedKeyManagement.set(KeyMgmt.NONE);
    }
    // wep
    if (Type == WifiCipherType.WIFICIPHER_WEP) {
    if (!TextUtils.isEmpty(Password)) {
    if (isHexWepKey(Password)) {
    config.wepKeys[0] = Password;
    } else {
    config.wepKeys[0] = "\"" + Password + "\"";
    }
    }
    config.allowedAuthAlgorithms.set(AuthAlgorithm.OPEN);
    config.allowedAuthAlgorithms.set(AuthAlgorithm.SHARED);
    config.allowedKeyManagement.set(KeyMgmt.NONE);
    config.wepTxKeyIndex = 0;
    }
    // wpa
    if (Type == WifiCipherType.WIFICIPHER_WPA) {
    config.preSharedKey = "\"" + Password + "\"";
    config.hiddenSSID = true;
    config.allowedAuthAlgorithms
    .set(AuthAlgorithm.OPEN);
    config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
    config.allowedKeyManagement.set(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;
    }
  25.  
  26. // 打开wifi功能
    private boolean openWifi() {
    boolean bRet = true;
    if (!wifiManager.isWifiEnabled()) {
    bRet = wifiManager.setWifiEnabled(true);
    }
    return bRet;
    }
  27.  
  28. private boolean closeifi() {
    boolean bRet = true;
    if (wifiManager.isWifiEnabled()) {
    bRet = wifiManager.setWifiEnabled(false);
    }
    return bRet;
    }
  29.  
  30. class ConnectRunnable implements Runnable {
    private String ssid;
  31.  
  32. private String password;
  33.  
  34. private WifiCipherType type;
  35.  
  36. public ConnectRunnable(String ssid, String password, WifiCipherType type) {
    this.ssid = ssid;
    this.password = password;
    this.type = type;
    }
  37.  
  38. @Override
    public void run() {
    try {
    // 打开wifi
    openWifi();
    sendMsg("opened");
    Thread.sleep(200);
    // 开启wifi功能需要一段时间(我在手机上测试一般需要1-3秒左右),所以要等到wifi
    // 状态变成WIFI_STATE_ENABLED的时候才能执行下面的语句
    while (wifiManager.getWifiState() == WifiManager.WIFI_STATE_ENABLING) {
    try {
    // 为了避免程序一直while循环,让它睡个100毫秒检测……
    Thread.sleep(100);
    } catch (InterruptedException ie) {
    }
    }
  39.  
  40. //去掉以往的WiFi配置
    List<WifiConfiguration> saveConfigureNetworks = cleanWifiConfiguredNetworks(ssid);
  41.  
  42. WifiConfiguration wifiConfig = createWifiInfo(ssid, password,
    type);
  43.  
  44. if (wifiConfig == null) {
    sendMsg("wifiConfig is null!");
    return;
    }
  45.  
  46. int netID = wifiManager.addNetwork(wifiConfig);
    boolean enabled = wifiManager.enableNetwork(netID, true);
    boolean connected = wifiManager.reconnect();
  47.  
  48. WifiInfo connectionInfo = wifiManager.getConnectionInfo();
  49.  
  50. int num = 0;
    int sum = 25;
    if (ssid.contains("DoPool")) {
    sum = 35;
    }
    while (!connectionInfo.getSSID().contains(ssid) ||
    connectionInfo.getSupplicantState() != SupplicantState.COMPLETED ||
    ssid.contains("DoPool") ? !getWifiInfoHint(connectionInfo) : false) {
    sendMsg(connectionInfo.getSSID() + "dd" + ssid + connectionInfo.getSupplicantState() + getWifiInfoHint(connectionInfo));
    connectionInfo = wifiManager.getConnectionInfo();
    try {
    num++;
    if (num == sum) {
    sendMsg(ssid + "exception");
    return;
    }
  51.  
  52. // 为了避免程序一直while循环,让它睡个100毫秒检测……
    Thread.sleep(200);
    } catch (InterruptedException ie) {
    }
    }
  53.  
  54. for (int i = 0; i < saveConfigureNetworks.size(); i++) {
    wifiManager.addNetwork(saveConfigureNetworks.get(i));
    }
  55.  
  56. sendMsg(connectionInfo.toString());
    sendMsg(ssid + "连接成功!");
    } catch (Exception e) {
    // TODO: handle exception
    sendMsg(ssid + "exception");
    e.printStackTrace();
    }
    }
    }
  57.  
  58. private static boolean isHexWepKey(String wepKey) {
    final int len = wepKey.length();
  59.  
  60. // WEP-40, WEP-104, and some vendors using 256-bit WEP (WEP-232?)
    if (len != 10 && len != 26 && len != 58) {
    return false;
    }
  61.  
  62. return isHex(wepKey);
    }
  63.  
  64. private static boolean isHex(String key) {
    for (int i = key.length() - 1; i >= 0; i--) {
    final char c = key.charAt(i);
    if (!(c >= '0' && c <= '9' || c >= 'A' && c <= 'F' || c >= 'a'
    && c <= 'f')) {
    return false;
    }
    }
    return true;
    }
  65.  
  66. public List<WifiConfiguration> cleanWifiConfiguredNetworks(String ssid) {
    List<WifiConfiguration> configuredNetworks = wifiManager
    .getConfiguredNetworks();
  67.  
  68. for (int i = 0; i < configuredNetworks.size(); i++) {
    wifiManager.removeNetwork(configuredNetworks.get(i).networkId);
    }
    return configuredNetworks;
    }
  69.  
  70. ArrayList<ScanResult> list;
  71.  
  72. public List<ScanResult> getNoDopoolWifi() {
    List<ScanResult> mSortWifi = getSortWifi();
    //去掉带Dopool的wifi
    for (int i = 0; i < mSortWifi.size(); i++) {
    if (mSortWifi.get(i).SSID.contains("DoPool")) {
    mSortWifi.remove(i);
    }
    }
    return mSortWifi;
    }
  73.  
  74. public List<ScanResult> getSortWifi() {
  75.  
  76. wifiManager.startScan();
    list = (ArrayList<ScanResult>) wifiManager.getScanResults();
    ArrayList<ScanResult> scanResults = new ArrayList<>();
  77.  
  78. //去掉重复的WiFi SSID的名字
    for (int i = 0; i < list.size(); i++) {
    if (list.get(i).SSID.equals("") || list.get(i).frequency > 3000) {
    continue;
    }
  79.  
  80. for (int j = 0; j <= scanResults.size(); j++) {
    if (j == scanResults.size()) {
    scanResults.add(list.get(i));
    break;
    } else if (scanResults.get(j).SSID.equals(list.get(i).SSID)) {
    break;
    }
    }
    }
    //按照信号强度排序
    for (int i = 0; i < scanResults.size(); i++) {
    for (int j = 0; j < scanResults.size(); j++) {
    if (scanResults.get(i).level > scanResults.get(j).level) {
    ScanResult temp = null;
    temp = scanResults.get(i);
    scanResults.set(i, scanResults.get(j));
    scanResults.set(j, temp);
    }
    }
    }
    return scanResults;
    }
  81.  
  82. //通过反射方法调用hide方法
    public boolean getWifiInfoHint(WifiInfo connectionInfo) throws InstantiationException {
    Class aClass = connectionInfo.getClass();
    try {
    Method getMeteredHint = aClass.getDeclaredMethod("getMeteredHint");
    getMeteredHint.setAccessible(true);
    Object invoke = getMeteredHint.invoke(connectionInfo);
    return (boolean) invoke;
    } catch (NoSuchMethodException e) {
    e.printStackTrace();
    } catch (IllegalAccessException e) {
    e.printStackTrace();
    } catch (InvocationTargetException e) {
    e.printStackTrace();
    }
    return false;
    }
  83.  
  84. }

  

Android WiFi使用记录的更多相关文章

  1. Android WiFi 日志记录(ASSOC_REJECT)

    记录Android N关联拒绝之后的相关的log. 10-26 20:35:35.844 2215 2215 D wpa_supplicant: * bssid_hint=44:48:c1:d6:57 ...

  2. Android WiFi 日志记录(四次握手)

    记录一下四次握手的log. PMK: PMK(Pairwise Master Key,成对主密钥 STA和AP得到PMK后,将进行密匙派生以得到PTK.最后,PTK被设置到硬件中, 用于数据的加解密. ...

  3. S3c6410 平台 Android系统的Wi-Fi调试记录

    硬件平台:S3c6410 操作系统:Android 网卡芯片:GH381(SDIO接口 sdio8688) 1.SDIO驱动 因为是SDIO接口,所以请先保证mmc驱动(代码在“kernel\driv ...

  4. Android WIFI 分析(一)

    本文基于<深入理解Android WiFi NFC和GPS 卷>和 Android N 代码结合分析   WifiService 是 Frameworks中负责wifi功能的核心服务,它主 ...

  5. android wifi P2P CONNECT, INVITE和JOIN流程选择

    android wifi P2P CONNECT, INVITE和JOIN流程选择

  6. android wifi ANR问题分析总结

    android wifi ANR问题分析总结 1 看看main进程阻塞在那里? 2 调用关系的函数阻塞在那里? 3 最终阻塞函数的阻塞前的log以及状态

  7. arcgis android 图上记录gps轨迹

    原文  arcgis android 图上记录gps轨迹 public class MainActivity extends Activity { MapView mMapView; Location ...

  8. android wifi驱动移植详细过程

    转自:http://bbs.imp3.net/thread-10558924-1-1.html 对于刚入手android没多久的人来说,android wifi 驱动的移植确实还是有难度的,不过参考了 ...

  9. Android WIFI 启动流程(TIP^^)

    前几天因为解决一堆Bug,没时间写.我不会每天都写,就是为了存档一些资料. 内容来源:工作中接触到的+高手博客+文档(Books)=自己理解 仅限参考^^ 此博客是上一个<<Android ...

随机推荐

  1. C语言解释器的实现--存储结构(一)

    目录: 1. 内存池 2. 栈 3. Hash表 1.内存池  在一些小的程序里,没什么必要添加内存管理模块在里面.但是对于比较复杂的代码,如果需要很多的内存操作,那么加入自己的内存管理是有必要的.至 ...

  2. Linux系统启动全过程

    分为两部分,第一部分是硬件本身需要加载的信息,之后才是加载Linux相关信息,因为有装有双系统的机器嘛 1.计算机加电 2.BIOS开始运行,检测硬件:cpu.内存.硬盘等 3.BIOS读取CMOS存 ...

  3. 自已封装Ajax方法

    function createXHR() { var request; if (typeof (XMLHttpRequest) == 'undefined') { request = new Acti ...

  4. hibernate 学习 五 hibernate核心接口

    一 Configuration接口 Configuration对象只存在于系统的初始化阶段.配置相关. 配置文件可以使用默认的路径,也可以指定路径. Configuration config = ne ...

  5. Linux Ctrl+Z的使用方法

    假设你发现前台运行的一个程序需要很长的时间,但是需要干其他的事情,你就可以用 Ctrl-Z ,终止这个程序,然后可以看到系统提示: [1]+ Stopped /root/bin/rsync.sh 然后 ...

  6. Request.UrlReferrer 实现页面刷新

    在使用Ajax 异步提交表单的时候,需要返回某些状态信息.但如果把需要返回的如分页.过滤的参数写在控制器的参数里面,会比较繁琐. 因此,1.可以在控制器里面使用 Request 对象的请求的URL. ...

  7. ASP.NET Core会议管理平台实战_汇总贴

    ASP.NET Core会议管理平台实战 课程地址:https://ke.qq.com/course/389673?from=800004097#term_id=100464670 ASP.NET C ...

  8. Identity Server 4 原理和实战(完结)_----选看 OpenId Connect 简介

    Identity Procider:身份提供商

  9. 如何将excel中的一个表格内容转成xml格式的文件

    转自:http://www.cnblogs.com/sansi/archive/2012/02/06/2340471.html 感谢作者,解决了折磨我几天的问题,顿时心情开朗~ ----------- ...

  10. MessageFomat学习

    MessageFomat 提供了一种以与语言无关的方式生成连接消息的方法. 用它来构造消息,显示给最终用户. 1.MessageFormat的格式 MessageFormatPattern:Forma ...