wifiutils/src/main/java/com/thanosfisherman/wifiutils/wifiConnect/WifiConnectionReceiver.java
public final class WifiConnectionReceiver extends BroadcastReceiver {
    @NonNull
    private final WifiConnectionCallback mWifiConnectionCallback;
    @Nullable
    private ScanResult mScanResult;
    @NonNull
    private final WifiManager mWifiManager;
    private String ssid;


    public WifiConnectionReceiver(@NonNull final WifiConnectionCallback callback, @NonNull final WifiManager wifiManager) {
        this.mWifiConnectionCallback = callback;
        this.mWifiManager = wifiManager;
    }

    @Override
    public void onReceive(final Context context, @NonNull final Intent intent) {
        final String action = intent.getAction();
        wifiLog("Connection Broadcast action: " + action);
        if (isAndroidQOrLater()) {
            if (Objects.equals(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION, action)) {
                final SupplicantState state = intent.getParcelableExtra(WifiManager.EXTRA_NEW_STATE);
                final int suppl_error = intent.getIntExtra(WifiManager.EXTRA_SUPPLICANT_ERROR, -1);
                wifiLog("Connection Broadcast state: " + state);
                wifiLog("suppl_error: " + suppl_error);
                if (mScanResult == null && isAlreadyConnected2(mWifiManager, ssid)) {
                    mWifiConnectionCallback.successfulConnect();
                }
                if (state == SupplicantState.DISCONNECTED && suppl_error == WifiManager.ERROR_AUTHENTICATING) {
                    mWifiConnectionCallback.errorConnect(ConnectionErrorCode.AUTHENTICATION_ERROR_OCCURRED);
                }
            }
        } else {
            if (Objects.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION, action)) {
                /*
                    Note here we don't check if has internet connectivity, because we only validate
                    if the connection to the hotspot is active, and not if the hotspot has internet.
                 */
                if (isAlreadyConnected(mWifiManager, of(mScanResult).next(scanResult -> scanResult.BSSID).get())) {

                    mWifiConnectionCallback.successfulConnect();
                }
            } else if (Objects.equals(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION, action)) {
                final SupplicantState state = intent.getParcelableExtra(WifiManager.EXTRA_NEW_STATE);
                final int supl_error = intent.getIntExtra(WifiManager.EXTRA_SUPPLICANT_ERROR, -1);

                if (state == null) {
                    mWifiConnectionCallback.errorConnect(ConnectionErrorCode.COULD_NOT_CONNECT);
                    return;
                }

                wifiLog("Connection Broadcast state: " + state);

                switch (state) {
                    case COMPLETED:
                    case FOUR_WAY_HANDSHAKE:
                        if (mScanResult == null && isAlreadyConnected2(mWifiManager, ssid)) {
                            mWifiConnectionCallback.successfulConnect();
                        } else if (isAlreadyConnected(mWifiManager, of(mScanResult).next(scanResult -> scanResult.BSSID).get())) {
                            mWifiConnectionCallback.successfulConnect();
                        }
                        break;
                    case DISCONNECTED:
                        if (supl_error == WifiManager.ERROR_AUTHENTICATING) {
                            wifiLog("Authentication error...");
                            mWifiConnectionCallback.errorConnect(ConnectionErrorCode.AUTHENTICATION_ERROR_OCCURRED);
                        } else {
                            wifiLog("Disconnected. Re-attempting to connect...");
                            reEnableNetworkIfPossible(mWifiManager, mScanResult);
                        }
                }
            }
        }
    }

    public static boolean isAlreadyConnected2(@Nullable WifiManager wifiManager, @Nullable String ssid) {
        if (ssid != null && wifiManager != null) {
            if (wifiManager.getConnectionInfo() != null && wifiManager.getConnectionInfo().getSSID() != null &&
                    wifiManager.getConnectionInfo().getIpAddress() != 0 &&
                    Objects.equals(ssid, wifiManager.getConnectionInfo().getSSID())) {
                wifiLog("Already connected to: " + wifiManager.getConnectionInfo().getSSID() + "  BSSID: " + wifiManager.getConnectionInfo().getBSSID());
                return true;
            }
        }
        return false;
    }

    @NonNull
    public WifiConnectionReceiver connectWith(@NonNull ScanResult result, @NonNull String password, @NonNull ConnectivityManager connectivityManager) {
        mScanResult = result;

        return this;
    }

    @NonNull
    public WifiConnectionReceiver connectWith(@NonNull String ssid, @NonNull String password, @NonNull ConnectivityManager connectivityManager) {
        this.ssid = ssid;

        return this;
    }
}
wifiutils/src/main/java/com/thanosfisherman/wifiutils/wifiRemove/RemoveSuccessListener.java
public interface RemoveSuccessListener {
    void success();

