zoukankan      html  css  js  c++  java
  • Android WiFi使用记录

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

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

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

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

    String capabilities = scanResult.capabilities;
    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);
    }

    通过获取scanResult的capabilities来判断WiFi的加密方式


    2.连接WiFi的成功率

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

    public List<WifiConfiguration> cleanWifiConfiguredNetworks(String ssid) {
    List<WifiConfiguration> configuredNetworks = wifiManager
    .getConfiguredNetworks();

    for (int i = 0; i < configuredNetworks.size(); i++) {
    wifiManager.removeNetwork(configuredNetworks.get(i).networkId);
    }
    return configuredNetworks;
    }
    很简单直接清空了历史配置或者设置其他为不可用。

    3.wifi连接成功的监听

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

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

    connectionInfo.getSSID().contains(ssid) ||
    connectionInfo.getSupplicantState() != SupplicantState.COMPLETED

    再判断wifi的ssid以及wifimanager的状态,两条件都满足时则WiFi连接成功。
    项目需求我这接下来要进行socket通信,这种状态下获取的IP地址存在延迟增加了新的条件判断,对于wifiinfo中的MeteredHint参数额外的判断。当这变为true
    时,获取了正确IP。这个参数获取方法给hide,不能调用需反射才能成功使用代码如下:

    //通过反射方法调用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;
    }

    获取服务器的IP地址方法:
    DhcpInfo info = wifiManage.getDhcpInfo();
    String serverAddress = intToIp(info.serverAddress);

    // 将获取的int转为真正的ip地址,参考的网上的,修改了下
    private String intToIp(int i) {
    return (i & 0xFF) + "." + ((i >> 8) & 0xFF) + "." + ((i >> 16) & 0xFF) + "." + ((i >> 24) & 0xFF);
    }




    OK 结束 修改过后的全部代码如下:

    package com.dopool.usersystem.hotspot;


    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;

    import com.dopool.usersystem.Constant;
    import com.zhy.http.okhttp.utils.L;

    import java.lang.reflect.Field;
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    import java.util.ArrayList;
    import java.util.List;

    public class WifiConnector {
    public Handler mHandler;
    WifiManager wifiManager;

    /**
    * 向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);
    }
    }

    //WIFICIPHER_WEP是WEP ,WIFICIPHER_WPA是WPA,WIFICIPHER_NOPASS没有密码
    public enum WifiCipherType {
    WIFICIPHER_WEP, WIFICIPHER_WPA, WIFICIPHER_NOPASS, WIFICIPHER_INVALID
    }

    // 构造函数
    public WifiConnector(Context context) {
    // 取得WifiManager对象
    this.wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
    }

    // 提供一个外部接口,传入要连接的无线网
    public void connect(String ssid, String password, WifiCipherType type) {
    Thread thread = new Thread(new ConnectRunnable(ssid, password, type));
    thread.start();
    }

    // 查看以前是否也配置过这个网络
    private WifiConfiguration isExsits(String SSID) {
    List<WifiConfiguration> existingConfigs = wifiManager
    .getConfiguredNetworks();
    for (WifiConfiguration existingConfig : existingConfigs) {
    if (existingConfig.SSID.equals(""" + SSID + """)) {
    return existingConfig;
    }
    }
    return null;
    }


    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;
    }

    // 打开wifi功能
    private boolean openWifi() {
    boolean bRet = true;
    if (!wifiManager.isWifiEnabled()) {
    bRet = wifiManager.setWifiEnabled(true);
    }
    return bRet;
    }

    private boolean closeifi() {
    boolean bRet = true;
    if (wifiManager.isWifiEnabled()) {
    bRet = wifiManager.setWifiEnabled(false);
    }
    return bRet;
    }


    class ConnectRunnable implements Runnable {
    private String ssid;

    private String password;

    private WifiCipherType type;

    public ConnectRunnable(String ssid, String password, WifiCipherType type) {
    this.ssid = ssid;
    this.password = password;
    this.type = type;
    }

    @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) {
    }
    }

    //去掉以往的WiFi配置
    List<WifiConfiguration> saveConfigureNetworks = cleanWifiConfiguredNetworks(ssid);

    WifiConfiguration wifiConfig = createWifiInfo(ssid, password,
    type);

    if (wifiConfig == null) {
    sendMsg("wifiConfig is null!");
    return;
    }

    int netID = wifiManager.addNetwork(wifiConfig);
    boolean enabled = wifiManager.enableNetwork(netID, true);
    boolean connected = wifiManager.reconnect();

    WifiInfo connectionInfo = wifiManager.getConnectionInfo();

    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;
    }

    // 为了避免程序一直while循环,让它睡个100毫秒检测……
    Thread.sleep(200);
    } catch (InterruptedException ie) {
    }
    }

    for (int i = 0; i < saveConfigureNetworks.size(); i++) {
    wifiManager.addNetwork(saveConfigureNetworks.get(i));
    }


    sendMsg(connectionInfo.toString());
    sendMsg(ssid + "连接成功!");
    } catch (Exception e) {
    // TODO: handle exception
    sendMsg(ssid + "exception");
    e.printStackTrace();
    }
    }
    }

    private static boolean isHexWepKey(String wepKey) {
    final int len = wepKey.length();

    // WEP-40, WEP-104, and some vendors using 256-bit WEP (WEP-232?)
    if (len != 10 && len != 26 && len != 58) {
    return false;
    }

    return isHex(wepKey);
    }

    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;
    }

    public List<WifiConfiguration> cleanWifiConfiguredNetworks(String ssid) {
    List<WifiConfiguration> configuredNetworks = wifiManager
    .getConfiguredNetworks();

    for (int i = 0; i < configuredNetworks.size(); i++) {
    wifiManager.removeNetwork(configuredNetworks.get(i).networkId);
    }
    return configuredNetworks;
    }


    ArrayList<ScanResult> list;

    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;
    }


    public List<ScanResult> getSortWifi() {

    wifiManager.startScan();
    list = (ArrayList<ScanResult>) wifiManager.getScanResults();
    ArrayList<ScanResult> scanResults = new ArrayList<>();

    //去掉重复的WiFi SSID的名字
    for (int i = 0; i < list.size(); i++) {
    if (list.get(i).SSID.equals("") || list.get(i).frequency > 3000) {
    continue;
    }

    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;
    }

    //通过反射方法调用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;
    }


    }

      

  • 相关阅读:
    046 Android 给app加入百度地图
    007 Android newsClient 小实例应用
    IntelliJ IDEA(Android Studio)设置代码的快捷编辑模板Live Templates
    006 Android 利用apache tomcat在自己的电脑上搭建服务器
    005 Android HttpURLConnection的使用+Handler的原理及典型应用
    004 Andriod ListView组件的使用
    spd更改标题点击链接路径到编辑页面
    以下修改a标签的href链接和修改文字的代码
    域名不能访问,ip能访问就是dns
    删除web部件
  • 原文地址:https://www.cnblogs.com/fuccc/p/7157063.html
Copyright © 2011-2022 走看看