解决:android 开发 WIFI 功能 密码输入正确时监听的问题

问题描述:
在一个 android 项目中 需要 开发 类似于 系统 wifi 连接的功能,选择可用 wifi 后,输入正确的密码后,WifiManager.SUPPLICANT_STATE_CHANGED_ACTION 中的 WifiManager.ERROR_AUTHENTICATING
密码错误广播 偶尔也会收到监听,文章最后已有解决方案
在这里插入图片描述

先看看 wifi 功能开发的常规流程

1、注意 wifi状态的监听

private void regiterWifiBroadcast() {
        wifiReceiver = new WifiBroadcastReceiver();
        IntentFilter filter = new IntentFilter();
        filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);//监听wifi是开关变化的状态
        filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);//监听wifi连接状态广播,是否连接了一个有效路由
        filter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);//监听wifi列表变化(开启一个热点或者关闭一个热点)
        filter.addAction(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION); //监听密码
        registerReceiver(wifiReceiver, filter);
    }

2、创建 wifi 监听的广播


//获取WifiManager
WifiManager wifiManager = (WifiManager)Context.getSystemService(Context.WIFI_SERVICE);

public class WifiBroadcastReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {

            if(WifiManager.WIFI_STATE_CHANGED_ACTION.equals(intent.getAction())){
                int state = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, 0);
                switch (state){
                    /**
                     * WIFI_STATE_DISABLED    WLAN已经关闭
                     * WIFI_STATE_DISABLING   WLAN正在关闭
                     * WIFI_STATE_ENABLED     WLAN已经打开
                     * WIFI_STATE_ENABLING    WLAN正在打开
                     * WIFI_STATE_UNKNOWN     未知
                     */
                    case WifiManager.WIFI_STATE_DISABLED:{
                        Log.e(TAG,"wifi已经关闭");
                        break;
                    }
                    case WifiManager.WIFI_STATE_DISABLING:{
                        Log.e(TAG,"wifi正在关闭");
                        break;
                    }
                    case WifiManager.WIFI_STATE_ENABLED:{
                        Log.e(TAG,"wifi已经打开");
                        connectType = -1;
                        wifiManager.startScan();

                        break;
                    }
                    case WifiManager.WIFI_STATE_ENABLING:{
                        Log.e(TAG,"wifi正在打开");
                        break;
                    }
                    case WifiManager.WIFI_STATE_UNKNOWN:{
                        Log.e(TAG,"wifi未知状态");
                        break;
                    }
                }
            }else if(WifiManager.NETWORK_STATE_CHANGED_ACTION.equals(intent.getAction())){
                NetworkInfo info = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
                Log.e(TAG, "--网络状态--" + info.toString());
                if(NetworkInfo.State.DISCONNECTED == info.getState()){//wifi没连接上
                    Log.e(TAG,"wifi没连接上,已断开");
                    if(connectType!=0) {
                        connectType = 0;
                        for (int i = 0; i < realWifiList.size(); i++) {//没连接上将 所有的连接状态都置为“未连接”
                            realWifiList.get(i).setState(WifiSupport.WIFI_STATE_UNCONNECT);
                        }
                        adapter.setList(realWifiList);
                        listView.post(new Runnable() {
                            @Override
                            public void run() {
                                adapter.notifyDataSetChanged();
                            }
                        });
                    }
                    connectType = 0;

                }else if(NetworkInfo.State.CONNECTED == info.getState()){//wifi连接上了

                    if(connectType!=1) {
                        connectType = 1;
                        WifiInfo connectedWifiInfo = WifiSupport.getConnectedWifiInfo(context);
                        String ssidName = connectedWifiInfo.getSSID();
                        wifiListSet(ssidName,connectType);
                        Log.e(TAG,ssidName + ":wifi连接上了");
                        //连接成功
                        Toast.makeText(context,ssidName + " 连接成功",Toast.LENGTH_SHORT).show();
                        //连接成功保持密码(用系统自己的方式保存密码)
                        //PreferenceHelper.write(mContext,ssidName,inputPass);
                    }

                    connectType = 1;
                }else if(NetworkInfo.State.CONNECTING == info.getState()) {//正在连接

                    if(connectType!=2) {
                        connectType = 2;
                        WifiInfo connectedWifiInfo = WifiSupport.getConnectedWifiInfo(context);
                        String ssid = connectedWifiInfo.getSSID();
                        wifiListSet(ssid, connectType);
                        Log.e(TAG, ssid + "-->wifi正在连接");
                    }
                    connectType = 2;
                }

            }else if(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION.equals(intent.getAction())){
                Log.e(TAG,"网络列表变化了");

                wifiListChange();
            }else if(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION.equals(intent.getAction())){   //密码监听
                SupplicantState supplicantState = intent.getParcelableExtra(WifiManager.EXTRA_NEW_STATE);
                NetworkInfo.DetailedState state = WifiInfo.getDetailedStateOf(supplicantState);
                int error = intent.getIntExtra(WifiManager.EXTRA_SUPPLICANT_ERROR, -1);
                Log.e(TAG, "当前网络连接状态码:" + error + ";连接状态 --->>> " + state);
                if (error == WifiManager.ERROR_AUTHENTICATING) {
                    String ssidName = wifiManager.getConnectionInfo().getSSID();
                    Log.e(TAG, ssidName + ":密码错误,连接状态 --->>>" + state +",connectType:" + connectType);
                    //状态为 DISCONNECTED 断开的 时候才是真的密码错误
                    if(state == NetworkInfo.DetailedState.DISCONNECTED){
                        Toast.makeText(context,"密码错误,连接失败",Toast.LENGTH_SHORT).show();
                        //用系统自己的方式忘记wifi
                        boolean b = WifiSupport.forgetWifiNetWork(ssidName, mContext);//连接失败后需要忘记密码,不然会因为重连机制导致反复广播
                        //密码错误时清空保持中的密码
                        //PreferenceHelper.write(mContext,ssidName,"");
                    }else if(state == NetworkInfo.DetailedState.SCANNING){
                        //密码正确的时,第一次会走密码错误的逻辑 进入 SCANNING 扫描的状态,或者进入 CONNECTING 连接的状态

                    }
                }

            }
        }
    }