    void failed(@NonNull RemoveErrorCode errorCode);
}
wifiutils/src/main/java/com/thanosfisherman/wifiutils/wifiConnect/ConnectionSuccessListener.java
public interface ConnectionSuccessListener {
    void success();

    void failed(@NonNull ConnectionErrorCode errorCode);
}
wifiutils/src/main/java/com/thanosfisherman/wifiutils/wifiScan/WifiScanCallback.java
public interface WifiScanCallback {
    void onScanResultsReady();
}
wifiutils/src/main/java/com/thanosfisherman/wifiutils/ConnectorUtils.java
@RequiresPermission(allOf = {ACCESS_FINE_LOCATION, ACCESS_WIFI_STATE})
static boolean connectToWifi(@NonNull final Context context, @Nullable final WifiManager wifiManager, @Nullable final ConnectivityManager connectivityManager, @NonNull WeakHandler handler, @NonNull final ScanResult scanResult, @NonNull final String password, @NonNull WifiConnectionCallback wifiConnectionCallback, boolean patternMatch, @Nullable String ssid) {
    if (wifiManager == null || connectivityManager == null) {
        return false;
    }

    if (isAndroidQOrLater()) {
        return connectAndroidQ(wifiManager, connectivityManager, handler, wifiConnectionCallback, scanResult, password, patternMatch, ssid);
    }

    return connectPreAndroidQ(context, wifiManager, scanResult, password);
}
wifiutils/src/main/java/com/thanosfisherman/wifiutils/wifiDisconnect/DisconnectionSuccessListener.java
public interface DisconnectionSuccessListener {
    void success();

    void failed(@NonNull DisconnectionErrorCode errorCode);
}
wifiutils/src/main/java/com/thanosfisherman/wifiutils/wifiConnect/WifiConnectionCallback.java
public interface WifiConnectionCallback {
    void successfulConnect();

    void errorConnect(@NonNull ConnectionErrorCode connectionErrorCode);
}
wifiutils/src/main/java/com/thanosfisherman/wifiutils/wifiConnect/ConnectionScanResultsListener.java
public interface ConnectionScanResultsListener {
    @Nullable
    ScanResult onConnectWithScanResult(@NonNull List<ScanResult> scanResults);
}
wifiutils/src/main/java/com/thanosfisherman/wifiutils/ConnectorUtils.java
@RequiresPermission(ACCESS_WIFI_STATE)
static boolean removeWifi(@NonNull final WifiManager wifiManager, @NonNull final String ssid) {
    final WifiConfiguration wifiConfiguration = ConfigSecurities.getWifiConfiguration(wifiManager, ssid);
    return cleanPreviousConfiguration(wifiManager, wifiConfiguration);
}
wifiutils/src/main/java/com/thanosfisherman/wifiutils/wifiConnect/TimeoutHandler.java
public class TimeoutHandler {
    private final WifiManager mWifiManager;
    private final WeakHandler mHandler;
    private final WifiConnectionCallback mWifiConnectionCallback;
    private ScanResult mScanResult;

    private final Runnable timeoutCallback = new Runnable() {
        @Override
        public void run() {
            wifiLog("Connection Timed out...");

            if (!isAndroidQOrLater()) {
                reEnableNetworkIfPossible(mWifiManager, mScanResult);
            }
            if (isAlreadyConnected(mWifiManager, of(mScanResult).next(scanResult -> scanResult.BSSID).get())) {
                mWifiConnectionCallback.successfulConnect();
            } else {
                mWifiConnectionCallback.errorConnect(ConnectionErrorCode.TIMEOUT_OCCURRED);
            }

            mHandler.removeCallbacks(this);
        }
    };

    public TimeoutHandler(@NonNull WifiManager wifiManager, @NonNull WeakHandler handler, @NonNull final WifiConnectionCallback wifiConnectionCallback) {
        this.mWifiManager = wifiManager;
        this.mHandler = handler;
        this.mWifiConnectionCallback = wifiConnectionCallback;
    }

