WIFI Util 兼容Android Q

前言

Android适配是老生常谈的问题,现在来看看特别是扫描和连接wifi常常会出现失败的情况,明明是用的标准API为什么却不成功呢?这个时候就得查阅谷歌官方文档一探究竟了。

API不支持

Android Q以前

mWifiManager可以满足所有功能


/**
 * @Author 
 * @Desc wifi工具类
 * @Date 2020/6/12
 */
public class WifiHelpUtils {

    public static final int Security_NONE = 0;
    public static final int Security_WEP = 1;
    public static final int Security_PSK = 2;
    public static final int Security_EAP = 3;

    public static final int WIFI_norMAL = 0;
    public static final int WIFI_CONNECTING = 1;
    public static final int WIFI_CONNECTED = 2;

    private static WifiHelpUtils wifiHelpUtils = null;
    private Context applicationContext;
    private WifiManager mWifiManager;

    public static WifiHelpUtils getInstance(Context context) {
        if (wifiHelpUtils == null) {
            wifiHelpUtils = new WifiHelpUtils(context);
        }
        return wifiHelpUtils;
    }

    private WifiHelpUtils(Context context) {
        applicationContext = context.getApplicationContext();
        mWifiManager = (WifiManager) applicationContext.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
    }

    /**
     * 开启或关闭wifi
     */
    public void openorCloseWifi(boolean isOpen) {
        if (mWifiManager.isWifiEnabled() ^ isOpen) {
            mWifiManager.setWifiEnabled(isOpen);
        }
    }

    /**
     * 判断wifi是否开启
     */
    public boolean isWifiOpened() {
        return mWifiManager.isWifiEnabled();
    }


    /**
     * 开始扫描
     */
    public void startScan() {
        if (mWifiManager == null)
            return;
        if (mWifiManager.isWifiEnabled()) {
            mWifiManager.startScan();
        }

    }


    /**
     * 获取到wifi列表
     */
    public List<ScanResult> getScanResult() {
        if (mWifiManager == null)
            return null;
        if (!mWifiManager.isWifiEnabled())
            return null;
        List<ScanResult> list = new ArrayList<>();
        List<ScanResult> scanResults = mWifiManager.getScanResults();
        for (ScanResult result : scanResults) {
            int i = 0;
            for (ScanResult result1 : list) {
                if (result1.SSID.equals(result.SSID))
                    break;
                i++;
            }
            if (i == list.size()) {
                list.add(result);
            }
        }
        return list;
    }

    /**
     * 判断有是否需要密码
     */
    public static int getSecurity(ScanResult result) {
        if (result.capabilities.contains("WEP")) {
            return Security_WEP;
        } else if (result.capabilities.contains("PSK")) {
            return Security_PSK;
        } else if (result.capabilities.contains("EAP")) {
            return Security_EAP;
        }
        return Security_NONE;
    }


    /**
     * wifi设置
     *
     * @param ssid
     * @param pws
     * @param isHasPws
     */
    private WifiConfiguration getWifiConfig(String ssid, String pws, boolean isHasPws) {
        WifiConfiguration config = new WifiConfiguration();
        config.allowedAuthAlgorithms.clear();
        config.allowedGroupCiphers.clear();
        config.allowedKeyManagement.clear();
        config.allowedPairwiseCiphers.clear();
        config.allowedProtocols.clear();
        config.SSID = "\"" + ssid + "\"";

        WifiConfiguration tempConfig = isExist(ssid);
        if (tempConfig != null) {
            mWifiManager.removeNetwork(tempConfig.networkId);
        }
        if (isHasPws) {
            config.preSharedKey = "\"" + pws + "\"";
            config.hiddenSSID = true;
            config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
            config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
            config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
            config.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
            config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
            config.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
            config.status = WifiConfiguration.Status.ENABLED;
        } else {
            config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
        }
        return config;
    }

    /**
     * 得到配置好的网络连接
     *
     * @param ssid
     * @return
     */
    public WifiConfiguration isExist(String ssid) {
        List<WifiConfiguration> configs = mWifiManager.getConfigurednetworks();
        for (WifiConfiguration config : configs) {
            if (config.SSID.equals("\"" + ssid + "\"")) {
                return config;
            }
        }
        return null;
    }


