天天看点

Android6.0通过WiFi名称密码连接WiFi的方案

** 前言:早在去年,我曾写过一个针对android6.0连接指定WiFi的文章。虽然能成功连接,但有好多不合理甚至错误的地方,因此现在对那篇文章进行重新编辑发布**。

最近项目中有通过已知WiFi名称和密码连接传感器WiFi,实现数据交换的需求。在网上找了许多资料发现都是复制黏贴,也有好多bug,现在我将其整理封装并在项目中使用。

github地址:https://github.com/tangjiang24/WifiConnector

用法

step1

在根build.gradle中添加:

allprojects {
    repositories {
        maven { url "https://jitpack.io" }
    }
}      

在使用的模块build.gradle中添加:

dependencies {
    implementation 'com.github.tangjiang24:WifiConnector:Tag'
}      

(请替换 Tag 为最新的版本号: img)

Step2

分两种方法:

第一种:

1.将需要连接的activity继承 库中的 WifiActivity :

public class WifiConnectActivity extends WifiActivity{}      

2.直接调用父类中的 connectWifi(String ssid, String pwd, int type) 方法:

connectWifi(String ssid,String pwd,int type);      

3.重写连接失败成功的抽象方法即可:

@Override
    public void onConnectWifiSucess() {
        ToastUtil.showShortToast(this,"连接成功!!");
    }

    @Override
    public void onConnectWifiFail(String failMsg) {
        ToastUtil.showShortToast(this,failMsg);
    }      

第二种:

1.构建WifiConnector对象

WifiConnector connector = new WifiConnector(context);      

2.调用其connectWifi () 方法,并在回调中写成功或者失败后的逻辑