    public void startTimeout(final ScanResult scanResult, final long timeout) {
        // cleanup previous connection timeout handler
        mHandler.removeCallbacks(timeoutCallback);

        mScanResult = scanResult;
        mHandler.postDelayed(timeoutCallback, timeout);
    }

    public void stopTimeout() {
        mHandler.removeCallbacks(timeoutCallback);
    }
}
wifiutils/src/main/java/com/thanosfisherman/wifiutils/wifiWps/ConnectionWpsListener.java
public interface ConnectionWpsListener {
    void isSuccessful(boolean isSuccess);
}
wifiutils/src/main/java/com/thanosfisherman/wifiutils/wifiDisconnect/DisconnectionErrorCode.java
public enum DisconnectionErrorCode {
    COULD_NOT_GET_WIFI_MANAGER,
    COULD_NOT_GET_CONNECTIVITY_MANAGER,
    COULD_NOT_DISCONNECT,
}
wifiutils/src/main/java/com/thanosfisherman/wifiutils/ConnectorUtils.java
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@RequiresPermission(allOf = {ACCESS_FINE_LOCATION, ACCESS_WIFI_STATE})
static void connectWps(@Nullable final WifiManager wifiManager, @NonNull WeakHandler handler, @NonNull final ScanResult scanResult, @NonNull String pin, long timeOutMillis,
                       @NonNull final ConnectionWpsListener connectionWpsListener) {
    if (wifiManager == null) {
        connectionWpsListener.isSuccessful(false);
        return;
    }

    final WpsInfo wpsInfo = new WpsInfo();
    final Runnable handlerTimeoutRunnable = new Runnable() {
        @Override
        public void run() {
            wifiManager.cancelWps(null);
            wifiLog("Connection with WPS has timed out");
            cleanPreviousConfiguration(wifiManager, scanResult);
            connectionWpsListener.isSuccessful(false);
            handler.removeCallbacks(this);
        }
    };

    final WifiManager.WpsCallback wpsCallback = new WifiManager.WpsCallback() {
        @Override
        public void onStarted(String pin) {
        }

        @Override
        public void onSucceeded() {
            handler.removeCallbacks(handlerTimeoutRunnable);
            wifiLog("CONNECTED With WPS successfully");
            connectionWpsListener.isSuccessful(true);
        }

        @Override
        public void onFailed(int reason) {
            handler.removeCallbacks(handlerTimeoutRunnable);
            final String reasonStr;
            switch (reason) {
                case 3:
                    reasonStr = "WPS_OVERLAP_ERROR";
                    break;
                case 4:
                    reasonStr = "WPS_WEP_PROHIBITED";
                    break;
                case 5:
                    reasonStr = "WPS_TKIP_ONLY_PROHIBITED";
                    break;
                case 6:
                    reasonStr = "WPS_AUTH_FAILURE";
                    break;
                case 7:
                    reasonStr = "WPS_TIMED_OUT";
                    break;
                default:
                    reasonStr = String.valueOf(reason);
            }
            wifiLog("FAILED to connect with WPS. Reason: " + reasonStr);
            cleanPreviousConfiguration(wifiManager, scanResult);
            reenableAllHotspots(wifiManager);
            connectionWpsListener.isSuccessful(false);
        }
    };

    wifiLog("Connecting with WPS...");
    wpsInfo.setup = WpsInfo.KEYPAD;
    wpsInfo.BSSID = scanResult.BSSID;
    wpsInfo.pin = pin;
    wifiManager.cancelWps(null);

    if (!cleanPreviousConfiguration(wifiManager, scanResult)) {
        disableAllButOne(wifiManager, scanResult);
    }

    handler.postDelayed(handlerTimeoutRunnable, timeOutMillis);
    wifiManager.startWps(wpsInfo, wpsCallback);
}
wifiutils/src/main/java/com/thanosfisherman/wifiutils/ConnectorUtils.java
static void reenableAllHotspots(@Nullable WifiManager wifi) {
    if (wifi == null) {
        return;
    }
    final List<WifiConfiguration> configurations = wifi.getConfiguredNetworks();
    if (configurations != null && !configurations.isEmpty()) {
        for (final WifiConfiguration config : configurations) {
            wifi.enableNetwork(config.networkId, false);
        }
    }
}
wifiutils/src/main/java/com/thanosfisherman/wifiutils/wifiConnect/DisconnectCallbackHolder.java
@RequiresApi(Build.VERSION_CODES.Q)
public class DisconnectCallbackHolder {
    @Nullable
    private static volatile DisconnectCallbackHolder sInstance;
    @Nullable
    private ConnectivityManager.NetworkCallback mNetworkCallback;
    @Nullable
    private ConnectivityManager mConnectivityManager;