3、监听到wifi开启后开始扫描周围可用 wifi

case WifiManager.WIFI_STATE_ENABLED:{
        Log.e(TAG,"wifi已经打开");
        connectType = -1;
        wifiManager.startScan();
        break;
    }

4、监听到 wifi 发生变化的时候开始封装 可用的 wifi 信息

if(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION.equals(intent.getAction())){
    Log.e(TAG,"网络列表变化了");

    sortScaResult();
}
/**
     * 扫描周围可用的wifi,封装到List中
     */
    public void sortScaResult(){
        List<ScanResult> scanResults = WifiSupport.noSameName(WifiSupport.getWifiScanResult(this));
        WifiInfo connectedWifiInfo = WifiSupport.getConnectedWifiInfo(this);
        realWifiList.clear();
        int index = -1;
        String conn = "";
        if (connectedWifiInfo != null) {
            conn = connectedWifiInfo.getSSID();
            if(!TextUtils.isEmpty(conn)){
                if (conn.startsWith("\"")) {
                    conn = conn.substring(1, conn.length());
                }
                if (conn.endsWith("\"")) {
                    conn = conn.substring(0, conn.length() - 1);
                }
            }
        }

        Log.e(TAG,"附近有多少可用wifi: "+scanResults.size()+"\n当前连接的wifi信息="+connectedWifiInfo);
        if(!isNullOrEmpty(scanResults)){
            for(int i = 0;i < scanResults.size();i++){
                WifiBean wifiBean = new WifiBean();
                wifiBean.setWifiName(scanResults.get(i).SSID.trim());
                wifiBean.setState(WifiSupport.WIFI_STATE_UNCONNECT);   //只要获取都假设设置成未连接,真正的状态都通过广播来确定
                wifiBean.setCapabilities(scanResults.get(i).capabilities);
                wifiBean.setLevel(WifiSupport.getLevel(scanResults.get(i).level)+"");
                realWifiList.add(wifiBean);
                if (wifiBean.getWifiName().equals(conn)) {
                    wifiBean.setState(WifiSupport.WIFI_STATE_CONNECT);
                    index = i;
                }
            }
            //排序
            if (index != -1) {
                WifiBean bean = realWifiList.get(index);
                realWifiList.remove(index);
                realWifiList.add(0, bean);
            }
        }
        //     Collections.sort(realWifiList);

        if (adapter != null) {
            adapter.setList(realWifiList);
            listView.post(new Runnable() {
                @Override
                public void run() {
                    adapter.notifyDataSetChanged();
                }
            });
        }
        if(realWifiList.size() == 0){
            ll_box.setVisibility(View.GONE);
            tv_tips.setVisibility(View.VISIBLE);
        }else {
            ll_box.setVisibility(View.VISIBLE);
            tv_tips.setVisibility(View.GONE);
        }
    }

5、点击 列表的 Adapter 选中 要连接的 wifi,输入密码,开始连接

