Skip to content

Commit

Permalink
feat(android): add timeout parameter
Browse files Browse the repository at this point in the history
  • Loading branch information
Alessandro Marra authored and JuanSeBestia committed Mar 26, 2024
1 parent c898178 commit 9426913
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 35 deletions.
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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!");
},
Expand Down Expand Up @@ -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.

Expand All @@ -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.
Expand Down
73 changes: 42 additions & 31 deletions android/src/main/java/com/reactlibrary/rnwifi/RNWifiModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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;
}
Expand All @@ -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);
});
}

Expand Down Expand Up @@ -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 {
Expand All @@ -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);
}
Expand Down Expand Up @@ -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);
Expand All @@ -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);
}
Expand Down
2 changes: 1 addition & 1 deletion example/with-expo/components/ConnectToSSID.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand Down
4 changes: 3 additions & 1 deletion lib/types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<void>;

export enum GET_CURRENT_WIFI_SSID_ERRRORS {
Expand Down

0 comments on commit 9426913

Please sign in to comment.