    private boolean isNetworkcallbackAdded;

    private boolean isProcessBoundToNetwork;

    private DisconnectCallbackHolder() {
    }

    /**
     * Gets a Singleton instance of DisconnectCallbackHolder.
     * This is a Lazy and Thread safe Singleton with Double-check locking
     *
     * @return DisconnectCallbackHolder Singleton instance
     */
    public static DisconnectCallbackHolder getInstance() {
        if (sInstance == null) {
            synchronized (DisconnectCallbackHolder.class) {
                if (sInstance == null) {
                    sInstance = new DisconnectCallbackHolder();
                }
            }
        }
        return sInstance;
    }

    /**
     * Keeps a reference of {@link ConnectivityManager} and {@link ConnectivityManager.NetworkCallback}
     * This method must be called before anything else.
     *
     * @param networkCallback     the networkcallback class to keep a reference of
     * @param connectivityManager the ConnectivityManager
     */
    public void addNetworkCallback(@NonNull ConnectivityManager.NetworkCallback networkCallback, @NonNull ConnectivityManager connectivityManager) {
        mNetworkCallback = networkCallback;
        mConnectivityManager = connectivityManager;
        isNetworkcallbackAdded = true;
    }

    /**
     * Disconnects from Network and nullifies networkcallback meaning you will have to
     * call {@link DisconnectCallbackHolder#addNetworkCallback(ConnectivityManager.NetworkCallback, ConnectivityManager)} again
     * next time you want to connect again.
     */
    public void disconnect() {
        if (mNetworkCallback != null && mConnectivityManager != null) {
            wifiLog("Disconnecting on Android 10+");
            mConnectivityManager.unregisterNetworkCallback(mNetworkCallback);
            mNetworkCallback = null;
            isNetworkcallbackAdded = false;
        }
    }

    /**
     * See {@link ConnectivityManager#requestNetwork(NetworkRequest, ConnectivityManager.NetworkCallback) }
     *
     * @param networkRequest {@link NetworkRequest}
     */
    public void requestNetwork(NetworkRequest networkRequest) {
        if (mNetworkCallback != null && mConnectivityManager != null) {
            mConnectivityManager.requestNetwork(networkRequest, mNetworkCallback);
        } else {
            wifiLog("NetworkCallback has not been added yet. Please call addNetworkCallback method first");
        }
    }

    /**
     * Unbinds the previously bound Network from the process.
     */
    public void unbindProcessFromNetwork() {
        if (mConnectivityManager != null) {
            mConnectivityManager.bindProcessToNetwork(null);
            isProcessBoundToNetwork = false;
        } else {
            wifiLog("ConnectivityManager is null. Did you call addNetworkCallback method first?");
        }
    }


    /**
     * binds so all api calls performed over this new network
     * if we don't bind, connection with the wifi network is immediately dropped
     */
    public void bindProcessToNetwork(@NonNull Network network) {

        if (mConnectivityManager != null) {
            mConnectivityManager.bindProcessToNetwork(network);
            isProcessBoundToNetwork = true;
        } else {
            wifiLog("ConnectivityManager is null. Did you call addNetworkCallback method first?");
        }
    }

    /**
     * Checks whether {@link DisconnectCallbackHolder#addNetworkCallback(ConnectivityManager.NetworkCallback, ConnectivityManager)}
     * is called
     *
     * @return true if networkcallback is initialized false otherwise.
     */
    public boolean isNetworkcallbackAdded() {
        return isNetworkcallbackAdded;
    }