    /**
     * 有密码连接
     *
     * @param ssid
     * @param pws
     */
    public Boolean connectWifipws(String ssid, String pws) {
        mWifiManager.disableNetwork(getCurrentConnectInfo().getNetworkId());
        int netId = mWifiManager.addNetwork(getWifiConfig(ssid, pws, !TextUtils.isEmpty(pws)));
        return mWifiManager.enableNetwork(netId, true);
    }

    public void addNetwork(String ssid, String pws) {
        int netID = getCurrentConnectInfo().getNetworkId();
        if (netID > 0) {
            mWifiManager.disableNetwork(netID);
        }
        disconnect();
        WifiConfiguration wifiConfiguration = getWifiConfig(ssid, pws, !TextUtils.isEmpty(pws));
        if (wifiConfiguration.networkId > 0) {
            mWifiManager.enableNetwork(wifiConfiguration.networkId, true);
            mWifiManager.updateNetwork(wifiConfiguration);
        } else {
            int wcgID = mWifiManager.addNetwork(wifiConfiguration);
            if (wcgID != -1) {
                mWifiManager.enableNetwork(wcgID, true);
                mWifiManager.saveConfiguration();
                // mWifiManager.reconnect();
            }
        }

    }

    /**
     * 已配置直接重连
     */
    public void reconnect(WifiConfiguration wifiConfiguration) {
        int netID = getCurrentConnectInfo().getNetworkId();
        if (netID > 0) {
            mWifiManager.disableNetwork(netID);
        }
        disconnect();
        if (wifiConfiguration.networkId != -1) {
            mWifiManager.enableNetwork(wifiConfiguration.networkId, true);
            mWifiManager.updateNetwork(wifiConfiguration);
        }
    }

    public void disableNetWork(int id) {
        mWifiManager.disableNetwork(id);
    }

    public void disconnect() {
        mWifiManager.disconnect();
    }

    /**
     * 判断指定wifi是否连接
     */
    public boolean isConnected(String ssid) {
        WifiInfo wifiInfo = mWifiManager.getConnectionInfo();
        if (wifiInfo == null) {
            return false;
        }
        switch (wifiInfo.getSupplicantState()) {
            case AUTHENTICATING:
            case ASSOCIATING:
            case ASSOCIATED:
            case FOUR_WAY_HANDSHAKE:
            case GROUP_HANDSHAKE:
            case COMPLETED:
                return wifiInfo.getSSID().replace("\"", "").equals(ssid);
            default:
                return false;
        }
    }

    public boolean isWifiConnected(Context context, String wifiHotspotName) {

        ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);

        NetworkInfo info = manager.getActiveNetworkInfo();

        if (info != null) {
            String extraInfo = info.getExtraInfo();
            if (extraInfo.equals("\"" + wifiHotspotName + "\"")) {
                return true;
            }
        }

        return false;

    }

    public boolean isConnected() {
        ConnectivityManager connectivityManager = (ConnectivityManager) applicationContext
                .getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo activeNetInfo = connectivityManager.getActiveNetworkInfo();
        return activeNetInfo != null
                && activeNetInfo.getType() == ConnectivityManager.TYPE_WIFI;
    }

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

    @SuppressLint("PrivateApi")
    public void forgetNetwork(int networkId) {
        if (mWifiManager == null) {
            return;
        }
        try {
            Method forget = mWifiManager.getClass().getDeclaredMethod("forget", int.class, Class.forName("android.net.wifi.WifiManager$ActionListener"));
            forget.setAccessible(true);
            forget.invoke(mWifiManager, networkId, null);
            ToastUtils.showShort("忘记密码成功");
        } catch (Exception e) {
            ToastUtils.showShort("忘记密码异常");
            e.printstacktrace();
        }
    }

}
补充

