diff --git a/README.md b/README.md index d1347681..754b72a6 100644 --- a/README.md +++ b/README.md @@ -142,7 +142,7 @@ The plugin provides props for extra customization. Every time you change the pro ```javascript import WifiManager from "react-native-wifi-reborn"; -WifiManager.connectToProtectedSSID(ssid, password, isWep).then( +WifiManager.connectToProtectedSSID(ssid, password, isWep, timeout).then( () => { console.log("Connected successfully!"); }, @@ -171,7 +171,7 @@ _The api documentation is in progress._ The following methods work on both Android and iOS -### `connectToProtectedSSID(SSID: string, password: string, isWEP: boolean, isHidden: boolean): Promise` +### `connectToProtectedSSID(SSID: string, password: string, isWEP: boolean, isHidden: boolean, timeout: number): Promise` Returns a promise that resolves when connected or rejects with the error when it couldn't connect to the wifi network. @@ -197,6 +197,10 @@ Used on iOS. If true, the network is WEP Wi-Fi; otherwise it is a WPA or WPA2 pe Type: `boolean` Used on Android. If true, the network is a hidden Wi-Fi network. +#### timeout +TypeL `number` +Used to set a timeout in seconds. Default 15 seconds. + #### Errors: * iOS: * `unavailableForOSVersion`: Starting from iOS 11, NEHotspotConfigurationError is available. diff --git a/android/src/main/java/com/reactlibrary/rnwifi/RNWifiModule.java b/android/src/main/java/com/reactlibrary/rnwifi/RNWifiModule.java index b84a9148..eb6dee1d 100644 --- a/android/src/main/java/com/reactlibrary/rnwifi/RNWifiModule.java +++ b/android/src/main/java/com/reactlibrary/rnwifi/RNWifiModule.java @@ -18,6 +18,8 @@ import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; import android.net.wifi.WifiNetworkSpecifier; +import android.os.Handler; +import android.os.Looper; import android.util.Log; import android.provider.Settings; import android.os.Build; @@ -56,6 +58,8 @@ public class RNWifiModule extends ReactContextBaseJavaModule { private final ReactApplicationContext context; private static String TAG = "RNWifiModule"; + private static final int TIMEOUT_MILLIS = 15000; + RNWifiModule(ReactApplicationContext context) { super(context); @@ -217,10 +221,11 @@ public void openWifiSettings() { * @param password password of the network to connect with * @param isWep only for iOS * @param isHidden only for Android, use if WiFi is hidden + * @param timeout use to set timeout in seconds * @param promise to send success/error feedback */ @ReactMethod - public void connectToProtectedSSID(@NonNull final String SSID, @NonNull final String password, final boolean isWep, final boolean isHidden, final Promise promise) { + public void connectToProtectedSSID(@NonNull final String SSID, @NonNull final String password, final boolean isWep, final boolean isHidden, final Integer timeout, final Promise promise) { if(!assertLocationPermissionGranted(promise)) { return; } @@ -231,7 +236,8 @@ public void connectToProtectedSSID(@NonNull final String SSID, @NonNull final St } this.removeWifiNetwork(SSID, promise, () -> { - connectToWifiDirectly(SSID, password, isHidden, promise); + int secondsTimeout = timeout != null ? timeout * 1000 : TIMEOUT_MILLIS; + connectToWifiDirectly(SSID, password, isHidden, secondsTimeout, promise); }); } @@ -406,7 +412,7 @@ public void reScanAndLoadWifiList(final Promise promise) { boolean wifiStartScan = wifi.startScan(); Log.d(TAG, "wifi start scan: " + wifiStartScan); - if (wifiStartScan == true) { + if (wifiStartScan) { final WifiScanResultReceiver wifiScanResultReceiver = new WifiScanResultReceiver(wifi, promise); getReactApplicationContext().registerReceiver(wifiScanResultReceiver, new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)); } else { @@ -415,9 +421,9 @@ public void reScanAndLoadWifiList(final Promise promise) { } } - private void connectToWifiDirectly(@NonNull final String SSID, @NonNull final String password, final boolean isHidden, final Promise promise) { + private void connectToWifiDirectly(@NonNull final String SSID, @NonNull final String password, final boolean isHidden, final int timeout, final Promise promise) { if (isAndroidTenOrLater()) { - connectAndroidQ(SSID, password, isHidden, promise); + connectAndroidQ(SSID, password, isHidden,timeout, promise); } else { connectPreAndroidQ(SSID, password, promise); } @@ -454,7 +460,7 @@ private void connectPreAndroidQ(@NonNull final String SSID, @NonNull final Strin } @RequiresApi(api = Build.VERSION_CODES.Q) - private void connectAndroidQ(@NonNull final String SSID, @NonNull final String password, final boolean isHidden, final Promise promise) { + private void connectAndroidQ(@NonNull final String SSID, @NonNull final String password, final boolean isHidden, final int timeout, final Promise promise) { WifiNetworkSpecifier.Builder wifiNetworkSpecifier = new WifiNetworkSpecifier.Builder() .setIsHiddenSsid(isHidden) .setSsid(SSID); @@ -470,34 +476,39 @@ private void connectAndroidQ(@NonNull final String SSID, @NonNull final String p .build(); ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); + + final Handler timeoutHandler = new Handler(Looper.getMainLooper()); + final Runnable timeoutRunnable = () -> { + promise.reject("TimeoutError", "Connection timeout"); + DisconnectCallbackHolder.getInstance().unbindProcessFromNetwork(); + DisconnectCallbackHolder.getInstance().disconnect(); + }; - ConnectivityManager.NetworkCallback networkCallback = new - ConnectivityManager.NetworkCallback() { - @Override - public void onAvailable(Network network) { - super.onAvailable(network); - DisconnectCallbackHolder.getInstance().bindProcessToNetwork(network); - connectivityManager.setNetworkPreference(ConnectivityManager.DEFAULT_NETWORK_PREFERENCE); - if (!pollForValidSSID(3, SSID)) { - promise.reject(ConnectErrorCodes.android10ImmediatelyDroppedConnection.toString(), "Firmware bugs on OnePlus prevent it from connecting on some firmware versions."); - return; - } - promise.resolve("connected"); - } + timeoutHandler.postDelayed(timeoutRunnable, timeout); - @Override - public void onUnavailable() { - super.onUnavailable(); - promise.reject(ConnectErrorCodes.didNotFindNetwork.toString(), "Network not found or network request cannot be fulfilled."); - } + ConnectivityManager.NetworkCallback networkCallback = new ConnectivityManager.NetworkCallback() { + @Override + public void onAvailable(@NonNull Network network) { + super.onAvailable(network); + timeoutHandler.removeCallbacks(timeoutRunnable); + DisconnectCallbackHolder.getInstance().bindProcessToNetwork(network); + connectivityManager.setNetworkPreference(ConnectivityManager.DEFAULT_NETWORK_PREFERENCE); + if (!pollForValidSSID(3, SSID)) { + promise.reject(ConnectErrorCodes.android10ImmediatelyDroppedConnection.toString(), "Firmware bugs on OnePlus prevent it from connecting on some firmware versions."); + return; + } + promise.resolve("connected"); + } + + @Override + public void onUnavailable() { + super.onUnavailable(); + timeoutHandler.removeCallbacks(timeoutRunnable); + promise.reject(ConnectErrorCodes.didNotFindNetwork.toString(), "Network not found or network request cannot be fulfilled."); + + } + }; - @Override - public void onLost(@NonNull Network network) { - super.onLost(network); - DisconnectCallbackHolder.getInstance().unbindProcessFromNetwork(); - DisconnectCallbackHolder.getInstance().disconnect(); - } - }; DisconnectCallbackHolder.getInstance().addNetworkCallback(networkCallback, connectivityManager); DisconnectCallbackHolder.getInstance().requestNetwork(nr); } diff --git a/example/with-expo/components/ConnectToSSID.tsx b/example/with-expo/components/ConnectToSSID.tsx index fae629e3..1740c528 100644 --- a/example/with-expo/components/ConnectToSSID.tsx +++ b/example/with-expo/components/ConnectToSSID.tsx @@ -14,7 +14,7 @@ export const ConnectToSSID = () => { setError(''); setResponse(''); setIsLoading(true); - WifiManager.connectToProtectedSSID(ssid, pass, false, false) + WifiManager.connectToProtectedSSID(ssid, pass, false, false, 10) .then((r) => setResponse(JSON.stringify(r, null, 2))) .catch((e) => setError(e.toString())) .finally(() => setIsLoading(false)); diff --git a/lib/types/index.d.ts b/lib/types/index.d.ts index fdbc25f3..f1a66be9 100644 --- a/lib/types/index.d.ts +++ b/lib/types/index.d.ts @@ -96,12 +96,14 @@ declare module 'react-native-wifi-reborn' { * @param password `null` for open networks. * @param isWep Used on iOS. If `true`, the network is WEP Wi-Fi; otherwise it is a WPA or WPA2 personal Wi-Fi network. * @param isHidden only for Android, use if Wi-Fi is hidden. + * @param timeout only for Android, timeout in seconds. If the connection is not established in this time, it will reject. Default is 15 seconds. */ export function connectToProtectedSSID( SSID: string, password: string | null, isWEP: boolean, - isHidden: boolean + isHidden: boolean, + timeout: number | null ): Promise; export enum GET_CURRENT_WIFI_SSID_ERRRORS {