    /**
     * Checks whether {@link DisconnectCallbackHolder#bindProcessToNetwork(Network)}
     * is called
     *
     * @return true if bound false otherwise.
     */
    public boolean isProcessBoundToNetwork() {
        return isProcessBoundToNetwork;
    }
}
wifiutils/src/main/java/com/thanosfisherman/wifiutils/utils/VersionUtils.java
public static boolean isAndroidQOrLater() {
    return Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q;
}
wifiutils/src/main/java/com/thanosfisherman/wifiutils/ConnectorUtils.java
@RequiresPermission(ACCESS_WIFI_STATE)
static boolean disconnectFromWifi(@NonNull final WifiManager wifiManager) {
    return wifiManager.disconnect();
}
wifiutils/src/main/java/com/thanosfisherman/wifiutils/ConnectorUtils.java
static void registerReceiver(@NonNull final Context context, @Nullable final BroadcastReceiver receiver, @NonNull final IntentFilter filter) {
    if (receiver != null) {
        try {
            context.registerReceiver(receiver, filter);
        } catch (Exception ignored) {
            ignored.printStackTrace();
        }
    }
}
wifiutils/src/main/java/com/thanosfisherman/wifiutils/ConnectorUtils.java
@RequiresPermission(allOf = {ACCESS_FINE_LOCATION, ACCESS_WIFI_STATE})
static boolean cleanPreviousConfiguration(@Nullable final WifiManager wifiManager, @NonNull final ScanResult scanResult) {
    if (wifiManager == null) {
        return false;
    }
    //On Android 6.0 (API level 23) and above if my app did not create the configuration in the first place, it can not remove it either.
    final WifiConfiguration config = ConfigSecurities.getWifiConfiguration(wifiManager, scanResult);
    wifiLog("Attempting to remove previous network config...");
    if (config == null) {
        return true;
    }

    if (wifiManager.removeNetwork(config.networkId)) {
        wifiManager.saveConfiguration();
        return true;
    }
    return false;
}
wifiutils/src/main/java/com/thanosfisherman/wifiutils/wifiState/WifiStateReceiver.java
public final class WifiStateReceiver extends BroadcastReceiver {

    @NonNull
    private final WifiStateCallback wifiStateCallback;

    public WifiStateReceiver(@NonNull WifiStateCallback callbacks) {
        wifiStateCallback = callbacks;
    }

    @Override
    public void onReceive(Context context, @NonNull Intent intent) {
        int wifiState = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, 0);

        switch (wifiState) {
            case WifiManager.WIFI_STATE_ENABLED:
                wifiStateCallback.onWifiEnabled();
                break;
            case WifiManager.WIFI_STATE_ENABLING:
                break;
            case WifiManager.WIFI_STATE_DISABLING:
                break;
            case WifiManager.WIFI_STATE_DISABLED:
                break;
        }
    }
}
wifiutils/src/main/java/com/thanosfisherman/wifiutils/utils/VersionUtils.java
public static boolean isLollipopOrLater() {
    return Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP;
}
wifiutils/src/main/java/com/thanosfisherman/wifiutils/wifiScan/ScanResultsListener.java
public interface ScanResultsListener {
    void onScanResults(@NonNull List<ScanResult> scanResults);
}
wifiutils/src/main/java/com/thanosfisherman/wifiutils/wifiRemove/RemoveErrorCode.java
public enum RemoveErrorCode {
    COULD_NOT_GET_WIFI_MANAGER,
    COULD_NOT_GET_CONNECTIVITY_MANAGER,
    COULD_NOT_REMOVE,
}
wifiutils/src/main/java/com/thanosfisherman/wifiutils/ConnectorUtils.java
    @RequiresPermission(allOf = {ACCESS_FINE_LOCATION, ACCESS_WIFI_STATE})
    static boolean connectToWifiHidden(@NonNull final Context context,
                                       @Nullable final WifiManager wifiManager,
                                       @Nullable final ConnectivityManager connectivityManager,
                                       @NonNull WeakHandler handler,
//                                       @NonNull final ScanResult scanResult,
                                       @NonNull final String ssid,
                                       @Nullable final String type,
                                       @NonNull final String password,
                                       @NonNull WifiConnectionCallback wifiConnectionCallback) {
        if (wifiManager == null || connectivityManager == null || type == null) {
            return false;
        }

        if (isAndroidQOrLater()) {
            return connectAndroidQHidden(wifiManager, connectivityManager, handler, wifiConnectionCallback, ssid, type, password);
        }

        return connectPreAndroidQHidden(context, wifiManager, ssid, type, password);
    }
