瀏覽代碼

提交人:江天明
提交内容:修改模块名称

江天明 2 年之前
父節點
當前提交
80d50a6fd4

+ 1 - 1
BusinessAuth/build.gradle

@@ -9,7 +9,7 @@ android {
 
     defaultConfig {
         minSdk 21
-        targetSdk 30
+        targetSdk 27
 
         testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
         consumerProguardFiles "consumer-rules.pro"

+ 1 - 1
BusinessMain/build.gradle

@@ -9,7 +9,7 @@ android {
 
     defaultConfig {
         minSdk 21
-        targetSdk 30
+        targetSdk 27
 
         testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
         consumerProguardFiles "consumer-rules.pro"

+ 1 - 1
BusinessRouter/build.gradle

@@ -9,7 +9,7 @@ android {
 
     defaultConfig {
         minSdk 21
-        targetSdk 30
+        targetSdk 27
 
         testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
         consumerProguardFiles "consumer-rules.pro"

+ 1 - 1
BusinessSetting/build.gradle

@@ -9,7 +9,7 @@ android {
 
     defaultConfig {
         minSdk 21
-        targetSdk 30
+        targetSdk 27
 
         testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
         consumerProguardFiles "consumer-rules.pro"

+ 15 - 0
BusinessSetting/src/main/AndroidManifest.xml

@@ -1,6 +1,21 @@
 <?xml version="1.0" encoding="utf-8"?>
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
     package="com.develop.setting">
+    <uses-permission
+        android:name="android.permission.WRITE_SETTINGS"
+        tools:ignore="ProtectedPermissions" />
+
+    <uses-permission android:name="android.permission.INTERNET" />
+
+    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
+    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+
+    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
+    <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
+
+    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
+    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
 
     <application>
         <activity android:name=".init.ui.PowerAnimationActivity" />

+ 7 - 20
BusinessSetting/src/main/java/com/develop/setting/init/adapter/WifiListAdapter.kt

@@ -15,15 +15,16 @@ import com.chad.library.adapter.base.viewholder.BaseViewHolder
 import com.develop.food.base.data.model.WifiModel
 import com.develop.food.base.manager.WifiLevel
 import com.develop.food.base.manager.WifiManager
+import com.develop.food.base.manager.wifi.AccessPoint
 import com.develop.food.base.utils.GlobalToast
 import com.develop.setting.R
 
-class WifiListAdapter : BaseQuickAdapter<WifiModel, BaseViewHolder>
+class WifiListAdapter : BaseQuickAdapter<AccessPoint, BaseViewHolder>
     (R.layout.item_wifi_content) {
     private var selectedPosition = -1
     var onOkClickListener: OnOkClickListener? = null
-    override fun convert(holder: BaseViewHolder, item: WifiModel) {
-        holder.getView<AppCompatTextView>(R.id.tv_wifi_name).text = item.wifiName
+    override fun convert(holder: BaseViewHolder, item: AccessPoint) {
+        holder.getView<AppCompatTextView>(R.id.tv_wifi_name).text = item.ssid
         val tvWifiState = holder.getView<AppCompatTextView>(R.id.tv_wifi_state)
         val wifiLevel = holder.getView<ImageView>(R.id.iv_signal)
         val lockView = holder.getView<ImageView>(R.id.iv_lock)
@@ -32,7 +33,7 @@ class WifiListAdapter : BaseQuickAdapter<WifiModel, BaseViewHolder>
         val ckbEye = holder.getView<CheckBox>(R.id.ckb_eye)
         val etPwd = holder.getView<EditText>(R.id.et_pwd)
         val tvOk = holder.getView<AppCompatTextView>(R.id.tv_ok)
-        if (item.isOnLine) {
+        if (item.isSaved) {
             lockView.visibility = View.GONE
             tvWifiState.text = context.getString(R.string.on_line)
         } else {
@@ -54,20 +55,6 @@ class WifiListAdapter : BaseQuickAdapter<WifiModel, BaseViewHolder>
             contentLayout.setBackgroundResource(0)
             inputLayout.visibility = View.GONE
         }
-        when (WifiManager.getWifiLevel(item.rssi)) {
-            WifiLevel.HEIGHT -> {
-
-            }
-            WifiLevel.GENERAL -> {
-
-            }
-            WifiLevel.LOW -> {
-
-            }
-            WifiLevel.EXTREMELY -> {
-
-            }
-        }
 
         ckbEye.setOnCheckedChangeListener { compoundButton, b ->
             if (b) {
@@ -82,7 +69,7 @@ class WifiListAdapter : BaseQuickAdapter<WifiModel, BaseViewHolder>
                 GlobalToast.showToast(context.getString(R.string.pwd_can_not_be_empty))
                 return@setOnClickListener
             }
-            item.pwd = pwd
+            item.password = pwd
             onOkClickListener?.onOkClick(item)
         }
 
@@ -101,7 +88,7 @@ class WifiListAdapter : BaseQuickAdapter<WifiModel, BaseViewHolder>
 
 
     interface OnOkClickListener {
-        fun onOkClick(wifiModel: WifiModel)
+        fun onOkClick(accessPoint: AccessPoint)
     }
 
 }

+ 88 - 10
BusinessSetting/src/main/java/com/develop/setting/init/ui/WifiListActivity.kt

@@ -1,29 +1,37 @@
 package com.develop.setting.init.ui
 
 import android.graphics.Rect
+import android.net.wifi.WifiConfiguration
 import android.os.Bundle
 import android.view.LayoutInflater
 import android.view.View
 import androidx.recyclerview.widget.RecyclerView
 import com.alibaba.android.arouter.facade.annotation.Route
+import com.blankj.utilcode.util.NetworkUtils
 import com.develop.food.base.common.WIFI_FROM_MAIN_SETTING
 import com.develop.food.base.data.DataFactory
 import com.develop.food.base.data.model.WifiModel
 import com.develop.food.base.event.FinishAtyEvent
-import com.develop.food.base.ui.BaseActivity
-import com.develop.food.base.utils.ResDimension
+import com.develop.food.base.manager.wifi.AccessPoint
+import com.develop.food.base.manager.wifi.WifiReceiver
+import com.develop.food.base.manager.wifi.WifiUtils
 import com.develop.food.base.router.Screens
 import com.develop.food.base.router.navigateTo
+import com.develop.food.base.ui.BaseActivity
+import com.develop.food.base.utils.ResDimension
 import com.develop.setting.R
 import com.develop.setting.databinding.ActivityWifiListBinding
 import com.develop.setting.init.adapter.WifiListAdapter
-import com.eurigo.wifilib.WifiUtils
+import com.yanzhenjie.permission.AndPermission
+import com.yanzhenjie.permission.runtime.Permission
 import org.greenrobot.eventbus.EventBus
 
 @Route(path = Screens.Setting.WIFI)
-class WifiListActivity : BaseActivity<ActivityWifiListBinding>() {
+class WifiListActivity : BaseActivity<ActivityWifiListBinding>(), WifiReceiver.WifiStateListener,
+    NetworkUtils.OnNetworkStatusChangedListener {
     private var wifiListAdapter = WifiListAdapter()
     private var isFromMainSetting = false
+    private var accessPointList = mutableListOf<AccessPoint>()
     override fun createViewBinding(inflater: LayoutInflater): ActivityWifiListBinding {
         return ActivityWifiListBinding.inflate(layoutInflater)
     }
@@ -31,11 +39,11 @@ class WifiListActivity : BaseActivity<ActivityWifiListBinding>() {
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
         WifiUtils.getInstance().init(this)
-        WifiUtils.getInstance().openWifi()
-        isFromMainSetting = intent.extras?.getBoolean(WIFI_FROM_MAIN_SETTING)?:false
+        NetworkUtils.registerNetworkStatusChangedListener(this)
+        isFromMainSetting = intent.extras?.getBoolean(WIFI_FROM_MAIN_SETTING) ?: false
 
         if (isFromMainSetting) {
-           binding.tvSkin.visibility = View.INVISIBLE
+            binding.tvSkin.visibility = View.INVISIBLE
         }
 
         binding.topBar.listenBackClick {
@@ -45,13 +53,12 @@ class WifiListActivity : BaseActivity<ActivityWifiListBinding>() {
 
 
         wifiListAdapter.apply {
-            setList(DataFactory.genTestWifiList())
             onOkClickListener = object : WifiListAdapter.OnOkClickListener {
-                override fun onOkClick(wifiModel: WifiModel) {
+                override fun onOkClick(accessPoint: AccessPoint) {
 
                 }
             }
-            setOnItemClickListener {  adapter, view, position ->
+            setOnItemClickListener { adapter, view, position ->
                 updateSelectedPosition(position)
             }
         }
@@ -97,6 +104,77 @@ class WifiListActivity : BaseActivity<ActivityWifiListBinding>() {
 
     override fun onDestroy() {
         super.onDestroy()
+        WifiUtils.getInstance().unregisterWifiBroadcast()
         WifiUtils.getInstance().release()
     }
+
+    override fun onResume() {
+        super.onResume()
+        if (!WifiUtils.getInstance().isRegisterWifiBroadcast) {
+            WifiUtils.getInstance().registerWifiBroadcast(this)
+        }
+
+        AndPermission.with(this).runtime().permission(
+            Permission.ACCESS_FINE_LOCATION,
+            Permission.ACCESS_BACKGROUND_LOCATION, Permission.ACCESS_COARSE_LOCATION
+        )
+            .onGranted {
+                WifiUtils.getInstance().openWifi()
+            }.start()
+    }
+
+    override fun onWifiOpen() {
+        val lastWifiInfo = WifiUtils.getInstance().lastWifiInfo
+        val lastNetworkInfo = WifiUtils.getInstance().lastNetworkInfo
+        var lastWifiConfiguration: WifiConfiguration? = null
+        if (lastWifiInfo != null && lastWifiInfo.networkId != AccessPoint.INVALID_NETWORK_ID) {
+            lastWifiConfiguration = WifiUtils.getInstance().getWifiConfigurationForNetworkId(lastWifiInfo.networkId)
+        }
+
+        WifiUtils.getInstance().wifiList.forEach {
+            if (it.SSID.isNotEmpty()){
+                val accessPoint = AccessPoint(this, it)
+                if (!accessPointList.contains(accessPoint)){
+                    val wifiConfigurations = WifiUtils.getInstance().wifiConfigurations
+                    if (wifiConfigurations != null) {
+                        for (config in wifiConfigurations) {
+                            if (accessPoint.quotedSSID.equals(config.SSID)) {
+                                accessPoint.setWifiConfiguration(config)
+                            }
+                        }
+                    }
+                    if ( lastWifiInfo!= null && lastNetworkInfo != null) {
+                        accessPoint.update(lastWifiConfiguration, lastWifiInfo, lastNetworkInfo)
+                    }
+                    accessPointList.add(accessPoint)
+                }
+            }
+        }
+        accessPointList.sorted()
+        wifiListAdapter.setList(accessPointList)
+    }
+
+    override fun onWifiClose() {
+
+    }
+
+    override fun onHotpotOpen() {
+
+    }
+
+    override fun onHotpotOpenError() {
+
+    }
+
+    override fun onHotpotClose() {
+
+    }
+
+    override fun onDisconnected() {
+
+    }
+
+    override fun onConnected(networkType: NetworkUtils.NetworkType) {
+
+    }
 }

+ 1 - 1
BusinessStep/build.gradle

@@ -9,7 +9,7 @@ android {
 
     defaultConfig {
         minSdk 21
-        targetSdk 30
+        targetSdk 27
 
         testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
         consumerProguardFiles "consumer-rules.pro"

+ 1 - 1
app/build.gradle

@@ -10,7 +10,7 @@ android {
     defaultConfig {
         applicationId "com.develop.foodcooking"
         minSdk 21
-        targetSdk 30
+        targetSdk 27
         versionCode 1
         versionName "1.0"
 

+ 1 - 1
app/src/main/AndroidManifest.xml

@@ -9,11 +9,11 @@
     <uses-permission android:name="android.permission.INTERNET" />
     <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
     <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
-    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
     <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
     <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
 
     <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
+    <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"/>
     <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
     <application
         android:name=".FoodCookApp"

+ 1 - 1
libBase/build.gradle

@@ -9,7 +9,7 @@ android {
 
     defaultConfig {
         minSdk 21
-        targetSdk 30
+        targetSdk 27
 
         testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
         consumerProguardFiles "consumer-rules.pro"

+ 471 - 0
libBase/src/main/java/com/develop/food/base/manager/wifi/AccessPoint.java

@@ -0,0 +1,471 @@
+package com.develop.food.base.manager.wifi;
+
+import android.content.Context;
+import android.net.NetworkInfo;
+import android.net.wifi.ScanResult;
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiEnterpriseConfig;
+import android.net.wifi.WifiInfo;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.TextUtils;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import java.lang.reflect.Method;
+
+public class AccessPoint implements Parcelable, Comparable<AccessPoint> {
+    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;
+
+    private static final int PSK_UNKNOWN = 0;
+    private static final int PSK_WPA = 1;
+    private static final int PSK_WPA2 = 2;
+    private static final int PSK_WPA_WPA2 = 3;
+
+    /**
+     * Anything worse than or equal to this will show 0 bars.
+     */
+    private static final int MIN_RSSI = -100;
+
+    /**
+     * Anything better than or equal to this will show the max bars.
+     */
+    private static final int MAX_RSSI = -55;
+
+    public static final int SIGNAL_LEVELS = 4;
+
+    public static final int INVALID_NETWORK_ID = -1;
+
+    public Context context;
+    public String ssid;
+    public String bssid;
+    public int security;
+    public int networkId = INVALID_NETWORK_ID;
+    public int pskType = PSK_UNKNOWN;
+
+    public WifiConfiguration wifiConfiguration;
+
+    private int rssi = Integer.MAX_VALUE;
+
+    public WifiInfo wifiInfo;
+    public NetworkInfo networkInfo;
+
+    public boolean isSecured = true;
+    public String password;
+
+    private boolean isPasswordError = false;
+    private boolean selected;
+
+    public boolean isSelected() {
+        return selected;
+    }
+
+    public void setSelected(boolean selected) {
+        this.selected = selected;
+    }
+
+    public AccessPoint(Context context, ScanResult scanResult) {
+        this.context = context;
+        initWithScanResult(scanResult);
+    }
+
+    public AccessPoint(Context context, WifiConfiguration configuration) {
+        this.context = context;
+        initWithConfiguration(configuration);
+    }
+
+    public AccessPoint(WifiConfiguration configuration) {
+        initWithConfiguration(configuration);
+    }
+
+    /**
+     * 根据 ScanResult 初始化 AccessPoint
+     */
+    private void initWithScanResult(ScanResult result) {
+        this.ssid = result.SSID;
+        this.bssid = result.BSSID;
+        this.security = getSecurity(result);
+        if (this.security == SECURITY_PSK) {
+            this.pskType = getPskType(result);
+        }
+        if (this.security == SECURITY_NONE) {
+            this.isSecured = false;
+        }
+        this.rssi = result.level;
+    }
+
+    private void initWithConfiguration(WifiConfiguration configuration) {
+        this.ssid = (configuration.SSID == null ? "" : removeDoubleQuotes(configuration.SSID));
+        this.bssid = configuration.BSSID;
+        this.security = getSecurity(configuration);
+        this.networkId = configuration.networkId;
+        this.wifiConfiguration = configuration;
+    }
+
+    public int getSignalLevel() {
+        if (rssi == Integer.MAX_VALUE || rssi <= -100) {
+            return 0;
+        }
+        return calculateSignalLevel(rssi, SIGNAL_LEVELS);
+    }
+
+    public static int calculateSignalLevel(int rssi, int numLevels) {
+        if (rssi <= MIN_RSSI) {
+            return 0;
+        } else if (rssi >= MAX_RSSI) {
+            return numLevels - 1;
+        } else {
+            float inputRange = (MAX_RSSI - MIN_RSSI);
+            float outputRange = (numLevels - 1);
+            return (int) ((float) (rssi - MIN_RSSI) * outputRange / inputRange);
+        }
+    }
+
+    /**
+     * 获取 PSK 类型
+     */
+    private static int getPskType(ScanResult result) {
+        boolean wpa = result.capabilities.contains("WPA-PSK");
+        boolean wpa2 = result.capabilities.contains("WPA2-PSK");
+        if (wpa2 && wpa) {
+            return PSK_WPA_WPA2;
+        } else if (wpa2) {
+            return PSK_WPA2;
+        } else if (wpa) {
+            return PSK_WPA;
+        } else {
+            return PSK_UNKNOWN;
+        }
+    }
+
+    /**
+     * 根据 ScanResult 获取加密类型
+     */
+    private 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;
+    }
+
+    /**
+     * 根据 WifiConfiguration 获取加密类型
+     */
+    private static int getSecurity(WifiConfiguration config) {
+        if (config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_PSK)) {
+            return SECURITY_PSK;
+        }
+        if (config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_EAP) ||
+                config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.IEEE8021X)) {
+            return SECURITY_EAP;
+        }
+        return (config.wepKeys[0] != null) ? SECURITY_WEP : SECURITY_NONE;
+    }
+
+    /**
+     * 获取加密类型的字符串描述
+     */
+    public static String securityToString(int security, int pskType) {
+        if (security == SECURITY_WEP) {
+            return "WEP";
+        } else if (security == SECURITY_PSK) {
+            if (pskType == PSK_WPA) {
+                return "WPA";
+            } else if (pskType == PSK_WPA2) {
+                return "WPA2";
+            } else if (pskType == PSK_WPA_WPA2) {
+                return "WPA_WPA2";
+            }
+            return "PSK";
+        } else if (security == SECURITY_EAP) {
+            return "EAP";
+        }
+        return "NONE";
+    }
+
+    public NetworkInfo.DetailedState getDetailedState() {
+        if (networkInfo != null) {
+            return networkInfo.getDetailedState();
+        }
+        return null;
+    }
+
+    public boolean update(@Nullable WifiConfiguration config, WifiInfo info, NetworkInfo networkInfo) {
+        boolean reorder = false;
+        if (info != null && isInfoForThisAccessPoint(config, info)) {
+            reorder = (this.wifiInfo == null);
+            this.wifiInfo = info;
+            this.networkInfo = networkInfo;
+        } else if (this.wifiInfo != null) {
+            reorder = true;
+            this.wifiInfo = null;
+            this.networkInfo = null;
+        }
+        return reorder;
+    }
+
+    public void setWifiConfiguration(WifiConfiguration config) {
+        this.wifiConfiguration = config;
+        networkId = config.networkId;
+    }
+
+    /**
+     * 生成 wifiConfiguration
+     */
+    public void generateNetworkConfig() {
+        if (wifiConfiguration != null)
+            return;
+        wifiConfiguration = new WifiConfiguration();
+        wifiConfiguration.SSID = getQuotedSSID();
+        switch (security) {
+            case SECURITY_NONE:
+                wifiConfiguration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
+                break;
+            case SECURITY_WEP:
+                wifiConfiguration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
+                wifiConfiguration.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
+                wifiConfiguration.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.SHARED);
+                int length = password.length();
+                if ((length == 10 || length == 26 || length == 58) &&
+                        password.matches("[0-9A-Fa-f]*")) {
+                    wifiConfiguration.wepKeys[0] = password;
+                } else {
+                    wifiConfiguration.wepKeys[0] = '"' + password + '"';
+                }
+                break;
+            case SECURITY_PSK:
+                wifiConfiguration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
+                if (password.matches("[0-9A-Fa-f]{64}")) {
+                    wifiConfiguration.preSharedKey = password;
+                } else {
+                    wifiConfiguration.preSharedKey = '"' + password + '"';
+                }
+                break;
+            case SECURITY_EAP:
+                // 暂时忽略
+                break;
+        }
+
+    }
+
+    /**
+     * Identify if this configuration represents a Passpoint network
+     */
+    private boolean isPassPoint(WifiConfiguration config) {
+        return config != null && !TextUtils.isEmpty(config.FQDN) &&
+                config.enterpriseConfig != null &&
+                config.enterpriseConfig.getEapMethod() != WifiEnterpriseConfig.Eap.NONE;
+    }
+
+    /**
+     * Return whether the given {@link WifiInfo} is for this access point.
+     * If the current AP does not have a network Id then the wifiConfiguration is used to
+     * match based on SSID and security.
+     */
+    private boolean isInfoForThisAccessPoint(WifiConfiguration config, WifiInfo info) {
+        if (!isPassPoint(wifiConfiguration) && networkId != INVALID_NETWORK_ID) {
+            return networkId == info.getNetworkId();
+        } else if (config != null) {
+            return matches(config);
+        } else {
+            return ssid.equals(removeDoubleQuotes(info.getSSID()));
+        }
+    }
+
+    private boolean matches(WifiConfiguration config) {
+        if (isPassPoint(config) && isPassPoint(wifiConfiguration)) {
+            return config.FQDN.equals(this.wifiConfiguration.FQDN);
+        } else {
+            return ssid.equals(removeDoubleQuotes(config.SSID)) &&
+                    security == getSecurity(config) &&
+                    this.wifiConfiguration == null;
+        }
+    }
+
+    public void setPasswordError(boolean passwordError) {
+        isPasswordError = passwordError;
+        wifiConfiguration = null;
+        networkId = INVALID_NETWORK_ID;
+    }
+
+    public boolean isPasswordError() {
+        return isPasswordError;
+    }
+
+    public boolean isSaved() {
+        return networkId != INVALID_NETWORK_ID;
+    }
+
+    public String getPassword() {
+        return password;
+    }
+
+    public void setPassword(String password) {
+        this.password = password;
+    }
+
+    /**
+     * 通过反射获取 NetworkSelectionStatus
+     */
+    public boolean isNetworkEnabled() {
+        boolean enabled = true;
+        if (wifiConfiguration != null) {
+            try {
+                Class NetworkSelectionStatus = Class.forName("android.net.wifi.WifiConfiguration$NetworkSelectionStatus");
+                Method getNetworkSelectionStatus = WifiConfiguration.class.getMethod("getNetworkSelectionStatus");
+                Object networkSelectionStatus = getNetworkSelectionStatus.invoke(wifiConfiguration);
+                Method isNetworkEnabled = NetworkSelectionStatus.getMethod("isNetworkEnabled");
+                enabled = (boolean) isNetworkEnabled.invoke(networkSelectionStatus);
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+        return enabled;
+    }
+
+    /**
+     * 通过反射获取 NetworkSelectionStatus
+     */
+    public int getNetworkSelectionDisableReason() {
+        int status = 0;
+        if (wifiConfiguration != null) {
+            try {
+                Class NetworkSelectionStatus = Class.forName("android.net.wifi.WifiConfiguration$NetworkSelectionStatus");
+                Method getNetworkSelectionStatus = WifiConfiguration.class.getMethod("getNetworkSelectionStatus");
+                Object networkSelectionStatus = getNetworkSelectionStatus.invoke(wifiConfiguration);
+                Method getDisableReason = NetworkSelectionStatus.getMethod("getNetworkSelectionDisableReason");
+                status = (int) getDisableReason.invoke(networkSelectionStatus);
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+        return status;
+    }
+
+    public boolean isActive() {
+        return networkInfo != null &&
+                (networkId != INVALID_NETWORK_ID ||
+                        networkInfo.getState() != NetworkInfo.State.DISCONNECTED);
+    }
+
+    public boolean isActivated() {
+        return networkId != INVALID_NETWORK_ID &&
+                networkInfo != null &&
+                networkInfo.getState() == NetworkInfo.State.CONNECTED;
+    }
+
+    /**
+     * 添加双引号
+     */
+    public String getQuotedSSID() {
+        return "\"" + ssid + "\"";
+    }
+
+    /**
+     * 移除双引号
+     */
+    static String removeDoubleQuotes(String string) {
+        if (TextUtils.isEmpty(string)) {
+            return "";
+        }
+        int length = string.length();
+        if ((length > 1) && (string.charAt(0) == '"')
+                && (string.charAt(length - 1) == '"')) {
+            return string.substring(1, length - 1);
+        }
+        return string;
+    }
+
+    @Override
+    public int compareTo(@NonNull AccessPoint other) {
+        // Active one goes first.
+        if (isActive() && !other.isActive()) return -1;
+        if (!isActive() && other.isActive()) return 1;
+        // Reachable one goes before unreachable one.
+        if (this.rssi != Integer.MAX_VALUE && other.rssi == Integer.MAX_VALUE) return -1;
+        if (this.rssi == Integer.MAX_VALUE && other.rssi != Integer.MAX_VALUE) return 1;
+        // Configured one goes before unConfigured one.
+        if (isSaved() && !other.isSaved()) return -1;
+        if (!isSaved() && other.isSaved()) return 1;
+        int difference = other.getSignalLevel() - this.getSignalLevel();
+        if (difference != 0) {
+            return difference;
+        }
+        return this.ssid.compareToIgnoreCase(other.ssid);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj == null) {
+            return false;
+        }
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof AccessPoint) {
+            return ssid.equals(((AccessPoint) obj).ssid);
+        }
+        return false;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = 0;
+        if (wifiInfo != null) result += 13 * wifiInfo.hashCode();
+        result += 19 * networkId;
+        result += 23 * ssid.hashCode();
+        return result;
+    }
+
+    protected AccessPoint(Parcel in) {
+        ssid = in.readString();
+        bssid = in.readString();
+        security = in.readInt();
+        networkId = in.readInt();
+        pskType = in.readInt();
+        wifiConfiguration = in.readParcelable(WifiConfiguration.class.getClassLoader());
+        rssi = in.readInt();
+        wifiInfo = in.readParcelable(WifiInfo.class.getClassLoader());
+        networkInfo = in.readParcelable(NetworkInfo.class.getClassLoader());
+        isSecured = in.readByte() != 0;
+    }
+
+    public static final Creator<AccessPoint> CREATOR = new Creator<AccessPoint>() {
+        @Override
+        public AccessPoint createFromParcel(Parcel in) {
+            return new AccessPoint(in);
+        }
+
+        @Override
+        public AccessPoint[] newArray(int size) {
+            return new AccessPoint[size];
+        }
+    };
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeString(ssid);
+        dest.writeString(bssid);
+        dest.writeInt(security);
+        dest.writeInt(networkId);
+        dest.writeInt(pskType);
+        dest.writeParcelable(wifiConfiguration, flags);
+        dest.writeInt(rssi);
+        dest.writeParcelable(wifiInfo, flags);
+        dest.writeParcelable(networkInfo, flags);
+        dest.writeByte((byte) (isSecured ? 1 : 0));
+    }
+}

+ 121 - 0
libBase/src/main/java/com/develop/food/base/manager/wifi/WifiReceiver.java

@@ -0,0 +1,121 @@
+package com.develop.food.base.manager.wifi;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.net.wifi.WifiManager;
+
+/**
+ * @author Eurigo
+ * Created on 2021/7/28 17:48
+ * desc   : WIFI及热点状态
+ */
+public class WifiReceiver extends BroadcastReceiver {
+
+    private static final int WIFI_AP_STATE_DISABLING = 10;
+    private static final int WIFI_AP_STATE_DISABLED = 11;
+    private static final int WIFI_AP_STATE_ENABLING = 12;
+    private static final int WIFI_AP_STATE_ENABLED = 13;
+    private static final int WIFI_AP_STATE_FAILED = 14;
+
+    private WifiStateListener wifiStateListener;
+
+    public WifiStateListener getWifiStateListener() {
+        return wifiStateListener;
+    }
+
+    public void setWifiStateListener(WifiStateListener wifiStateListener) {
+        this.wifiStateListener = wifiStateListener;
+    }
+
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        if (intent.getAction() != null &&
+                intent.getAction().equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
+            switch (intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, WifiManager.WIFI_STATE_UNKNOWN)) {
+                case WifiManager.WIFI_STATE_DISABLED:
+                    setWifiState(false);
+                    break;
+                case WifiManager.WIFI_STATE_ENABLED:
+                    setWifiState(true);
+                    break;
+                case WifiManager.WIFI_STATE_DISABLING:
+                case WifiManager.WIFI_STATE_ENABLING:
+                case WifiManager.WIFI_STATE_UNKNOWN:
+                default:
+                    break;
+
+            }
+        }
+        if (intent.getAction() != null &&
+                "android.net.wifi.WIFI_AP_STATE_CHANGED".equals(intent.getAction())) {
+            //热点的状态为:10---正在关闭;11---已关闭;12---正在开启;13---已开启
+            int state = intent.getIntExtra("wifi_state", 0);
+            switch (state) {
+                // 热点状态:已关闭
+                case WIFI_AP_STATE_DISABLED:
+                    setHotpotState(false);
+                    break;
+                // 热点状态:已开启
+                case WIFI_AP_STATE_ENABLED:
+                    setHotpotState(true);
+                    break;
+                // 打开热点异常
+                case WIFI_AP_STATE_FAILED:
+                    if (wifiStateListener != null) {
+                        wifiStateListener.onHotpotOpenError();
+                    }
+                    break;
+                default:
+                    break;
+            }
+        }
+    }
+
+    public interface WifiStateListener {
+        /**
+         * WiFi打开
+         */
+        void onWifiOpen();
+
+        /**
+         * WiFi关闭
+         */
+        void onWifiClose();
+
+        /**
+         * 热点打开
+         */
+        void onHotpotOpen();
+
+        /**
+         * 热点打开异常
+         */
+        void onHotpotOpenError();
+
+        /**
+         * 热点关闭
+         */
+        void onHotpotClose();
+    }
+
+    private void setWifiState(boolean state) {
+        if (wifiStateListener != null) {
+            if (state) {
+                wifiStateListener.onWifiOpen();
+            } else {
+                wifiStateListener.onWifiClose();
+            }
+        }
+    }
+
+    private void setHotpotState(boolean state) {
+        if (wifiStateListener != null) {
+            if (state) {
+                wifiStateListener.onHotpotOpen();
+            } else {
+                wifiStateListener.onHotpotClose();
+            }
+        }
+    }
+}

+ 550 - 0
libBase/src/main/java/com/develop/food/base/manager/wifi/WifiUtils.java

@@ -0,0 +1,550 @@
+package com.develop.food.base.manager.wifi;
+
+import static android.Manifest.permission.ACCESS_COARSE_LOCATION;
+import static android.Manifest.permission.ACCESS_FINE_LOCATION;
+import static android.content.Context.WIFI_SERVICE;
+import static android.os.Build.VERSION_CODES.M;
+import static android.os.Build.VERSION_CODES.O;
+import static android.os.Build.VERSION_CODES.P;
+
+import android.annotation.SuppressLint;
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.net.ConnectivityManager;
+import android.net.DhcpInfo;
+import android.net.NetworkInfo;
+import android.net.Uri;
+import android.net.wifi.ScanResult;
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiInfo;
+import android.net.wifi.WifiManager;
+import android.os.Build;
+import android.provider.Settings;
+import android.text.TextUtils;
+import android.util.Log;
+
+import androidx.annotation.RequiresApi;
+import androidx.core.content.ContextCompat;
+
+
+import com.eurigo.dx.stock.ProxyBuilder;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * @author Eurigo
+ * Created on 2021/7/14 16:46
+ * desc   :
+ */
+public class WifiUtils {
+
+    private static final String TAG = "WifiUtils";
+
+    public WifiUtils() {
+    }
+
+    public static WifiUtils getInstance() {
+        return SingletonHelper.INSTANCE;
+    }
+
+    private static class SingletonHelper {
+        @SuppressLint("StaticFieldLeak")
+        private final static WifiUtils INSTANCE = new WifiUtils();
+    }
+
+    /**
+     * 请求修改系统设置Code
+     */
+    public static final int REQUEST_WRITE_SETTING_CODE = 1;
+
+    private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
+
+    private WifiReceiver wifiReceiver;
+
+    private WifiManager wifiManager;
+
+    private ConnectivityManager connectivityManager;
+
+    private Context mContext;
+
+
+    public void init(Context mContext) {
+        this.mContext = mContext;
+    }
+
+    private WifiManager getWifiManager() {
+        if (mContext == null) {
+            throw new RuntimeException("please init first");
+        }
+        if (wifiManager == null) {
+            wifiManager = (WifiManager) mContext.getApplicationContext().getSystemService(WIFI_SERVICE);
+        }
+        return wifiManager;
+    }
+
+    private ConnectivityManager getConnectivityManager() {
+        if (mContext == null) {
+            throw new RuntimeException("please init first");
+        }
+        if (connectivityManager == null) {
+            connectivityManager = (ConnectivityManager) mContext
+                    .getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);
+        }
+        return connectivityManager;
+    }
+
+    @SuppressLint("MissingPermission")
+    public NetworkInfo getLastNetworkInfo() {
+        return getConnectivityManager().getActiveNetworkInfo();
+    }
+
+    public WifiInfo getLastWifiInfo() {
+        return getWifiManager().getConnectionInfo();
+    }
+
+    @SuppressLint("MissingPermission")
+    public List<WifiConfiguration> getWifiConfigurations(){
+        return getWifiManager().getConfiguredNetworks();
+    }
+
+    /**
+     * WiFi是否打开
+     */
+    public boolean isWifiEnable() {
+        return getWifiManager().isWifiEnabled();
+    }
+
+    /**
+     * 打开WiFi
+     */
+    public void openWifi() {
+        getWifiManager().setWifiEnabled(true);
+    }
+
+    /**
+     * 关闭WiFi
+     */
+    public void closeWifi() {
+        getWifiManager().setWifiEnabled(false);
+    }
+
+    /**
+     * 连接WIFI,密码为空则不使用密码连接
+     * 9.0以下设备需要关闭热点
+     *
+     * @param ssid     wifi名称
+     * @param password wifi密码
+     */
+    public void connectWifi(Activity activity, String ssid, String password) {
+        // 9.0以下系统不支持关闭热点和WiFi共存
+        if (Build.VERSION.SDK_INT <= P) {
+            if (isApEnable()) {
+                closeAp(activity);
+            }
+        }
+        // 打开WiFi
+        if (!isWifiEnable()) {
+            openWifi();
+        }
+        // 需要等待WiFi开启再去连接
+        new ThreadPoolExecutor(CPU_COUNT
+                , 2 * CPU_COUNT + 1
+                , 60
+                , TimeUnit.SECONDS
+                , new LinkedBlockingQueue<>()
+                , new ConnectWiFiThread()).execute(new Runnable() {
+            @Override
+            public void run() {
+                while (!getWifiManager().isWifiEnabled()) {
+                    try {
+                        Thread.sleep(1000);
+                    } catch (InterruptedException e) {
+                        e.printStackTrace();
+                    }
+                }
+                getWifiManager().disableNetwork(getWifiManager().getConnectionInfo().getNetworkId());
+                int netId = getWifiManager().addNetwork(getWifiConfig(ssid, password, !TextUtils.isEmpty(password)));
+                getWifiManager().enableNetwork(netId, true);
+            }
+        });
+    }
+
+    /**
+     * 便携热点是否开启
+     */
+    public boolean isApEnable() {
+        try {
+            Method method = getWifiManager().getClass().getDeclaredMethod("isWifiApEnabled");
+            method.setAccessible(true);
+            return (boolean) method.invoke(wifiManager);
+        } catch (Throwable e) {
+            e.printStackTrace();
+        }
+        return false;
+    }
+
+    /**
+     * 关闭便携热点
+     */
+    public void closeAp(Activity activity) {
+        // 6.0+申请修改系统设置权限
+        if (Build.VERSION.SDK_INT >= M) {
+            if (!isGrantedWriteSettings(activity)) {
+                requestWriteSettings(activity);
+            }
+        }
+        // 8.0以上的关闭方式不一样
+        if (Build.VERSION.SDK_INT >= O) {
+            stopTethering();
+        } else {
+            try {
+                Method method = getWifiManager().getClass().getMethod("setWifiApEnabled", WifiConfiguration.class, boolean.class);
+                method.setAccessible(true);
+                method.invoke(getWifiManager(), null, false);
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+    }
+
+    /**
+     * 开启便携热点
+     *
+     * @param activity activity
+     * @param ssid     便携热点SSID
+     * @param password 便携热点密码
+     */
+    public void openAp(Activity activity, String ssid, String password) {
+        // 6.0+申请修改系统设置权限
+        if (Build.VERSION.SDK_INT >= M) {
+            if (!isGrantedWriteSettings(activity)) {
+                requestWriteSettings(activity);
+            }
+        }
+        // 9.0以下版本不支持热点和WiFi共存
+        if (Build.VERSION.SDK_INT <= P) {
+            // 关闭WiFi
+            if (isWifiEnable()) {
+                getWifiManager().setWifiEnabled(false);
+            }
+        }
+        // 8.0以下的开启方式不一样
+        if (Build.VERSION.SDK_INT >= O) {
+            startTethering();
+        } else {
+            try {
+                // 热点的配置类
+                WifiConfiguration config = new WifiConfiguration();
+                // 配置热点的名称(可以在名字后面加点随机数什么的)
+                config.SSID = ssid;
+                config.preSharedKey = password;
+                //是否隐藏网络
+                config.hiddenSSID = false;
+                //开放系统认证
+                config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
+                config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
+                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;
+                // 调用反射打开热点
+                Method method = getWifiManager().getClass().getMethod("setWifiApEnabled", WifiConfiguration.class, Boolean.TYPE);
+                // 返回热点打开状态
+                method.invoke(getWifiManager(), config, true);
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+    }
+
+    /**
+     * 查看授权情况, 开启热点需要申请系统设置修改权限,如有必要,可提前申请
+     */
+    @RequiresApi(api = Build.VERSION_CODES.M)
+    public void requestWriteSettings(Activity activity) {
+        if (isGrantedWriteSettings(activity)) {
+            Log.d(TAG, "已授权修改系统设置权限");
+            return;
+        }
+        Intent intent = new Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS);
+        intent.setData(Uri.parse("package:" + activity.getPackageName()));
+        activity.startActivityForResult(intent, REQUEST_WRITE_SETTING_CODE);
+    }
+
+    /**
+     * 返回应用程序是否可以修改系统设置
+     *
+     * @return {@code true}: yes
+     * {@code false}: no
+     */
+    @RequiresApi(api = Build.VERSION_CODES.M)
+    public boolean isGrantedWriteSettings(Context context) {
+        return Settings.System.canWrite(context);
+    }
+
+    /**
+     * 是否连接着指定WiFi,通过已连接的SSID判断
+     *
+     * @param ssid 是否连接着wifi
+     */
+    public boolean isConnectedTargetSsid(String ssid) {
+        return ssid.equals(getSsid());
+    }
+
+    /**
+     * 获取当前WiFi名称
+     *
+     * @return 返回不含双引号的SSID
+     */
+    public String getSsid() {
+        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.O) {
+            if (!isGrantedLocationPermission()) {
+                return "Version Android O+ get ssid need Location permission!";
+            }
+        }
+        String ssid = getWifiManager().getConnectionInfo().getSSID();
+        if (TextUtils.isEmpty(ssid)) {
+            return "";
+        }
+        if (ssid.startsWith("\"") && ssid.endsWith("\"")) {
+            return ssid.subSequence(1, ssid.length() - 1).toString();
+        }
+        return ssid;
+    }
+
+    /**
+     * @return 是否有位置权限
+     */
+    private boolean isGrantedLocationPermission() {
+        return ContextCompat.checkSelfPermission(mContext, ACCESS_COARSE_LOCATION)
+                + ContextCompat.checkSelfPermission(mContext, ACCESS_FINE_LOCATION) == 0;
+    }
+
+    /**
+     * @return 获取WiFi列表
+     */
+    public List<ScanResult> getWifiList() {
+        List<ScanResult> resultList = new ArrayList<>();
+        if (getWifiManager() != null && isWifiEnable()) {
+            resultList.addAll(getWifiManager().getScanResults());
+        }
+        return resultList;
+    }
+
+    /**
+     * 获取开启便携热点后自身热点IP地址
+     *
+     * @return ip地址
+     */
+    public String getLocalIp() {
+        DhcpInfo dhcpInfo = getWifiManager().getDhcpInfo();
+        if (dhcpInfo != null) {
+            int address = dhcpInfo.serverAddress;
+            return ((address & 0xFF)
+                    + "." + ((address >> 8) & 0xFF)
+                    + "." + ((address >> 16) & 0xFF)
+                    + "." + ((address >> 24) & 0xFF));
+        }
+        return null;
+    }
+
+    /**
+     * android8.0以上开启手机热点
+     */
+    private void startTethering() {
+        try {
+            Class classOnStartTetheringCallback = Class.forName("android.net.ConnectivityManager$OnStartTetheringCallback");
+            Method startTethering = getConnectivityManager().getClass()
+                    .getDeclaredMethod("startTethering", int.class, boolean.class, classOnStartTetheringCallback);
+            Object proxy = ProxyBuilder.forClass(classOnStartTetheringCallback)
+                    .handler(new InvocationHandler() {
+                        @Override
+                        public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
+                            return null;
+                        }
+                    }).build();
+            startTethering.invoke(getConnectivityManager(), 0, false, proxy);
+        } catch (Exception e) {
+            Log.e(TAG, "打开热点失败");
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * android8.0以上关闭手机热点
+     */
+    private void stopTethering() {
+        try {
+            Method stopTethering = getConnectivityManager()
+                    .getClass().getDeclaredMethod("stopTethering", int.class);
+            stopTethering.invoke(getConnectivityManager(), 0);
+        } catch (Exception e) {
+            Log.e(TAG, "关闭热点失败");
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * wifi设置
+     *
+     * @param ssid     WIFI名称
+     * @param pws      WIFI密码
+     * @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) {
+            getWifiManager().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
+     */
+    @SuppressLint("MissingPermission")
+    private WifiConfiguration isExist(String ssid) {
+        List<WifiConfiguration> configs = getWifiManager().getConfiguredNetworks();
+        if (configs == null) {
+            Log.e(TAG, "isExist: null");
+            return null;
+        }
+        for (WifiConfiguration config : configs) {
+            if (config.SSID.equals("\"" + ssid + "\"")) {
+                return config;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * 根据 NetworkId 获取 WifiConfiguration 信息
+     *
+     * @param networkId 需要获取 WifiConfiguration 信息的 networkId
+     * @return 指定 networkId 的 WifiConfiguration 信息
+     */
+    @SuppressLint("MissingPermission")
+    public WifiConfiguration getWifiConfigurationForNetworkId(int networkId) {
+      final List<WifiConfiguration> configs = wifiManager.getConfiguredNetworks();
+        if (configs != null) {
+            for (WifiConfiguration config : configs) {
+                if (networkId == config.networkId) {
+                    return config;
+                }
+            }
+        }
+        return null;
+    }
+
+    private static final class ConnectWiFiThread extends AtomicInteger
+            implements ThreadFactory {
+
+        private final AtomicInteger POOL_NUMBER = new AtomicInteger(1);
+
+        @Override
+        public Thread newThread(Runnable r) {
+            Thread t = new Thread(r) {
+                @Override
+                public void run() {
+                    try {
+                        super.run();
+                    } catch (Throwable e) {
+                        Log.e(TAG, "Thread run threw throwable", e);
+                    }
+                }
+            };
+            t.setName(TAG + new AtomicInteger(1)
+                    + "-pool-" + POOL_NUMBER.getAndIncrement() +
+                    "-thread-");
+            t.setDaemon(false);
+            t.setPriority(Thread.NORM_PRIORITY);
+            t.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
+                @Override
+                public void uncaughtException(Thread t, Throwable e) {
+                    Log.e(TAG, "Thread run threw uncaughtException throwable", e);
+                }
+            });
+            return t;
+        }
+    }
+
+    public boolean isRegisterWifiBroadcast() {
+        return wifiReceiver != null;
+    }
+
+    /**
+     * 注册Wifi广播
+     */
+    public void registerWifiBroadcast(WifiReceiver.WifiStateListener wifiStateListener) {
+        // 刚注册广播时会立即收到一条当前状态的广播
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
+        filter.addAction("android.net.wifi.WIFI_AP_STATE_CHANGED");
+        filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
+        filter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
+        filter.addAction("android.net.wifi.CONFIGURED_NETWORKS_CHANGE");
+        filter.addAction("android.net.wifi.LINK_CONFIGURATION_CHANGED");
+        filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
+        filter.addAction(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION);
+        wifiReceiver = new WifiReceiver();
+        mContext.registerReceiver(wifiReceiver, filter);
+        wifiReceiver.setWifiStateListener(wifiStateListener);
+    }
+
+    /**
+     * 解除Wifi广播
+     */
+    public void unregisterWifiBroadcast() {
+        if (isRegisterWifiBroadcast()) {
+            mContext.unregisterReceiver(wifiReceiver);
+            wifiReceiver.setWifiStateListener(null);
+            wifiReceiver = null;
+        }
+    }
+
+    /**
+     * 资源释放
+     */
+    public void release() {
+        mContext = null;
+        wifiManager = null;
+        connectivityManager = null;
+        wifiReceiver = null;
+        System.gc();
+    }
+}

二進制
libBase/src/main/res/drawable-xxxhdpi/ic_wifi_1.webp


二進制
libBase/src/main/res/drawable-xxxhdpi/ic_wifi_2.webp


二進制
libBase/src/main/res/drawable-xxxhdpi/ic_wifi_3.webp


二進制
libBase/src/main/res/drawable-xxxhdpi/ic_wifi_4.webp


+ 19 - 0
libBase/src/main/res/drawable/icon_wifi_signal_level.xml

@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<level-list xmlns:android="http://schemas.android.com/apk/res/android">
+    <item
+        android:drawable="@drawable/ic_wifi_1"
+        android:maxLevel="0" />
+
+    <item
+        android:drawable="@drawable/ic_wifi_2"
+        android:maxLevel="1" />
+
+    <item
+        android:drawable="@drawable/ic_wifi_3"
+        android:maxLevel="2" />
+
+    <item
+        android:drawable="@drawable/ic_wifi_4"
+        android:maxLevel="3" />
+
+</level-list>

+ 1 - 1
libDeviceSdk/build.gradle

@@ -8,7 +8,7 @@ android {
 
     defaultConfig {
         minSdk 21
-        targetSdk 30
+        targetSdk 27
 
         testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
         consumerProguardFiles "consumer-rules.pro"

+ 3 - 2
libThirdParty/build.gradle

@@ -8,7 +8,7 @@ android {
 
     defaultConfig {
         minSdk 21
-        targetSdk 30
+        targetSdk 27
 
         testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
         consumerProguardFiles "consumer-rules.pro"
@@ -68,6 +68,7 @@ dependencies {
 
     api 'androidx.room:room-common:2.3.0'
     api 'androidx.room:room-runtime:2.3.0'
-    api 'com.github.eurigo:WiFiUtils:1.1.6'
+    api 'com.github.eurigo:dexmakerhook:1.0'
+    api 'com.blankj:utilcodex:1.31.0'
 
 }