创建wifi的方法

   // 定义几种加密方式,一种是WEP,一种是WPA,还有没有密码的情况
    public enum WifiCipherType {
        WIFICIPHER_WEP, WIFICIPHER_WPA, WIFICIPHER_nopASS, WIFICIPHER_INVALID
    }
    
    public WifiConfiguration createWifiInfo(String SSID, String password, WifiCipherType type) {

        Log.v(TAG, "SSID = " + SSID + "## Password = " + password + "## Type = " + 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);
        if (tempConfig != null) {
            mWifiManager.removeNetwork(tempConfig.networkId);
        }

        // 分为三种情况:1没有密码2用wep加密3用wpa加密
        if (type == WifiCipherType.WIFICIPHER_nopASS) {// WIFICIPHER_nopASS
            config.wepKeys[0] = "";
            config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
            config.wepTxKeyIndex = 0;

        } else if (type == WifiCipherType.WIFICIPHER_WEP) {  //  WIFICIPHER_WEP
            config.hiddenSSID = true;
            config.wepKeys[0] = "\"" + password + "\"";
            config.allowedAuthAlgorithms
                    .set(WifiConfiguration.AuthAlgorithm.SHARED);
            config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
            config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
            config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40);
            config.allowedGroupCiphers
                    .set(WifiConfiguration.GroupCipher.WEP104);
            config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
            config.wepTxKeyIndex = 0;
        } else if (type == WifiCipherType.WIFICIPHER_WPA) {   // WIFICIPHER_WPA
            config.preSharedKey = "\"" + password + "\"";
            config.hiddenSSID = true;
            config.allowedAuthAlgorithms
                    .set(WifiConfiguration.AuthAlgorithm.OPEN);
            config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
            config.allowedKeyManagement.set(WifiConfiguration.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;
    }

Android Q以后


/**
 * 文件名:WifiUtil
 * 描  述:
 * 作  者:
 * 时  间:2022/8/17 10:10
 */

import android.Manifest;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageManager;
import android.net.ConnectivityManager;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
import android.net.NetworkSpecifier;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager;
import android.net.wifi.WifiNetworkSpecifier;
import android.net.wifi.WifiNetworkSuggestion;
import android.os.Build;
import android.support.v4.app.ActivityCompat;
import android.util.Log;

import java.util.ArrayList;
import java.util.List;

import static android.content.Context.WIFI_SERVICE;

/**
 * @author 
 */
public class WifiUtil {


    private ConnectivityManager connectivityManager;
    private WifiManager mWifiManager;

    private ConnectivityManager.NetworkCallback networkCallback;

    public interface Networkchangelistener {
        void onNetworkChange(boolean enableNetwork);
    }

    public void removeNetworkchangelistener() {
        if (null != mNetworkchangelistener) {
            mNetworkchangelistener = null;
        }
        if (null != networkCallback) {
            connectivityManager.unregisterNetworkCallback(networkCallback);
        }
    }

    private Networkchangelistener mNetworkchangelistener;

    public void changetoWifi(Networkchangelistener networkchangelistener, Activity context, String wifiName, String wifipwd) {
        mNetworkchangelistener = networkchangelistener;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            changetoWifiAfterQ(context, wifiName, wifipwd);
        } else {
            changetoWifiBeforeQ(wifiName, wifipwd);
        }
    }

    /**
     * 切换到指定wifi Android版本小于10
     *
     * @param wifiName 指定的wifi名字
     * @param wifipwd  wifi密码,如果已经保存过密码,可以传入null
     * @return
     */
    public void changetoWifiBeforeQ(String wifiName, String wifipwd) {
        if (mWifiManager == null) {
            Log.d(TAG, " ***** init first ***** ");
            return;
        }
        WifiConfiguration wifiNewConfiguration = createWifiInfo(wifiName, wifipwd);//使用wpa2的wifi加密方式
            int newNetworkId = mWifiManager.addNetwork(wifiNewConfiguration);
        if (newNetworkId == -1) {
            Log.d(TAG, "操作失败,需要您到手机wifi列表中取消对设备连接的保存");
        } else {
            doChange2Wifi(newNetworkId);
        }

//        String mWifiName = "\"" + wifiName + "\"";

//        /**
//         * 判断定位权限
//         */
//        if (ActivityCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
//            return;
//        }
//        //获取wifi列表
//        List wifiList = mWifiManager.getConfigurednetworks();
//        boolean bFindInList = false;
//        for (int i = 0; i < wifiList.size(); ++i) {
//            WifiConfiguration wifiInfo0 = (WifiConfiguration) wifiList.get(i);
//
//            // 先找到对应的wifi
//            if (mWifiName.equals(wifiInfo0.SSID) || wifiName.equals(wifiInfo0.SSID)) {
//                // 1、 先启动,可能已经输入过密码,可以直接启动
//                Log.d(TAG, " set wifi 1 = " + wifiInfo0.SSID);
//                doChange2Wifi(wifiInfo0.networkId);
//
//                return;
//            }
//        }
//
//        // 2、如果wifi还没有输入过密码,尝试输入密码,启动wifi
//        if (!bFindInList) {
//            WifiConfiguration wifiNewConfiguration = createWifiInfo(wifiName, wifipwd);//使用wpa2的wifi加密方式
//            int newNetworkId = mWifiManager.addNetwork(wifiNewConfiguration);
//            if (newNetworkId == -1) {
//                Log.d(TAG, "操作失败,需要您到手机wifi列表中取消对设备连接的保存");
//            } else {
//                doChange2Wifi(newNetworkId);
//
//            }
//        }

    }


    /**
     * 切换到指定wifi Android版本大于等于10
     *
     * @param context
     * @param wifiName 指定的wifi名字
     * @param wifipwd  wifi密码,如果已经保存过密码,可以传入null
     * @return
     */
    @TargetApi(Build.VERSION_CODES.Q)
    public void changetoWifiAfterQ(Activity context, String wifiName, String wifipwd) {
        if (mWifiManager == null || connectivityManager == null) {
            Log.d(TAG, " ***** init first ***** ");
            return;
        }
        final WifiNetworkSuggestion suggestion1 =
                new WifiNetworkSuggestion.Builder()
                        .setSsid(wifiName)
                        .setIsAppInteractionrequired(true) // Optional (Needs location permission)
                        .build();

        final WifiNetworkSuggestion suggestion2 =
                new WifiNetworkSuggestion.Builder()
                        .setSsid(wifiName)
                        .setWpa2Passphrase(wifipwd)
                        .setIsAppInteractionrequired(true) // Optional (Needs location permission)
                        .build();

        final WifiNetworkSuggestion suggestion3 =
                new WifiNetworkSuggestion.Builder()
                        .setSsid(wifiName)
                        .setWpa3Passphrase(wifipwd)
                        .setIsAppInteractionrequired(true) // Optional (Needs location permission)
                        .build();

        final List<WifiNetworkSuggestion> suggestionsList = new ArrayList<WifiNetworkSuggestion>();
        suggestionsList.add(suggestion1);
        suggestionsList.add(suggestion2);
        suggestionsList.add(suggestion3);

        int removestatus = mWifiManager.removeNetworkSuggestions(suggestionsList);
        if (removestatus == WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS) {
            Log.d(TAG, "onAvailable 删除成功");
        }
        int addstatus = mWifiManager.addNetworkSuggestions(suggestionsList);
        if (addstatus == WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS) {
            Log.d(TAG, "onAvailable 添加成功");
        }

//保存到wifi列表 API30
//        Intent intent = new Intent(Settings.ACTION_WIFI_ADD_NETWORKS);
//        intent.putParcelableArrayListExtra(Settings.EXTRA_WIFI_NETWORK_LIST, suggestions);
//        context.startActivityForResult(intent, 0x125);

//        if (ActivityCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
//            return;
//        }
//        获取wifi扫描列表
//        List<ScanResult> wifiList = mWifiManager.getScanResults();
//        ScanResult scan = null;
//        for (ScanResult scanResult : wifiList) {
//            if (wifiName.equals(scanResult.SSID)) {
//                scan = scanResult;
//                break;
//            }
//        }
//        //扫描到了Wi-Fi
//        if (null != scan) {
        //setSsidPattern/setSsid/setBssidPattern/setBssid should be invoked for specifier
        NetworkSpecifier specifier = new WifiNetworkSpecifier.Builder()
                //.setSsidPattern(new PatternMatcher(wifiName, PatternMatcher.PATTERN_PREFIX))
                .setSsid(wifiName)
                .setWpa2Passphrase(wifipwd)
                //.setBssid(MacAddress.fromString(scan.BSSID))
                .build();

        NetworkRequest request =
                new NetworkRequest.Builder()
                        .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
                        .removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
                        .setNetworkSpecifier(specifier)
                        .build();

        unregisterNetWork();
        networkCallback = new ConnectivityManager.NetworkCallback() {
            @Override
            public void onAvailable(Network network) {
                super.onAvailable(network);
                Log.d(TAG, "onAvailable:" + network);
                connectivityManager.bindProcesstoNetwork(network);
                if (mNetworkchangelistener != null) {
                    mNetworkchangelistener.onNetworkChange(true);
                }
            }

            @Override
            public void onUnavailable() {
                super.onUnavailable();
                if (mNetworkchangelistener != null) {
                    mNetworkchangelistener.onNetworkChange(false);
                }
                Log.d(TAG, "Your Password is incorrect");
            }

        };
        connectivityManager.registerNetworkCallback(request, networkCallback);
        connectivityManager.requestNetwork(request, networkCallback);
//        } else {
//            Log.d(TAG, "未找到目标Wi-Fi");
//        }
    }

    @TargetApi(Build.VERSION_CODES.M)
    private void unregisterNetWork() {
        if (null != connectivityManager && null != networkCallback) {
            connectivityManager.bindProcesstoNetwork(null);
            connectivityManager.unregisterNetworkCallback(networkCallback);
        }
    }

    private boolean doChange2Wifi(int newNetworkId) {
        // 如果wifi权限没打开(1、先打开wifi,2,使用指定的wifi
        if (!mWifiManager.isWifiEnabled()) {
            mWifiManager.setWifiEnabled(true);
        }
        boolean enableNetwork = mWifiManager.enableNetwork(newNetworkId, true);
        if (mNetworkchangelistener != null) {
            mNetworkchangelistener.onNetworkChange(enableNetwork);
        }
        if (!enableNetwork) {
            return false;
        } else {
            return true;
        }
    }

    /**
     * 创建 WifiConfiguration,这里创建的是wpa2加密方式的wifi
     *
     * @param ssid     wifi账号
     * @param password wifi密码
     * @return
     */
    private WifiConfiguration createWifiInfo(String ssid, String password) {
        WifiConfiguration config = new WifiConfiguration();
        config.allowedAuthAlgorithms.clear();
        config.allowedGroupCiphers.clear();
        config.allowedKeyManagement.clear();
        config.allowedPairwiseCiphers.clear();
        config.allowedProtocols.clear();
        config.SSID = "\"" + ssid + "\"";
        config.preSharedKey = "\"" + password + "\"";
        config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
        config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
        config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
        config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
        config.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
        config.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
        config.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
        config.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
        config.status = WifiConfiguration.Status.ENABLED;
        return config;
    }

    public static final String TAG = "WifiUtil";

    private static final WifiUtil ourInstance = new WifiUtil();
    private static Context mContext;

    public static WifiUtil getIns() {
        return ourInstance;
    }

    public void init(Context context) {
        mContext = context;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            connectivityManager = (ConnectivityManager)
                    mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
        }
        mWifiManager = (WifiManager) mContext.getSystemService(WIFI_SERVICE);
    }

}

相关文章

显卡天梯图2024最新版,显卡是电脑进行图形处理的重要设备,...
初始化电脑时出现问题怎么办,可以使用win系统的安装介质,连...
todesk远程开机怎么设置,两台电脑要在同一局域网内,然后需...
油猴谷歌插件怎么安装,可以通过谷歌应用商店进行安装,需要...
虚拟内存这个名词想必很多人都听说过,我们在使用电脑的时候...