wifiutils/src/main/java/com/thanosfisherman/wifiutils/ConnectorUtils.java
@Nullable
static ScanResult matchScanResult(@NonNull String ssid, @NonNull String bssid, @NonNull Iterable<ScanResult> results) {
    for (ScanResult result : results) {
        if (Objects.equals(result.SSID, ssid) && Objects.equals(result.BSSID, bssid)) {
            return result;
        }
    }
    return null;
}
wifiutils/src/main/java/com/thanosfisherman/wifiutils/wifiConnect/ConnectionErrorCode.java
public enum ConnectionErrorCode {
    /**
     * Starting Android 10, apps are no longer allowed to enable wifi.
     * User has to manually do this.
     */
    COULD_NOT_ENABLE_WIFI,
    /**
     * Starting Android 9, it's only allowed to scan 4 times per 2 minuts in a foreground app.
     * https://developer.android.com/guide/topics/connectivity/wifi-scan
     */
    COULD_NOT_SCAN,
    /**
     * If the wifi network is not in range, the security type is unknown and WifiUtils doesn't support
     * connecting to the network.
     */
    DID_NOT_FIND_NETWORK_BY_SCANNING,
    /**
     * Authentication error occurred while trying to connect.
     * The password could be incorrect or the user could have a saved network configuration with a
     * different password!
     */
    AUTHENTICATION_ERROR_OCCURRED,
    /**
     * Could not connect in the timeout window.
     */
    TIMEOUT_OCCURRED,
    /**
     * Firmware bugs on OnePlus prevent it from connecting on some firmware versions.
     * More info: https://github.com/ThanosFisherman/WifiUtils/issues/63
     */
    ANDROID_10_IMMEDIATELY_DROPPED_CONNECTION,
    /**
     * Starting Android 10, the user has to confirm connecting, but can also cancel.
     */
    USER_CANCELLED,
    COULD_NOT_CONNECT,
}
wifiutils/src/main/java/com/thanosfisherman/wifiutils/utils/Elvis.java
public static <T> Elvis<T> of(T t) {
    return new Elvis<>(t);
}
wifiutils/src/main/java/com/thanosfisherman/wifiutils/wifiState/WifiStateCallback.java
public interface WifiStateCallback {
    void onWifiEnabled();
}
wifiutils/src/main/java/com/thanosfisherman/wifiutils/ConnectorUtils.java
@Nullable
static ScanResult matchScanResultBssid(@NonNull String bssid, @NonNull Iterable<ScanResult> results) {
    for (ScanResult result : results) {
        if (Objects.equals(result.BSSID, bssid)) {
            return result;
        }
    }
    return null;
}
wifiutils/src/main/java/com/thanosfisherman/wifiutils/ConnectorUtils.java
@Nullable
static ScanResult matchScanResultSsid(@NonNull String ssid, @NonNull Iterable<ScanResult> results, boolean mPatternMatch) {
    for (ScanResult result : results) {
        if (mPatternMatch ? result.SSID.startsWith(ssid) : Objects.equals(result.SSID, ssid)) {
            return result;
        }
    }
    return null;
}
wifiutils/src/main/java/com/thanosfisherman/wifiutils/wifiScan/WifiScanReceiver.java
public class WifiScanReceiver extends BroadcastReceiver {
    @NonNull
    private final WifiScanCallback callback;

    public WifiScanReceiver(@NonNull WifiScanCallback callback) {
        this.callback = callback;
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        callback.onScanResultsReady();
    }
}
wifiutils/src/main/java/com/thanosfisherman/wifiutils/wifiState/WifiStateListener.java
public interface WifiStateListener {
    void isSuccess(boolean isSuccess);
}
wifiutils/src/main/java/com/thanosfisherman/wifiutils/ConnectorUtils.java
static void unregisterReceiver(@NonNull final Context context, @Nullable final BroadcastReceiver receiver) {
    if (receiver != null) {
        try {
            context.unregisterReceiver(receiver);
        } catch (IllegalArgumentException ignored) {
        }
    }
}


