天天看点

Android/安卓开发之WIFI的基本应用

本文没有涉及到连接WIFI之后进行通讯,若有这方面的想法(例如两个客户端连接至同一WIFI后进行通讯),请关注后续文章一起讨论。

其实关于WIFI的开发的文章也非常的多,但是大部分只是简单的例子,不够全面,我这里是想写一个比较完整的WIFI应用,主要功能:

1.能够打开/关闭WIFI

2.能够扫面wifi并获取扫描结果

3.能够连接wifi,无论是什么加密方式

4.能够监听连接状态,如正在连接、正在获取ip、密码错误等

5.能够锁定wifi

6.能获取wifi的加密方式

7.开启热点

8.等等,大部分wifi操作常用的功能...

至于开发中用的几个相关类我就不做过多介绍了,网上比比皆是,还不了解的可以先看一下其他博客的介绍或者官方文档。

我尽量在代码中增加了一些注释,还是那句话:我还是个安卓小白,错误在所难免,如果有错误,希望大家多多指点。

一般使用WIFI流程:

1.打开wifi

1.1 状态监听

2.扫描wifi

3.连接wifi

4.关闭wifi

其中连接需要分几种情况:

1.如果是之前已经保存,直接连接

2.如果没有保存,必须先进行配置,再连接

2.1配置需要区分三种加密方式:无密码、WEP、WPA

3.WPS连接

那么就来打造一个简单demo,按照以上的步骤来。

开发流程

我们为了以后使用方便,直接编写一个wifi管理类,然后在activity直接调用对应方法就行了。下面着手进行这个类的编写:

0.在开始开发之前我们需要先配置相应的权限,如果是Android N以上级的动态申请位置权限哦

<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
    <!-- 在android N 以上 需要添加位置权限 -->
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
           

然后先看看我们需要准备什么全局变量

private WifiManager mWifiManager;//wifi管理器
    private List<ScanResult> mScanResults;//扫描结果
    private Context mContext;
    private WifiStateReceiver mReceiver;//广播接收器
    private WifiStateChangeListener mWifiStateChangeListener;//
    private WifiManager.WifiLock mWifiLock;//WIFI锁
    private static WiFiAdmin mWifiAdmin;//单利模式,
           

1.第一步,初始化wifi管理器并打开wifi

初始化

/***
     * 构造方法  - - 由于使用单例,所以设为私有
     * @param context
     */
    private WiFiAdmin(Context context) {
        mContext = context;
        //如果使用activity的context则不能访问存储空间,在版本大于Android N时,因此使用全局的Context
        mWifiManager = (WifiManager) mContext.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
        mWifiLock = mWifiManager.createWifiLock("mlock");
    }
           

打开wifi

public void openWifi() {
        if (!mWifiManager.isWifiEnabled()) {
            mWifiManager.setWifiEnabled(true);
        }
    }
           

2.注册广播,接收wifi的一些状态,例如正在连接、正在获取ip地址、断开连接等

private void registerWifiRecv() {
        //注册广播
        mReceiver = new WifiStateReceiver();
        IntentFilter mFilter = new IntentFilter();
        mFilter.addAction(WifiManager.RSSI_CHANGED_ACTION); //信号强度变化
        mFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION); //网络状态变化
        mFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION); //wifi状态,是否连上,密码
        mFilter.addAction(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION); //是不是正在获得IP地址
        mFilter.addAction(WifiManager.NETWORK_IDS_CHANGED_ACTION);
        mFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
        mContext.registerReceiver(mReceiver, mFilter);
        isRegisterRecv = true;
    }
           

3.既然注册了广播,那么我们肯定要处理对应结果

class WifiStateReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (!isRegisterRecv) return;//没注册监听就没必要执行之后的逻辑
            String action = intent.getAction();
            switch (action) {
                case WifiManager.RSSI_CHANGED_ACTION:
                    //信号强度变化
                    mWifiStateChangeListener.onSignalStrengthChanged(getStrength(context));
                    break;
                case WifiManager.NETWORK_STATE_CHANGED_ACTION:
                    NetworkInfo info = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
                    if (info.getDetailedState().equals(NetworkInfo.DetailedState.DISCONNECTED)) {
                        //wifi已断开
                        mWifiStateChangeListener.onWifiDisconnect();
                    } else if (info.getDetailedState().equals(NetworkInfo.DetailedState.CONNECTING)) {
                        //正在连接...
                        mWifiStateChangeListener.onWifiConnecting();
                    } else if (info.getDetailedState().equals(NetworkInfo.DetailedState.CONNECTED)) {
                        //连接到网络
                        mWifiStateChangeListener.onWifiConnected();
                    }else if(info.getDetailedState().equals(NetworkInfo.DetailedState.OBTAINING_IPADDR)){
                        //正在获取IP地址
                        mWifiStateChangeListener.onWifiGettingIP();
                    }else if(info.getDetailedState().equals(NetworkInfo.DetailedState.FAILED)){
                        //连接失败
                    }

                    break;
                case WifiManager.WIFI_STATE_CHANGED_ACTION:
                    int wifiState = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, 0);
                    switch (wifiState) {
                        case WifiManager.WIFI_STATE_ENABLING:
                            //wifi正在启用
                            mWifiStateChangeListener.onWifiEnabling();
                            break;
                        case WifiManager.WIFI_STATE_ENABLED:
                            //Wifi已启用
                            mWifiStateChangeListener.onWifiEnable();
                            break;
                    }
                    break;
                case WifiManager.SUPPLICANT_STATE_CHANGED_ACTION:
                    int error = intent.getIntExtra(WifiManager.EXTRA_SUPPLICANT_ERROR, -100);
                    LogUtil.log("密码认证错误:"+error+"\n");
                    if (error==WifiManager.ERROR_AUTHENTICATING){
                        //wifi密码认证错误!
                        mWifiStateChangeListener.onPasswordError();
                    }
                    break;
                case WifiManager.NETWORK_IDS_CHANGED_ACTION:
                    //已经配置的网络的ID可能发生变化时
                    mWifiStateChangeListener.onWifiIDChange();
                    break;
                case ConnectivityManager.CONNECTIVITY_ACTION:
                    //连接状态发生变化,暂时没用到
                    int type = intent.getIntExtra(ConnectivityManager.EXTRA_NETWORK_TYPE,0);
                    break;
                default:
                    break;
            }
        }
    }

    /**
     * 计算信号强度
     *
     * @param context 含有WIFI信息的资源对象
     * @return 信号强度
     */
    private int getStrength(Context context) {
        WifiInfo info = getConnectInfo();
        if (info.getBSSID() != null) {
            int strength = WifiManager.calculateSignalLevel(info.getRssi(), 5);
            // 链接速度
//			int speed = info.getLinkSpeed();
//			// 链接速度单位
//			String units = WifiInfo.LINK_SPEED_UNITS;
//			// Wifi源名称
//			String ssid = info.getSSID();
            return strength;
        }
        return 0;
    }
           

4.然后发起扫描并获取扫描结果

/**
     * 启动扫描,扫描前应使用 {@link #getWifiState()}判断WIFI是否可用
     * 或者在回调函数 mWifiStateChangeListener.onWifiEnable() 调用
     */
    public void startWifiScan() {
        mWifiManager.startScan();
        mScanResults = mWifiManager.getScanResults();
    }
           

5.获取到扫描结果之后,我们就可以发起连接了。对于之前已经连接过的wifi,可以直接这样:

public boolean connectWifi(int netId) {
        return mWifiManager.enableNetwork(netId, true);
    }
           

那么netid怎么来的?这就需要以下这些操作,首先要获取已经配置过(就是之前连接过的)的wifi

public WifiInfo getConnectInfo() {
        return mWifiManager.getConnectionInfo();
    }
           

使用以下方法获取netid,如果返回-1,证明没有配置,需要配置才能发起连接请求。

public int isWifiConfig(String ssid) {
        List<WifiConfiguration> lists = getConfigWifiList();
        for (WifiConfiguration c : lists) {
            if (c.SSID.equals("\"" + ssid + "\"")) {
                return c.networkId;
            }
        }
        return -1;
    }
           

而如果是连接新的wifi(上面的方法返回-1)需要先配置对应的参数,例如密码之类的才能发起连接

public int configWifi(String ssid, String pwd,int security) {
        int result = -1;
        for (ScanResult s : mScanResults) {
            if (s.SSID.equals(ssid)) {
                WifiConfiguration config = new WifiConfiguration();
                config.SSID = "\"" + ssid + "\"";
                config.hiddenSSID = false;
                config.status = WifiConfiguration.Status.ENABLED;
                switch (security){
                    case SECURITY_NONE:
                        config.wepKeys[0] ="\""+pwd+"\"";
                        config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
                        config.wepTxKeyIndex = 0;
                        break;
                    case SECURITY_WEP:
                        config.wepKeys[0]= "\""+pwd+"\"";
                        config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
                        config.wepTxKeyIndex = 0;
                        break;
                    case SECURITY_WPA:
                    case SECURITY_WPA_PSK:
                        config.preSharedKey = "\"" + pwd + "\"";
                        break;
                    default:
                        break;
                }
                result = mWifiManager.addNetwork(config);
                break;
            }
        }
        return result;
    }
           