/**
     * Adapter条目的点击事件
     */
    RVBaseAdapter.OnItemClickListener onItemClickListener = new RVBaseAdapter.OnItemClickListener() {
        @Override
        public void OnItemClick(View view, RVBaseAdapter.ViewHolder holder, int position, Object o) {
            WifiBean wifiBean = realWifiList.get(position);
            if (wifiBean.getState() == WifiSupport.WIFI_STATE_UNCONNECT || wifiBean.getState() == WifiSupport.WIFI_STATE_ON_CONNECTING) {
                String capabilities = realWifiList.get(position).getCapabilities();
                //当前wifi的加密方式是不需要密码的
                if (WifiSupport.getWifiCipher(capabilities) == WifiSupport.WifiCipherType.WIFICIPHER_NOPASS) {//无需密码
                    WifiConfiguration tempConfig = WifiSupport.isExsits(wifiBean.getWifiName(), view.getContext());
                    if (tempConfig == null) {
                        WifiConfiguration exsits = WifiSupport.createWifiConfig(wifiBean.getWifiName(), null, WifiSupport.WifiCipherType.WIFICIPHER_NOPASS);
                        WifiSupport.addNetWork(exsits, view.getContext());
                    } else {
                        WifiSupport.addNetWork(tempConfig, view.getContext());
                    }
                } else {
                    //String s = PreferenceHelper.readString(mContext, wifiBean.getWifiName());
                    WifiConfiguration wifiConfiguration = WifiSupport.isExsits(wifiBean.getWifiName(), view.getContext());
                    if (wifiConfiguration != null) {
                        //如果以前连接过的wifi就直接进行连接(如果连接失败会被删除)
                        WifiSupport.addNetWork(wifiConfiguration,mContext);
                    }else {
                        //需要密码,弹出输入密码dialog
                        noConfigurationWifi(position);
                    }
                }
            }
        }
    };
//输入密码dialog
    public void noConfigurationWifi(int position) {
        final WifiBean wifiBean = realWifiList.get(position);
        String wifiName = wifiBean.getWifiName();
        final CommonDialog inputDialog = new CommonDialog(mContext);
        inputDialog.setTitle(wifiName);
        final ClearEditText inputView = (ClearEditText) LayoutInflater.from(
                mContext).inflate(R.layout.layout_input_edit, null);
        inputDialog.setContent(inputView);
        inputView.setHint("请输入密码");
        inputView.setInputType(InputType.TYPE_CLASS_TEXT);
        inputDialog.setPositiveButton(R.string.confirm,
                new android.content.DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int which) {
                        String wifiName = wifiBean.getWifiName();
                        inputPass = inputView.getText().toString();
                        String capabilities = wifiBean.getCapabilities();
                        if(wifiEditCheck(capabilities,inputPass)){
                            WifiConfiguration wifiConfiguration =  WifiSupport.createWifiConfig(wifiName,inputPass,WifiSupport.getWifiCipher(capabilities));
                            //连接wifi
                            WifiSupport.addNetWork(wifiConfiguration,mContext);
                            inputDialog.cancel();
                        }
                    }
                });
        inputDialog.setNegativeButton(R.string.cancel,
                new android.content.DialogInterface.OnClickListener() {

                    public void onClick(DialogInterface dialog, int which) {
                        inputDialog.cancel();
                    }
                });

        inputDialog.show();

    }

问题:输入正确的密码后,

WifiManager.SUPPLICANT_STATE_CHANGED_ACTION

中的 WifiManager.ERROR_AUTHENTICATING

密码错误广播 偶尔也会收到监听

解决方案

网络连接状态码为: WifiManager.ERROR_AUTHENTICATING
并且连接状态为:NetworkInfo.DetailedState.DISCONNECTED
的时候才是真的密码错误,然后再去忘记密码!

if(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION.equals(intent.getAction())){   //密码监听
                SupplicantState supplicantState = intent.getParcelableExtra(WifiManager.EXTRA_NEW_STATE);
                NetworkInfo.DetailedState state = WifiInfo.getDetailedStateOf(supplicantState);
                int error = intent.getIntExtra(WifiManager.EXTRA_SUPPLICANT_ERROR, -1);
                Log.e(TAG, "当前网络连接状态码:" + error + ";连接状态 --->>> " + state);
                if (error == WifiManager.ERROR_AUTHENTICATING) {
                    String ssidName = wifiManager.getConnectionInfo().getSSID();
                    Log.e(TAG, ssidName + ":密码错误,连接状态 --->>>" + state +",connectType:" + connectType);
                    //状态为 DISCONNECTED 断开的 时候才是真的密码错误
                    if(state == NetworkInfo.DetailedState.DISCONNECTED){
                        Toast.makeText(context,"密码错误,连接失败",Toast.LENGTH_SHORT).show();
                        //用系统自己的方式忘记wifi
                        boolean b = WifiSupport.forgetWifiNetWork(ssidName, mContext);//连接失败后需要忘记密码,不然会因为重连机制导致反复广播
                        //密码错误时清空保持中的密码
                        //PreferenceHelper.write(mContext,ssidName,"");
                    }else if(state == NetworkInfo.DetailedState.SCANNING){
                        //密码正确的时,第一次会走密码错误的逻辑 进入 SCANNING 扫描的状态,或者进入 CONNECTING 连接的状态

                    }
                }
            }

文中用到的工具类 下载地址

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值