Question: import android.annotation.SuppressLint;
import android.content.Context;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiManager;
import android.os.Build;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import com.thanosfisherman.wifiutils.wifiConnect.ConnectionErrorCode;
import com.thanosfisherman.wifiutils.wifiConnect.ConnectionScanResultsListener;
import com.thanosfisherman.wifiutils.wifiConnect.ConnectionSuccessListener;
import com.thanosfisherman.wifiutils.wifiConnect.DisconnectCallbackHolder;
import com.thanosfisherman.wifiutils.wifiConnect.TimeoutHandler;
import com.thanosfisherman.wifiutils.wifiConnect.WifiConnectionCallback;
import com.thanosfisherman.wifiutils.wifiConnect.WifiConnectionReceiver;
import com.thanosfisherman.wifiutils.wifiDisconnect.DisconnectionErrorCode;
import com.thanosfisherman.wifiutils.wifiDisconnect.DisconnectionSuccessListener;
import com.thanosfisherman.wifiutils.wifiRemove.RemoveErrorCode;
import com.thanosfisherman.wifiutils.wifiRemove.RemoveSuccessListener;
import com.thanosfisherman.wifiutils.wifiScan.ScanResultsListener;
import com.thanosfisherman.wifiutils.wifiScan.WifiScanCallback;
import com.thanosfisherman.wifiutils.wifiScan.WifiScanReceiver;
import com.thanosfisherman.wifiutils.wifiState.WifiStateCallback;
import com.thanosfisherman.wifiutils.wifiState.WifiStateListener;
import com.thanosfisherman.wifiutils.wifiState.WifiStateReceiver;
import com.thanosfisherman.wifiutils.wifiWps.ConnectionWpsListener;
import java.util.ArrayList;
import java.util.List;
import static com.thanosfisherman.wifiutils.utils.Elvis.of;
import static com.thanosfisherman.wifiutils.ConnectorUtils.cleanPreviousConfiguration;
import static com.thanosfisherman.wifiutils.ConnectorUtils.connectToWifi;
import static com.thanosfisherman.wifiutils.ConnectorUtils.connectToWifiHidden;
import static com.thanosfisherman.wifiutils.ConnectorUtils.connectWps;
import static com.thanosfisherman.wifiutils.ConnectorUtils.disconnectFromWifi;
import static com.thanosfisherman.wifiutils.ConnectorUtils.matchScanResult;
import static com.thanosfisherman.wifiutils.ConnectorUtils.matchScanResultBssid;
import static com.thanosfisherman.wifiutils.ConnectorUtils.matchScanResultSsid;
import static com.thanosfisherman.wifiutils.ConnectorUtils.reenableAllHotspots;
import static com.thanosfisherman.wifiutils.ConnectorUtils.registerReceiver;
import static com.thanosfisherman.wifiutils.ConnectorUtils.removeWifi;
import static com.thanosfisherman.wifiutils.ConnectorUtils.unregisterReceiver;
import static com.thanosfisherman.wifiutils.utils.VersionUtils.isAndroidQOrLater;
import static com.thanosfisherman.wifiutils.utils.VersionUtils.isLollipopOrLater;
    private final WifiScanReceiver mWifiScanReceiver;
    @Nullable
    private String mSsid;
    @Nullable
    private String type;
    @Nullable
    private String mBssid;
    @Nullable
    private String mPassword;
    @Nullable
    private ScanResult mSingleScanResult;
    @Nullable
    private ScanResultsListener mScanResultsListener;
    @Nullable
    private ConnectionScanResultsListener mConnectionScanResultsListener;
    @Nullable
    private ConnectionSuccessListener mConnectionSuccessListener;
    @Nullable
    private WifiStateListener mWifiStateListener;
    @Nullable
    private ConnectionWpsListener mConnectionWpsListener;
    @Nullable
    private boolean mPatternMatch;

    @NonNull
    private final WifiStateCallback mWifiStateCallback = new WifiStateCallback() {
        @Override
        public void onWifiEnabled() {
            wifiLog("WIFI ENABLED...");
            unregisterReceiver(mContext, mWifiStateReceiver);
            of(mWifiStateListener).ifPresent(stateListener -> stateListener.isSuccess(true));

            if (mScanResultsListener != null || mPassword != null) {
                wifiLog("START SCANNING....");
                if (mWifiManager.startScan()) {
                    registerReceiver(mContext, mWifiScanReceiver, new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
                } else {
                    of(mScanResultsListener).ifPresent(resultsListener -> resultsListener.onScanResults(new ArrayList<>()));
                    of(mConnectionWpsListener).ifPresent(wpsListener -> wpsListener.isSuccessful(false));
                    mWifiConnectionCallback.errorConnect(ConnectionErrorCode.COULD_NOT_SCAN);
                    wifiLog("ERROR COULDN'T SCAN");
                }
            }
        }
    };

    @NonNull
    private final WifiScanCallback mWifiScanResultsCallback = new WifiScanCallback() {
        @Override
        public void onScanResultsReady() {
            wifiLog("GOT SCAN RESULTS");
            unregisterReceiver(mContext, mWifiScanReceiver);

            final List<ScanResult> scanResultList = mWifiManager.getScanResults();
            of(mScanResultsListener).ifPresent(resultsListener -> resultsListener.onScanResults(scanResultList));
            of(mConnectionScanResultsListener).ifPresent(connectionResultsListener -> mSingleScanResult = connectionResultsListener.onConnectWithScanResult(scanResultList));

            if (mConnectionWpsListener != null && mBssid != null && mPassword != null) {
                mSingleScanResult = matchScanResultBssid(mBssid, scanResultList);
                if (mSingleScanResult != null && isLollipopOrLater()) {
                    connectWps(mWifiManager, mHandler, mSingleScanResult, mPassword, mWpsTimeoutMillis, mConnectionWpsListener);
                } else {
                    if (mSingleScanResult == null) {
                        wifiLog("Couldn't find network. Possibly out of range");
                    }
                    mConnectionWpsListener.isSuccessful(false);
                }
                return;
            }

            if (mSsid != null) {
                if (mBssid != null) {
                    mSingleScanResult = matchScanResult(mSsid, mBssid, scanResultList);
                } else {
                    mSingleScanResult = matchScanResultSsid(mSsid, scanResultList, mPatternMatch);
                }
            }
            if (mSingleScanResult != null && mPassword != null) {
                if (connectToWifi(mContext, mWifiManager, mConnectivityManager, mHandler, mSingleScanResult, mPassword, mWifiConnectionCallback, mPatternMatch, mSsid)) {
                    registerReceiver(mContext, (mWifiConnectionReceiver).connectWith(mSingleScanResult, mPassword, mConnectivityManager),
                            new IntentFilter(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION));
                    registerReceiver(mContext, mWifiConnectionReceiver,
                            new IntentFilter(WifiManager.NETWORK_STATE_CHANGED_ACTION));
                    mTimeoutHandler.startTimeout(mSingleScanResult, mTimeoutMillis);
                } else {
                    mWifiConnectionCallback.errorConnect(ConnectionErrorCode.COULD_NOT_CONNECT);
                }
            } else {
                if (connectToWifiHidden(mContext, mWifiManager, mConnectivityManager, mHandler, mSsid, type, mPassword, mWifiConnectionCallback)) {
                    registerReceiver(mContext, (mWifiConnectionReceiver).connectWith(mSsid, mPassword, mConnectivityManager),
                            new IntentFilter(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION));
                    registerReceiver(mContext, mWifiConnectionReceiver,
                            new IntentFilter(WifiManager.NETWORK_STATE_CHANGED_ACTION));
                    mTimeoutHandler.startTimeout(mSingleScanResult, mTimeoutMillis);
                } else {
                    mWifiConnectionCallback.errorConnect(ConnectionErrorCode.COULD_NOT_CONNECT);
                }
            }
        }
    };

    @NonNull
    private final WifiConnectionCallback mWifiConnectionCallback = new WifiConnectionCallback() {
        @Override
        public void successfulConnect() {
            wifiLog("CONNECTED SUCCESSFULLY");
            unregisterReceiver(mContext, mWifiConnectionReceiver);
            mTimeoutHandler.stopTimeout();

            //reenableAllHotspots(mWifiManager);
            of(mConnectionSuccessListener).ifPresent(ConnectionSuccessListener::success);
        }

        @Override
        public void errorConnect(@NonNull ConnectionErrorCode connectionErrorCode) {
            unregisterReceiver(mContext, mWifiConnectionReceiver);
            mTimeoutHandler.stopTimeout();
            if (isAndroidQOrLater()) {
                DisconnectCallbackHolder.getInstance().disconnect();
            }
Answer:             reenableAllHotspots(mWifiManager);