博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android设备wifi开发
阅读量:5977 次
发布时间:2019-06-20

本文共 7821 字,大约阅读时间需要 26 分钟。

前言

       三月份新入职的公司,公司的主要业务是只能电视应用,由于公司战略需要,准备做一个tvos,里面包含有设置的系统应用,本人分到的任务是wifi这一块开发。由于之前接手的都是移动端的开发,对于wifi这一块几乎没有接触过,所以分享出来,希望我踩过的坑,大家能避免。

正文

      wifi扫描:

首先,要对设备的网络情况就行修改,就要获得相应的权限:

复制代码

     然后,接收网络变化的广播:

public class WifiBroadcastReceiver extends BroadcastReceiver {    private IntentFilter filter;    private Context context;    private WifiStateChangeListener wifiStateChangeListener;    public WifiBroadcastReceiver(Context context) {        this.context = context;        filter = new IntentFilter();        filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);//wifi开关变化广播        filter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);//热点扫描结果通知广播        filter.addAction(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION);//—热点连接结果通知广播        filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);  //—网络状态变化广播(与上一广播协同完成连接过程通知)        filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);        context.registerReceiver(this, filter);    }    @Override    public void onReceive(Context context, Intent intent) {        String action = intent.getAction();        if (null != wifiStateChangeListener) {            wifiStateChangeListener.onWifiChange(intent);        }    }    public void unRegister() {        context.unregisterReceiver(this);    }    public void setWifiStateChangeListener(WifiStateChangeListener wifiStateChangeListener) {        this.wifiStateChangeListener = wifiStateChangeListener;    }    public interface WifiStateChangeListener {        /**         */        void onWifiChange(Intent action);    }}复制代码

通过不同广播的action,进行相应的处理:

@Overridepublic void onWifiChange(Intent action) {    switch (action.getAction()) {        case WifiManager.WIFI_STATE_CHANGED_ACTION:            checkWfiState(action);            break;        case WifiManager.SCAN_RESULTS_AVAILABLE_ACTION:            getScanResult();            break;        case WifiManager.SUPPLICANT_STATE_CHANGED_ACTION:            int error = action.getIntExtra(WifiManager.EXTRA_SUPPLICANT_ERROR, 0);            if (WifiManager.ERROR_AUTHENTICATING == error) {                toastFail();            } else {                checkWifiConnectState(action);            }            break;        default:            //网线            if (NetInfoUtil.isEthernet()) {                finish();            }            break;    }}复制代码

接下来打开wifi,

//开启或者关闭WIFIpublic void openWifi(boolean isEnable) {    if (!isEnable) {        removeConnecting();    }    wifiManager.setWifiEnabled(isEnable);}复制代码

如果wifi以及打开就开始扫描wifi信号:

private void checkWfiState(Intent intent) {//获取当前wifi的状态    int wifiState = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,            WifiManager.WIFI_STATE_DISABLED);    switch (wifiState) {        case WifiManager.WIFI_STATE_DISABLED:            //wifi已关闭            connectState = WifiConnectState.NONE;            wifiSwitchView.setEnabled(true);            wifiSwitchView.setWifiOpened(false);            stopScanWifi();            break;        case WifiManager.WIFI_STATE_ENABLED:            //wifi已打开            startScanWifi(true);            wifiSwitchView.setEnabled(true);            wifiSwitchView.setWifiOpened(true);            break;        case WifiManager.WIFI_STATE_ENABLING:            wifiSwitchView.setEnabled(false);            //wifi正在打开            break;        case WifiManager.WIFI_STATE_DISABLING:            wifiSwitchView.setEnabled(false);            //wifi正在关闭            break;        default:            break;    }}复制代码

开始扫描wifi:

/** * 开始扫描Wifi */private void startScanWifi(boolean isLoading) {    if (isLoading) {        showLoadingDialog("");    }    wifiManager.startScan();}复制代码

Wifi扫描成功之后,会发出一个WifiManager.SCAN_RESULTS_AVAILABLE_ACTION

的广播。通过List<ScanResult> scanResults = wifiManager.getScanResults();

获取扫描结果,接下来看下ScanResult这个类,其中SSID,表示是wifi的名称。capabilities描述了wifi的加密方式等信息,可以通过如下方式判断wifi的加密方式:

if (model.capabilities.contains("WPA") || model.capabilities.contains("wpa")) {    encryptType = TYPE_ENCRYPT_WPA;} else if (model.capabilities.contains("WEP") || model.capabilities.contains("wep")) {    encryptType = TYPE_ENCRYPT_WEP;} else {    encryptType = "";}复制代码

不同的加密方式,连接的处理方式第不一样的。level是表示wifi的信号强度,一般是个负数,越大表示信号越强。

wifi连接:

首先判读wifi是否已保存,如果以及保存,那么不需要输入密码直接连接,通过如下方法判读wifi是否保存:

private WifiConfiguration getExistConfig(String ssid) {    List
existingConfigs = wifiManager.getConfiguredNetworks(); if (!CollectionUtil.isEmpty(existingConfigs)) { for (WifiConfiguration existingConfig : existingConfigs) { if (TextUtil.isEquals(existingConfig.SSID, ssid)) return existingConfig; } } return null;}复制代码

wifiManager.getConfiguredNetworks()会把所有已经保存的wifi,返回,如果扫描出的wifi吗名称,能够在.getConfiguredNetworks()找到证明是已保存的。通过如下方法连接wifi:

int netId = wifiManager.addNetwork(config);//WifiManager的enableNetwork接口,就可以连接到netId对应的wifi了//其中boolean参数,主要用于指定是否需要断开其它Wifi网络wifiManager.enableNetwork(netId, true);复制代码

如果wifi没有保存,那么有自己构造WifiConfiguration,如下:

public WifiConfiguration createWifiConfig(WifiScanResultVM wifiScanResultVM) {    //初始化WifiConfiguration    WifiConfiguration config = new WifiConfiguration();    config.SSID = wifiScanResultVM.getSsid();    //不需要密码的场景    String password = wifiScanResultVM.getPassWord();    if (!wifiScanResultVM.isEncrypt()) {        config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);        //以WEP加密的场景    } else if (TextUtil.isEquals(wifiScanResultVM.getEncryptType(), WifiScanResultVM.TYPE_ENCRYPT_WEP)) {        int i = password.length();        if (((i == 10 || (i == 26) || (i == 58))) && (password.matches("[0-9A-Fa-f]*"))) {            config.wepKeys[0] = password;        } else {            config.wepKeys[0] = "\"" + password + "\"";        }        //以WPA加密的场景,自己测试时,发现热点以WPA2建立时,同样可以用这种配置连接    } else if (TextUtil.isEquals(wifiScanResultVM.getEncryptType(), WifiScanResultVM.TYPE_ENCRYPT_WPA)) {        config.preSharedKey = "\"" + password + "\"";        config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);    }    return config;}复制代码

需要区分不同的加密方式,连接过程中会多次发出,WifiManager.SUPPLICANT_STATE_CHANGED_ACTION

这个广播,处理如下:

int error = action.getIntExtra(WifiManager.EXTRA_SUPPLICANT_ERROR, 0);if (WifiManager.ERROR_AUTHENTICATING == error) {    toastFail();} else {    checkWifiConnectState(action);}复制代码

/**     * wifi切换连接     *     * @param intent     */    public void checkWifiConnectState(Intent intent) {        SupplicantState supplicantState = intent.getParcelableExtra(WifiManager.EXTRA_NEW_STATE);        if (null != supplicantState) {            switch (supplicantState) {                case DISCONNECTED:                    connectState = WifiConnectState.NONE;                    getScanResult();                    break;                case COMPLETED://                    if (currentData != null) {//                        XLog.e("SSID", "checkWifiConnectState" + currentData.getSsid());//                    }                    getScanResult();                    connectState = WifiConnectState.CONNECTED;                    break;            }            return;        }    }复制代码

还有一个问题,如何判断当前正在连接的是哪个wifi,如下:

private String getCurrentSsid() {//        XLog.e("SSID", "getCurrentSsid: ");        if (connectState != WifiConnectState.CONNECTED) {//            XLog.e("SSID", " WifiConnectState.CONNECTED: " + connectState.name());            return "";        }        WifiInfo wifiInfo = wifiManager.getConnectionInfo();        if (wifiInfo != null) {//            XLog.e("SSID", "wifiInfo" + wifiInfo.getSSID());            return wifiInfo.getSSID();        }//        XLog.e("SSID", "null null null  ");        return "";    }复制代码

通过拿到当前wifi的连接信息进行比对,有个问题值得注意,当前wifi正在连接时,

WifiInfo wifiInfo = wifiManager.getConnectionInfo();复制代码

返回的也是有值得,需要注意下。

未填的坑:

当有两个wifi名称一样的时候,就不好处理,这边的处理是直接忽略一个,如果有大神有好的方案,欢迎留言,大家一起讨论下

转载地址:http://igsox.baihongyu.com/

你可能感兴趣的文章
RHCE是否还值得考取?
查看>>
Google Cloud 下一站之战略转变
查看>>
【自用】nginx.conf
查看>>
保持坦然平和的心态!
查看>>
KVM配置之(3)- 克隆
查看>>
分享自制的C#和VB Code互转工具
查看>>
Spring容器初始化Bean、销毁Bean前所做操作的定义方式汇总
查看>>
Linux系统的常用命令的使用
查看>>
Apache Solr入门教程(初学者之旅)
查看>>
IPV4报头格式详解
查看>>
echart地图配置
查看>>
了解计算机病毒
查看>>
node学习准备工作1 --- nvm下载、终端环境iterm2配置
查看>>
centos7 apache2.4 多站点配置
查看>>
zabbix监控mysql
查看>>
微信小程序(6)模板详解 template
查看>>
FAQ宝典之常见问题排查与修复方法
查看>>
Guitar Pro7最新版发布 吉他编谱首选
查看>>
jenkins安装
查看>>
如何修改MySQL8.0.5以上版本root密码
查看>>