Android app应用连接WiFi的方法(兼容Android10)

Android应用开发有时候会有应用直连app的需求,由于Android系统 api会时常变动,wifi连接api亦如此,Android10以下直接使用:

复制代码
  WifiConfiguration configured = isExist(ssid);
        if (configured != null) {
            //在配置表中找到了,直接连接
            isSuccess = wifiManager.enableNetwork(configured.networkId, true);
        } else {
            WifiConfiguration wifiConfig = createWifiConfig(ssid, password, getCipherType(scanResult.getCapabilities()));
            int netId = wifiManager.addNetwork(wifiConfig);
            isSuccess = wifiManager.enableNetwork(netId, true);
        }

Android 10以上则可以使用

复制代码
  WifiNetworkSpecifier wifiNetworkSpecifier = new WifiNetworkSpecifier.Builder()
                .setSsid(ssid)
                .setWpa2Passphrase(password)
                .build();
        //网络请求
        NetworkRequest request = new NetworkRequest.Builder()
                .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
                .removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
                .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
                .addCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED)
                .setNetworkSpecifier(wifiNetworkSpecifier)
                .build();
        //网络回调处理
        ConnectivityManager.NetworkCallback networkCallback = new ConnectivityManager.NetworkCallback() {
            @Override
            public void onAvailable(@NonNull Network network) {
                super.onAvailable(network);
                if (wifiConnectCallback != null) {
                    wifiConnectCallback.onSuccess(network);
                    Log.d("WifiUtils", "======onAvailable: ====连接成功======");
                }
            }

            @Override
            public void onUnavailable() {
                super.onUnavailable();
                Log.d("WifiUtils", "======onAvailable: ====连接失败======");
                if (wifiConnectCallback != null) {
                    wifiConnectCallback.onFailure();
                }
            }
        };

        //连接网络
        connectivityManager.requestNetwork(request, networkCallback);

或是WifiNetworkSuggestion 方式

复制代码
 WifiNetworkSuggestion suggestion = new WifiNetworkSuggestion.Builder()
                .setSsid(ssid)
                .setWpa2Passphrase(password)
                .setIsAppInteractionRequired(true)
                .build();

最后分享工具类

复制代码
public class ConnectWifiUtils {

    private static final String TAG = ConnectWifiUtils.class.getSimpleName();

    private final ConnectivityManager connectivityManager;//连接管理者

    private final WifiManager wifiManager;//Wifi管理者

    private WifiConnectCallback wifiConnectCallback;

    @SuppressLint("StaticFieldLeak")
    private static volatile ConnectWifiUtils mInstance;

    private final Context mContext;

    public ConnectWifiUtils(Context context) {
        mContext = context;
        wifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
        connectivityManager = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
    }

    public static ConnectWifiUtils initialize(Context context) {
        if (mInstance == null) {
            synchronized (ConnectWifiUtils.class) {
                if (mInstance == null) {
                    mInstance = new ConnectWifiUtils(context);
                }
            }
        }
        return mInstance;
    }

    public void setWifiConnectCallback(WifiConnectCallback wifiConnectCallback) {
        this.wifiConnectCallback = wifiConnectCallback;
    }