connector.connectWifi(ssid, pwd, WifiUtil.TYPE_WPA, new WifiConnector.WifiConnectCallBack() {
    @Override
    public void onConnectSucess() {
        Toast.makeText(WifiConnectActivity.this,"连接成功!!",Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onConnectFail(String msg) {
        Toast.makeText(WifiConnectActivity.this,msg,Toast.LENGTH_SHORT).show();
    }
});      

参数说明:

参数名     类型     意义

ssid     String     WiFi名称

pwd     String     WiFi 密码

type     int     密码类型

wifiConnectCallBack     WifiConnectCallBack     连接回调

三种密码类型:

    WifiUtil.TYPE_NO_PWD(无密码)

    WifiUtil.TYPE_WEB (WEB)

    WifiUtil.TYPE_WPA(WPA)

注意:由于Java的单继承性,第一种方法有很大的局限,建议使用第二种方法。

​原理:

1.判断当前手机wifi网络是否开启可用;

开启WiFi代码:

public boolean openWifi() {
        boolean sucess = true;
        if(!this.mWifiManager.isWifiEnabled()) {
            sucess = this.mWifiManager.setWifiEnabled(true);
        }

        return sucess;
    }      

开启WiFi一般需要一定的时间,因此不能立马去连接,需要等WiFi稳定可用,经测试一般2.5秒即可完成,因此我们每隔100毫秒就去判断WiFi是否可用,代码如下:

if(!this.openWifi()) {
            return false;
        } else {
            long timeMills = System.currentTimeMillis();

            while(this.mWifiManager.getWifiState() != 3) {
                try {
                    if(System.currentTimeMillis() - timeMills > 2500L) {
                        break;
                    }

                    Thread.sleep(100L);
                } catch (InterruptedException var8) {
                    var8.printStackTrace();
                }
            }      

2.根据WiFi名称,获取/创建WifiConfiguration;

首先我们需要判断是否包含有当前WiFi名称的WifiConfiguration,若包含则试着将其删除再添加。1.为什么是试着删除?因为在android6.0以上,只允许删除由本应用创建的wificonfiguratin,不能改变删除其他应用所创建的。 2.为什么不直接连接而要删除再添加?因为wificonfiguratin不一定是连接成功后的wificonfiguratin,也有可能是手残输错了密码,这样直接去连接会导致一辈子也连接不上。

具体代码如下:

private WifiConfiguration createWifiInfo(String SSID, String Password, int Type) {
        WifiConfiguration config = new WifiConfiguration();
        config.allowedAuthAlgorithms.clear();
        config.allowedGroupCiphers.clear();
        config.allowedKeyManagement.clear();
        config.allowedPairwiseCiphers.clear();
        config.allowedProtocols.clear();
        config.SSID = "\"" + SSID + "\"";
        WifiConfiguration tempConfig = this.IsExsits(SSID);
        List<WifiConfiguration> beforeConfig = this.mWifiManager.getConfiguredNetworks();
        if(tempConfig != null) {
            this.removeWifi(tempConfig.networkId);
        }

        List<WifiConfiguration> afterConfig = this.mWifiManager.getConfiguredNetworks();
        if(tempConfig != null && beforeConfig.size() == afterConfig.size()) {
            return tempConfig;
        } else {
            if(Type == 1) {
                config.allowedKeyManagement.set(0);
            }

            if(Type == 2) {
                config.hiddenSSID = true;
                config.wepKeys[0] = "\"" + Password + "\"";
                config.allowedAuthAlgorithms.set(1);
                config.allowedGroupCiphers.set(3);
                config.allowedGroupCiphers.set(2);
                config.allowedGroupCiphers.set(0);
                config.allowedGroupCiphers.set(1);
                config.allowedKeyManagement.set(0);
                config.wepTxKeyIndex = 0;
            }

            if(Type == 3) {
                config.preSharedKey = "\"" + Password + "\"";
                config.hiddenSSID = true;
                config.allowedAuthAlgorithms.set(0);
                config.allowedGroupCiphers.set(2);
                config.allowedKeyManagement.set(1);
                config.allowedPairwiseCiphers.set(1);
                config.allowedGroupCiphers.set(3);
                config.allowedPairwiseCiphers.set(2);
                config.status = 2;
            }

            return config;
        }
    }      

3.注册网络变化的广播,当监听到网络连接上时,判断当前WiFi网络的名称是否和目标WiFi的一致;

广播中主要代码:

NetworkInfo info = (NetworkInfo)intent.getParcelableExtra("networkInfo");
        Log.i("wifi:", "接受到网络连接变化的广播,当前网络状态为:" + info.getState());
        if(info.getState().equals(State.CONNECTED)) {
            WifiManager wifiManager = (WifiManager)context.getSystemService("wifi");
            WifiInfo wifiInfo = wifiManager.getConnectionInfo();
            String ssid = wifiInfo.getSSID();
            Log.i("wifi:", "接受到网络连接变化的广播,已连接的网络的ssid=" + ssid);
            this.mListner.isConnectMyWifi(ssid);
        }
 
public void setOnWifiConnetListner(WifiConnectReceiver.onWifiConnectListner listner) {
        this.mListner = listner;
    }

    public interface onWifiConnectListner {
        void isConnectMyWifi(String var1);
    }      

activity中实现receiver中声明的接口onWifiConnectListner,主要代码:

public void isConnectMyWifi(String s) {
        if(!TextUtils.isEmpty(this.ssid)) {
            if(s.equals("\"" + this.ssid + "\"")) {
                this.handler.removeMessages(1);
                this.handler.removeMessages(2);
                this.handler.sendEmptyMessageDelayed(1, 1000L);
            } else {
                Log.i("wifi:", "未连接到指定网络!");
                this.sendFailMessage("未连接到指定网络!", 1L);
            }
        }

    }

    private void registWifiConnectReceiver() {
        if(!this.mReceiverTag) {
            this.wifiConnectReceiver = new WifiConnectReceiver();
            this.mReceiverTag = true;
            this.wifiConnectReceiver.setOnWifiConnetListner(this);
            IntentFilter intentFilter = new IntentFilter();
            intentFilter.addAction("android.net.wifi.STATE_CHANGE");
            this.registerReceiver(this.wifiConnectReceiver, intentFilter);
        }      

总结及注意点:

1.开启WiFi时需要时间的,必须等稳定后再去连接;

2.手机中保存的wificonfiguratin不一定可用,连接时需要先删除再添加;

3.在6.0以后调用mWifiManager.removeNetwork(netId)只对本应用添加的有效;

config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);