配置完成再次调用获取netid的方法就可以获取netid了 

6.经过步骤5,我们已经能连接上wifi,接下来就可以退出程序,愉快的上网了。当然,如果不需要wifi了,别忘了关闭哦~

public void closeWifi() {
        if (mWifiManager.isWifiEnabled()) {
            mWifiManager.setWifiEnabled(false);
        }
    }
           

上面是简化后的步骤,像在配置时,还需要判断有没有加密,加密方式是什么,怎么获取加密方式等都省略了。全部了解请看下方全部代码哦~

下面有关于wifi的更多操作,也有要共享wifi的法等。

总体就是这种流程,按照这个流程来调用对应的方法就差不多了。记得根据步骤来阅读,才不会觉得混乱。下面是wifi管理类的全部代码,我整合大部分需要用到的功能:

package cn.small_qi.wificonn;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

/**
 * Created by small_qi on 2017/7/21.
 */
public class WiFiAdmin {
    private WifiManager mWifiManager;
    private List<ScanResult> mScanResults;
    private Context mContext;
    private WifiStateReceiver mReceiver;
    private WifiStateChangeListener mWifiStateChangeListener;
    private WifiManager.WifiLock mWifiLock;
    private static WiFiAdmin mWifiAdmin;
    private boolean isRegisterRecv;
    private boolean isWifiLock;

    public static final int SECURITY_WEP = 3;//WEP
    public static final int SECURITY_WPA = 2;//WPA/WPA2
    public static final int SECURITY_WPA_PSK = 1;//WPA-PSK/WPA2-PSK
    public static final int SECURITY_NONE = 0;//没有密码
    public static final int ORDER_SMART_SORT = 0;//智能排序,
    public static final int ORDER_SIGNAL_LEVEL_SORT = 1;//信号强度排序

    /***
     * 构造方法  - - 由于使用单例,所以设为私有
     * @param context
     */
    private WiFiAdmin(Context context) {
        mContext = context;
        //如果使用activity的context则不能访问存储空间,在版本大于Android N时,因此使用全局的Context
        mWifiManager = (WifiManager) mContext.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
        mWifiLock = mWifiManager.createWifiLock("mlock");
    }

    /**
     * 对外面公开的获取实例的方法
     *
     * @param context
     * @return 新建的
     */
    public static WiFiAdmin getInstance(Context context) {
        if (mWifiAdmin == null) {
            mWifiAdmin = new WiFiAdmin(context);
        }
        return mWifiAdmin;
    }

    /**
     * 设置网络状态监听
     * 如果设置了监听,一定要在调用的Activity/Fragment
     * 的生命周期结束时调用{@link #removeWifiStateChangeListener()}
     * 避免内存泄漏
     */
    public void addWifiStateChangeListener(WifiStateChangeListener wscListener) {
        if (isRegisterRecv) return;
        registerWifiRecv();
        this.mWifiStateChangeListener = wscListener;
    }