    /**
     * 连接Wifi
     *
     * @param scanResult 扫描结果
     * @param password   密码
     */
    public void connectWifi(WifiBean scanResult, String password) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            connectBySug(scanResult.getWifiName(), password);

        } else {
            connectByOld(scanResult, password);
        }
    }

    /**
     * Android 10 以下使用
     *
     * @param scanResult 扫描结果
     * @param password   密码
     */
    private void connectByOld(WifiBean scanResult, String password) {
        String ssid = scanResult.getWifiName();
        boolean isSuccess;
        WifiConfiguration configured = isExist(ssid);
        if (configured != null) {
            //在配置表中找到了,直接连接
            isSuccess = wifiManager.enableNetwork(configured.networkId, true);
        } else {
            WifiConfiguration wifiConfig = createWifiConfig(ssid, password, getCipherType(scanResult.getCapabilities()));
            int netId = wifiManager.addNetwork(wifiConfig);
            isSuccess = wifiManager.enableNetwork(netId, true);
        }
        Log.d(TAG, "connectWifi: " + (isSuccess ? "成功" : "失败"));
    }

    /**
     * Android 10及以上版本使用此方式连接Wifi
     *
     * @param ssid     名称
     * @param password 密码
     */
    @SuppressLint("NewApi")
    private void connectByNew(String ssid, String password) {

        WifiNetworkSpecifier wifiNetworkSpecifier = new WifiNetworkSpecifier.Builder()
                .setSsid(ssid)
                .setWpa2Passphrase(password)
                .build();
        //网络请求
        NetworkRequest request = new NetworkRequest.Builder()
                .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
                .removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
                .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
                .addCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED)
                .setNetworkSpecifier(wifiNetworkSpecifier)
                .build();
        //网络回调处理
        ConnectivityManager.NetworkCallback networkCallback = new ConnectivityManager.NetworkCallback() {
            @Override
            public void onAvailable(@NonNull Network network) {
                super.onAvailable(network);
                if (wifiConnectCallback != null) {
                    wifiConnectCallback.onSuccess(network);
                    Log.d("WifiUtils", "======onAvailable: ====连接成功======");
                }
            }

            @Override
            public void onUnavailable() {
                super.onUnavailable();
                Log.d("WifiUtils", "======onAvailable: ====连接失败======");
                if (wifiConnectCallback != null) {
                    wifiConnectCallback.onFailure();
                }
            }
        };

        //请求连接网络
        connectivityManager.requestNetwork(request, networkCallback);
    }

    @SuppressLint("NewApi")
    private void connectBySug(String ssid, String password) {
        WifiNetworkSuggestion suggestion = new WifiNetworkSuggestion.Builder()
                .setSsid(ssid)
                .setWpa2Passphrase(password)
                .setIsAppInteractionRequired(true)
                .build();
        List<WifiNetworkSuggestion> suggestionList = new ArrayList<>();
        suggestionList.add(suggestion);
        int status = wifiManager.addNetworkSuggestions(suggestionList);
        if (status != WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS) {
            return;
        }
        Log.d(TAG, "======onReceive: ==网络连接状态=111111111===");
        IntentFilter intentFilter = new IntentFilter(WifiManager.ACTION_WIFI_NETWORK_SUGGESTION_POST_CONNECTION);
        BroadcastReceiver wifiScanReceiver = new BroadcastReceiver() {

            @Override
            public void onReceive(Context context, Intent intent) {

                Log.d(TAG, "======onReceive: ==网络连接状态====");
                if (!intent.getAction().equals(WifiManager.ACTION_WIFI_NETWORK_SUGGESTION_POST_CONNECTION)) {

                    return;
                }
            }
        };
        mContext.registerReceiver(wifiScanReceiver, intentFilter);
    }

    /**
     * 创建Wifi配置
     *
     * @param ssid     名称
     * @param password 密码
     * @param type     类型
     */
    private WifiConfiguration createWifiConfig(String ssid, String password, WifiCapability type) {
        WifiConfiguration config = new WifiConfiguration();
        config.allowedAuthAlgorithms.clear();
        config.allowedGroupCiphers.clear();
        config.allowedKeyManagement.clear();
        config.allowedPairwiseCiphers.clear();
        config.allowedProtocols.clear();
        config.SSID = "\"" + ssid + "\"";
        WifiConfiguration configured = isExist(ssid);
        if (configured != null) {
            wifiManager.removeNetwork(configured.networkId);
            wifiManager.saveConfiguration();
        }

        //不需要密码的场景
        if (type == WifiCapability.WIFI_CIPHER_NO_PASS) {
            config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
            //以WEP加密的场景
        } else if (type == WifiCapability.WIFI_CIPHER_WEP) {
            config.hiddenSSID = true;
            config.wepKeys[0] = "\"" + password + "\"";
            config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
            config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.SHARED);
            config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
            config.wepTxKeyIndex = 0;
            //以WPA加密的场景,自己测试时,发现热点以WPA2建立时,同样可以用这种配置连接
        } else if (type == WifiCapability.WIFI_CIPHER_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.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
            config.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
            config.status = WifiConfiguration.Status.ENABLED;
        }
        return config;
    }

    /**
     * 网络是否连接
     */
    @SuppressLint("NewApi")
    public static boolean isNetConnected(ConnectivityManager connectivityManager) {
        return connectivityManager.getActiveNetwork() != null;
    }

    /**
     * 连接网络类型是否为Wifi
     */
    @SuppressLint("NewApi")
    public static boolean isWifi(ConnectivityManager connectivityManager) {
        if (connectivityManager.getActiveNetwork() == null) {
            return false;
        }
        NetworkCapabilities networkCapabilities = connectivityManager.getNetworkCapabilities(connectivityManager.getActiveNetwork());
        if (networkCapabilities != null) {
            return false;
        }
        return networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI);
    }

    /**
     * 配置表是否存在对应的Wifi配置
     *
     * @param SSID
     * @return
     */
    @SuppressLint("MissingPermission")
    private WifiConfiguration isExist(String SSID) {
        List<WifiConfiguration> existingConfigs = wifiManager.getConfiguredNetworks();
        for (WifiConfiguration existingConfig : existingConfigs) {
            if (existingConfig.SSID.equals("\"" + SSID + "\"")) {
                return existingConfig;
            }
        }
        return null;
    }

    private WifiCapability getCipherType(String capabilities) {
        if (capabilities.contains("WEB")) {
            return WifiCapability.WIFI_CIPHER_WEP;
        } else if (capabilities.contains("PSK")) {
            return WifiCapability.WIFI_CIPHER_WPA;
        } else if (capabilities.contains("WPS")) {
            return WifiCapability.WIFI_CIPHER_NO_PASS;
        } else {
            return WifiCapability.WIFI_CIPHER_NO_PASS;
        }
    }

    /**
     * wifi连接回调接口
     */
    public interface WifiConnectCallback {

        void onSuccess(Network network);

        void onFailure();
    }

    public enum WifiCapability {
        WIFI_CIPHER_WEP, WIFI_CIPHER_WPA, WIFI_CIPHER_NO_PASS
    }

}
相关推荐
hai_android43 分钟前
把 Android App 打包成系统应用(System App)
android·kotlin·android jetpack
JMchen1 小时前
【Jetpack 内核实战 01】开篇:Jetpack 组件全家桶核心逻辑与专栏完整规划
android·kotlin·android jetpack
骑着蜗牛撵大象3273 小时前
Linux 进程间通信之管道:从 pipe() 的内核语义到 FIFO 落地排错
android·java·linux·系统编程·fifo·管道·进程间通信
hunterandroid3 小时前
Retrofit 网络请求的异常处理与重试策略实战
android
sejinan4 小时前
极致轻量与秒级起播:NativeWasmTv 开源硬核技术解析与升级版体验
android·开源·webview·tv
小羊没烦恼!4 小时前
Ajax与JSON的一些总结
android·java·前端·数据库·mysql·算法·okhttp
mmsx4 小时前
Android 静默失败实录:五个没有日志的线上事故
android·kotlin
hai_android5 小时前
从零实现一个支持跨进程(IPC)的自定义 Toast
android·kotlin·android jetpack
龙腾-虎跃5 小时前
基于 SIP 协议的自研电话终端:FreeSWITCH 语音与视频通信实战
android·音视频·freeswitch·sip协议终端·wertc
imDwAaY6 小时前
操作系统如何管理程序运行?从线程、进程到内存隔离与用户态切换:CS162 Note2
android·java·redis