    private void registerWifiRecv() {
        //注册广播
        mReceiver = new WifiStateReceiver();
        IntentFilter mFilter = new IntentFilter();
        mFilter.addAction(WifiManager.RSSI_CHANGED_ACTION); //信号强度变化
        mFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION); //网络状态变化
        mFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION); //wifi状态,是否连上,密码
        mFilter.addAction(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION); //是不是正在获得IP地址
        mFilter.addAction(WifiManager.NETWORK_IDS_CHANGED_ACTION);
        mFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
        mContext.registerReceiver(mReceiver, mFilter);
        isRegisterRecv = true;
    }

    public void removeWifiStateChangeListener() {
        if (!isRegisterRecv) return;
        isRegisterRecv = false;
        mContext.unregisterReceiver(mReceiver);
    }


    public void openWifi() {
        if (!mWifiManager.isWifiEnabled()) {
            mWifiManager.setWifiEnabled(true);
        }
    }

    public void closeWifi() {
        if (mWifiManager.isWifiEnabled()) {
            mWifiManager.setWifiEnabled(false);
        }
    }

    public boolean lockWifi() {
        if (mWifiLock == null) {
            return false;
        }
        mWifiLock.acquire();
        isWifiLock = true;
        return true;
    }

    public boolean unLockWifi() {
        if (mWifiLock == null) {
            return false;
        }
        mWifiLock.release();
        isWifiLock = false;
        return true;
    }

    public boolean isWifiLock() {
        return isWifiLock;
    }

    /**
     * 获取网卡状态
     *
     * @return
     */
    public int getWifiState() {
        /**
         * WIFI网卡的状态是由一系列的整形常量来表示的。
           1.WIFI_STATE_DISABLED : WIFI网卡不可用(1)
           2.WIFI_STATE_DISABLING : WIFI网卡正在关闭(0)
           3.WIFI_STATE_ENABLED : WIFI网卡可用(3)
           4.WIFI_STATE_ENABLING : WIFI网正在打开(2) (WIFI启动需要一段时间)
           5.WIFI_STATE_UNKNOWN  : 未知网卡状态
         */
        if (mWifiManager.isWifiEnabled()) {
            return mWifiManager.getWifiState();
        }
        return -1;
    }

    /**
     * 启动扫描,扫描前应使用 {@link #getWifiState()}判断WIFI是否可用
     * 或者在回调函数 mWifiStateChangeListener.onWifiEnable() 调用
     */
    public void startWifiScan() {
        mWifiManager.startScan();
        mScanResults = mWifiManager.getScanResults();
    }


    /**
     * 获取排序后的扫描结果
     *
     * @param order 排序方式
     *              1.只按信号强度排序
     *              2.已经保存的在前面,其他按强度排序
     */
    public List<ScanResult> getOrderScanResults(int order) {
        List<ScanResult> sortResult = mScanResults;
        if (order == ORDER_SIGNAL_LEVEL_SORT) {
            levelSort(sortResult);
        } else if (order == ORDER_SMART_SORT) {
            smartSort(sortResult);
        }
        return null;
    }

    private void levelSort(List<ScanResult> sortResult) {
        Collections.sort(sortResult, new Comparator<ScanResult>() {
            @Override
            public int compare(ScanResult o1, ScanResult o2) {
                return o1.level - o2.level;
            }
        });
    }

    private void smartSort(List<ScanResult> sortResult) {
        Collections.sort(sortResult, new Comparator<ScanResult>() {
            @Override
            public int compare(ScanResult o1, ScanResult o2) {
                if (isWifiConfig(o1.SSID) > 0 && isWifiConfig(o2.SSID) > 0) {
                    return o1.level - o2.level;
                } else if (isWifiConfig(o1.SSID) > 0 || isWifiConfig(o2.SSID) > 0) {
                    return isWifiConfig(o1.SSID) - isWifiConfig(o2.SSID);
                } else {
                    return o1.level - o2.level;
                }
            }
        });
    }

    /**
     * 获取扫描结果
     */
    public List<ScanResult> getScanResults() {
        return mScanResults;
    }

    /**
     * 获取已经保存的wifi列表
     */
    public List<WifiConfiguration> getConfigWifiList() {
        List<WifiConfiguration> configurations = mWifiManager.getConfiguredNetworks();
        return configurations;
    }

    /**
     * 判断该wifi是否已经保存
     *
     * @return 返回-1表示没保存,已经保存返回网络id
     */
    public int isWifiConfig(String ssid) {
        List<WifiConfiguration> lists = getConfigWifiList();
        for (WifiConfiguration c : lists) {
            if (c.SSID.equals("\"" + ssid + "\"")) {
                return c.networkId;
            }
        }
        return -1;
    }

    /**
     * 配置没有保存的wifi
     * 一般只要配置一下几个属性就可以了,其他使用其,默认值
     * @param scanResult
     * @param pwd
     * @return 保存成功则返回该Wifi的网络id,否则-1
     */
    public int configWifi(ScanResult scanResult, String pwd,int security) {
        return configWifi(scanResult.SSID,pwd,security);

    }

    /**
     * 配置方法重载
     */
    public int configWifi(String ssid, String pwd,int security) {
        int result = -1;
        for (ScanResult s : mScanResults) {
            if (s.SSID.equals(ssid)) {
                WifiConfiguration config = new WifiConfiguration();
                config.SSID = "\"" + ssid + "\"";
                config.hiddenSSID = false;
                config.status = WifiConfiguration.Status.ENABLED;
                switch (security){
                    case SECURITY_NONE:
                        config.wepKeys[0] ="\""+pwd+"\"";
                        config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
                        config.wepTxKeyIndex = 0;
                        break;
                    case SECURITY_WEP:
                        config.wepKeys[0]= "\""+pwd+"\"";
                        config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
                        config.wepTxKeyIndex = 0;
                        break;
                    case SECURITY_WPA:
                    case SECURITY_WPA_PSK:
                        config.preSharedKey = "\"" + pwd + "\"";
                        break;
                    default:
                        break;
                }
                result = mWifiManager.addNetwork(config);
                break;
            }
        }
        return result;
    }

    /**
     * 配置方法重载,用于更复杂的配置
     */
    public int configWifi(WifiConfiguration config) {
        return mWifiManager.addNetwork(config);
    }

    /**
     * 获取加秘方式
     */
    public int getSecurity(ScanResult scanResult) {
        return getSecurity(scanResult.capabilities);
    }

    /**
     * 获取加秘方式
     *
     * @param capabilities
     * @return 加密类型, 具体类型请查看: {@link #SECURITY_NONE}{@link #SECURITY_WEP}{@link #SECURITY_WPA}{@link #SECURITY_WPA_PSK}
     */
    public int getSecurity(String capabilities) {
        if (capabilities.contains("WEP")) {
            return SECURITY_WEP;
        } else if (capabilities.contains("WPA")) {
            if (capabilities.contains("PSK"))
                return SECURITY_WPA_PSK;
            return SECURITY_WPA;
        } else {
            return SECURITY_NONE;
        }
    }

    /**
     * 删除/忘记一个wifi(也就是通常的不保存)
     *
     * @param ssid 要忘记网络名成
     * @return 执行结果
     */
    public boolean forgetWifi(String ssid) {
        for (WifiConfiguration c : getConfigWifiList()) {
            if (c.SSID.equals("\"" + ssid + "\"")) {
                return mWifiManager.removeNetwork(c.networkId);
            }
        }
        return false;
    }

    /**
     * 断开连接
     * @return
     */
    public boolean disconnectWifi(){
        return mWifiManager.disableNetwork(getConnectInfo().getNetworkId());
       // mWifiManager.disconnect();//断流
    }

    /**
     * 连接wifi
     *
     * @param netId wifi网络id
     * @return 连接结果
     */
    public boolean connectWifi(int netId) {
        return mWifiManager.enableNetwork(netId, true);
    }

    /**
     * 获取已经连接的WIFI信息
     */
    public WifiInfo getConnectInfo() {
        return mWifiManager.getConnectionInfo();
    }

    /**
     * IP 地址转换
     *
     * @param ip 转换前的IP
     * @return 转换后的IP
     */
    public static String parseIPAddressToString(int ip) {
        return ((ip & 0xff) + "." + (ip >> 8 & 0xff) + "." + (ip >> 16 & 0xff) + "." + (ip >> 24 & 0xff));
    }

    /**
     * 广播监听内部类
     */
    class WifiStateReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (!isRegisterRecv) return;//没注册监听就没必要执行之后的逻辑
            String action = intent.getAction();
            switch (action) {
                case WifiManager.RSSI_CHANGED_ACTION:
                    //信号强度变化
                    mWifiStateChangeListener.onSignalStrengthChanged(getStrength(context));
                    break;
                case WifiManager.NETWORK_STATE_CHANGED_ACTION:
                    NetworkInfo info = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
                    if (info.getState().equals(NetworkInfo.State.DISCONNECTED)) {
                        //wifi已断开
                        mWifiStateChangeListener.onWifiDisconnect();
                    } else if (info.getState().equals(NetworkInfo.State.CONNECTING)) {
                        //正在连接...
                        mWifiStateChangeListener.onWifiConnecting();
                    } else if (info.getState().equals(NetworkInfo.State.CONNECTED)) {
                        //连接到网络
                        mWifiStateChangeListener.onWifiConnected();
                    }else if(info.getDetailedState().equals(NetworkInfo.DetailedState.OBTAINING_IPADDR)){
                        //正在获取IP地址
                        mWifiStateChangeListener.onWifiGettingIP();
                    }

                    break;
                case WifiManager.WIFI_STATE_CHANGED_ACTION:
                    int wifiState = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, 0);
                    switch (wifiState) {
                        case WifiManager.WIFI_STATE_ENABLING:
                            //wifi正在启用
                            mWifiStateChangeListener.onWifiEnabling();
                            break;
                        case WifiManager.WIFI_STATE_ENABLED:
                            //Wifi已启用
                            mWifiStateChangeListener.onWifiEnable();
                            break;
                    }
                    break;
                case WifiManager.SUPPLICANT_STATE_CHANGED_ACTION:
                    int error = intent.getIntExtra(WifiManager.EXTRA_SUPPLICANT_ERROR, 0);
                    switch (error) {
                        case WifiManager.ERROR_AUTHENTICATING:
                            //wifi密码认证错误!
                            mWifiStateChangeListener.onPasswordError();
                            break;
                        default:
                            break;
                    }
                    break;
                case WifiManager.NETWORK_IDS_CHANGED_ACTION:
                    //已经配置的网络的ID可能发生变化时
                    mWifiStateChangeListener.onWifiIDChange();
                    break;
                case ConnectivityManager.CONNECTIVITY_ACTION:
                    //连接状态发生变化,暂时没用到
                    break;
                default:
                    break;
            }
        }
    }

    /**
     * 计算信号强度
     *
     * @param context 含有WIFI信息的资源对象
     * @return 信号强度
     */
    private int getStrength(Context context) {
        WifiInfo info = getConnectInfo();
        if (info.getBSSID() != null) {
            int strength = WifiManager.calculateSignalLevel(info.getRssi(), 5);
            // 链接速度
//			int speed = info.getLinkSpeed();
//			// 链接速度单位
//			String units = WifiInfo.LINK_SPEED_UNITS;
//			// Wifi源名称
//			String ssid = info.getSSID();
            return strength;
        }
        return 0;
    }

    /**
     * WIFI状态变化回调接口
     */
    public interface WifiStateChangeListener {
        //void onRssiChanged();
        //void onNetWorkStateChanged();
        //void onWifiStateChanged();
        //void onSupplicantStateChanged();
        // void NetWorkIDSChange();
        void onSignalStrengthChanged(int level);

        void onWifiConnecting();

        void onWifiGettingIP();

        void onWifiConnected();

        void onWifiDisconnect();

        void onWifiEnabling();

        void onWifiEnable();

        void onPasswordError();

        void onWifiIDChange();
        //void onWifiLock(int isLock);

    }


    //-------------------------------以下部分为开启热点-------------------------------------

    /**
     * 创建热点
     *
     * @param mSSID   热点名称
     * @param mPasswd 热点密码
     * @param isOpen  是否是开放热点
     */
    public void startWifiAp(String mSSID, String mPasswd, boolean isOpen) {
        Method method1 = null;
        try {
            method1 = mWifiManager.getClass().getMethod("setWifiApEnabled",
                    WifiConfiguration.class, boolean.class);
            WifiConfiguration netConfig = new WifiConfiguration();

            netConfig.SSID = mSSID;
            netConfig.preSharedKey = mPasswd;
            netConfig.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
            netConfig.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
            netConfig.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
            if (isOpen) {
                netConfig.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
            } else {
                netConfig.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
            }
            netConfig.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
            netConfig.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
            netConfig.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
            netConfig.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
            method1.invoke(mWifiManager, netConfig, true);

        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取热点名
     **/
    public String getApSSID() {
        try {
            Method localMethod = this.mWifiManager.getClass().getDeclaredMethod("getWifiApConfiguration", new Class[0]);
            if (localMethod == null) return null;
            Object localObject1 = localMethod.invoke(this.mWifiManager, new Object[0]);
            if (localObject1 == null) return null;
            WifiConfiguration localWifiConfiguration = (WifiConfiguration) localObject1;
            if (localWifiConfiguration.SSID != null) return localWifiConfiguration.SSID;
            Field localField1 = WifiConfiguration.class.getDeclaredField("mWifiApProfile");
            if (localField1 == null) return null;
            localField1.setAccessible(true);
            Object localObject2 = localField1.get(localWifiConfiguration);
            localField1.setAccessible(false);
            if (localObject2 == null) return null;
            Field localField2 = localObject2.getClass().getDeclaredField("SSID");
            localField2.setAccessible(true);
            Object localObject3 = localField2.get(localObject2);
            if (localObject3 == null) return null;
            localField2.setAccessible(false);
            String str = (String) localObject3;
            return str;
        } catch (Exception localException) {
        }
        return null;
    }


    /**
     * 检查是否开启Wifi热点
     *
     * @return
     */
    public boolean isWifiApEnabled() {
        try {
            Method method = mWifiManager.getClass().getMethod("isWifiApEnabled");
            method.setAccessible(true);
            return (boolean) method.invoke(mWifiManager);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 关闭热点
     */
    public void closeWifiAp() {
        WifiManager wifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
        if (isWifiApEnabled()) {
            try {
                Method method = wifiManager.getClass().getMethod("getWifiApConfiguration");
                method.setAccessible(true);
                WifiConfiguration config = (WifiConfiguration) method.invoke(wifiManager);
                Method method2 = wifiManager.getClass().getMethod("setWifiApEnabled", WifiConfiguration.class, boolean.class);
                method2.invoke(wifiManager, config, false);
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 开热点手机获得其他连接手机IP的方法
     *
     * @return 其他手机IP 数组列表
     */
    public ArrayList<String> getConnectedIP() {
        ArrayList<String> connectedIp = new ArrayList<String>();
        try {
            BufferedReader br = new BufferedReader(new FileReader(
                    "/proc/net/arp"));
            String line;
            while ((line = br.readLine()) != null) {
                String[] splitted = line.split(" +");
                if (splitted != null && splitted.length >= 4) {
                    String ip = splitted[0];
                    if (!ip.equalsIgnoreCase("ip")) {
                        connectedIp.add(ip);
                    }
                }
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return connectedIp;
    }


}
           

里面还少了一种WPS连接,这个如果需要,大家在自己添加上去了。

整个流程下来代码还是挺多的,至于哪些地方需要注意的一时半会也说不完,也忘记了我开发过程遇到哪些问题了~~~间歇性失忆,啊哈哈哈

但是我还是要说一下:

1.可能会有人注意到,为什么我使用ssid时,有时是直接使用,有时又需要加上双引号"\""+ ssid + "\""这样子,

这是因为如果你是从 WifiConfiguration 中获取到的ssid的话,他默认会有双引号,但是从ScanResult等获取到ssid是没有双引号的,

所以为了匹配只好加上了。因此,在配置 WifiConfiguration时ssid和密码都需要我们手动加上双引号,他默认格式是这样,不按照这个来会出现错误。

2.关于AP方面,目前开放的方法能直接开启,所以这部分的内容全是通过反射机制进行的,我也是参考了一些博客写的,具体我自己没试过。

3.其他有疑问的话,就在评论中提问吧~这样方便大神们给你回复。

后面我写了一个测试小程序,除了AP没有测试外,其他功能正常使用,和系统的wifi功能差不多哦~

下面是几张截图:

扫描-获取扫描结果

Android/安卓开发之WIFI的基本应用

点击连接(已经保存好的)wifi - -分别会显示正在连接...- - 正在获取ip...  - - 已连接

Android/安卓开发之WIFI的基本应用

连接没有保存的wifi --弹出输入密码框(如果是没加密不会弹出,而是直接连接),确认之后就连接

Android/安卓开发之WIFI的基本应用

如果点击已经连接的wifi,就可以选择断开还是忘记(不保存)

Android/安卓开发之WIFI的基本应用

大概就这样了。接下去可能会写连接上wifi之后进行区域网通讯相关的。

完整demo github地址:https://github.com/nongchengqi/WifiConn2

附上activity的代码:

package cn.small_qi.wificonn;

import android.Manifest;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiInfo;
import android.os.Build;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.Toast;


public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    private ListView list;
    private WifiAdapter adapter;
    private WiFiAdmin admin;
    private static final int PERMISSION_WIFI_CODE = 1001;
    private static final int PERMISSION_FILE_CODE = 1002;
    private int curPosition=-1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            int code = ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
            if (code != PackageManager.PERMISSION_GRANTED) {
                ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, PERMISSION_FILE_CODE);
            }
        }
        initList();
        setListener();
        setStateListener();


    }


    private void initList() {
        admin = WiFiAdmin.getInstance(this);
        list = (ListView) findViewById(R.id.list);
        adapter = new WifiAdapter(this);
        list.setAdapter(adapter);
        list.setOnItemClickListener(new AdapterView.OnItemClickListener() {

            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                curPosition = position;
                final ScanResult result = adapter.getItem(position);
                if (admin.getConnectInfo().getSSID().equals("\""+result.SSID+"\"")){
                    new AlertDialog.Builder(MainActivity.this)
                            .setTitle("是否断开连接?")
                            .setPositiveButton("断开", new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialog, int which) {
                                   admin.disconnectWifi();
                                }
                            })
                            .setNegativeButton("不保存", new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialog, int which) {
                                    admin.forgetWifi(result.SSID);
                                }
                            })
                            .create().show();
                    return;
                }
                final int security =admin.getSecurity(result) ;
                int netid = admin.isWifiConfig(result.SSID);
                if ( netid == -1) {
                    if (security != WiFiAdmin.SECURITY_NONE) {
                        final EditText pwdEt = new EditText(MainActivity.this);
                        //弹出输入密码对话框
                        new AlertDialog.Builder(MainActivity.this)
                                .setView(pwdEt)
                                .setTitle("请输入密码")
                                .setPositiveButton("确定", new DialogInterface.OnClickListener() {
                                    @Override
                                    public void onClick(DialogInterface dialog, int which) {
                                        admin.configWifi(result, pwdEt.getText().toString(),security);
                                       admin.connectWifi(admin.isWifiConfig(result.SSID));
                                    }
                                })
                                .setNegativeButton("取消", null)
                                .create().show();
                    } else {
                        admin.configWifi(result, "",security);
                        admin.connectWifi(admin.isWifiConfig(result.SSID)) ;
                    }
                } else {
                    admin.connectWifi(netid);
                }
            }
        });
    }

    private void setListener() {
        findViewById(R.id.close).setOnClickListener(this);
        findViewById(R.id.open).setOnClickListener(this);
        findViewById(R.id.scan).setOnClickListener(this);
        findViewById(R.id.info).setOnClickListener(this);
        findViewById(R.id.conn).setOnClickListener(this);
    }
    private void setStateListener() {
        admin.addWifiStateChangeListener(new WiFiAdmin.WifiStateChangeListener() {
            @Override
            public void onSignalStrengthChanged(int level) {

            }

            @Override
            public void onWifiConnecting() {
                adapter.updateState(0,curPosition);
            }

            @Override
            public void onWifiGettingIP() {
                adapter.updateState(1,curPosition);
            }

            @Override
            public void onWifiConnected() {
                adapter.updateState(2,curPosition);
            }

            @Override
            public void onWifiDisconnect() {
                adapter.updateState(4,curPosition);

            }

            @Override
            public void onWifiEnabling() {

            }

            @Override
            public void onWifiEnable() {

            }

            @Override
            public void onPasswordError() {
                adapter.updateState(3,curPosition);
            }

            @Override
            public void onWifiIDChange() {

            }
        });
    }


    private void checkPermission() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            int code = ContextCompat.checkSelfPermission(this, Manifest.permission_group.LOCATION);
            if (code != PackageManager.PERMISSION_GRANTED) {
                ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION}, PERMISSION_WIFI_CODE);
            } else {
                admin.startWifiScan();
                adapter.addAllWifis(admin.getScanResults());
            }
        } else {
            admin.startWifiScan();
            adapter.addAllWifis(admin.getScanResults());
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        admin.removeWifiStateChangeListener();
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        switch (requestCode) {
            case PERMISSION_WIFI_CODE:
                if (grantResults[1] == PackageManager.PERMISSION_GRANTED) {
                    admin.startWifiScan();
                    adapter.addAllWifis(admin.getScanResults());
                }
                break;
            default:
                super.onRequestPermissionsResult(requestCode, permissions, grantResults);
                break;

        }
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.close:
                admin.closeWifi();
                break;
            case R.id.open:
                admin.openWifi();
                break;
            case R.id.scan:
                //6.0权限
                checkPermission();
                break;
            case R.id.info:
                showInfo();
                break;
            case R.id.conn:
                if (admin!=null&&admin.getConnectInfo().getIpAddress()!=0){
                    startActivity(new Intent(MainActivity.this,ConnActivity.class));
                }else{
                    Toast.makeText(this, "请先连接Wifi或者等待Wifi连接成功", Toast.LENGTH_SHORT).show();
                }
                break;
        }
    }

    private void showInfo() {
        WifiInfo info = admin.getConnectInfo();
        if (info == null) {
            Toast.makeText(MainActivity.this, "当前未连接到WIFI", Toast.LENGTH_SHORT).show();
            return;
        }
        new AlertDialog.Builder(MainActivity.this)
                .setTitle("当前连接WIFI信息:")
                .setMessage(info.getSSID() + "\n" + info.getMacAddress() + "\n" + WiFiAdmin.parseIPAddressToString(info.getIpAddress()) + "\n" +
                        info.getLinkSpeed() + "\n" + info.getBSSID() + "\n" + info.getRssi())
                .create()
                .show();
    }
}
           

xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <HorizontalScrollView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        >

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal">

            <Button
                android:id="@+id/open"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="打开" />

            <Button
                android:id="@+id/close"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="关闭" />

            <Button
                android:id="@+id/scan"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="扫描" />

            <Button
                android:id="@+id/info"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="信息" />

            <Button
                android:id="@+id/conn"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="通讯" />
        </LinearLayout>
    </HorizontalScrollView>

    <ListView
        android:id="@+id/list"
        android:layout_width="match_parent"
        android:layout_height="match_parent"></ListView>

</LinearLayout>
           

--- 转载请注明本文地址---