Skip to content

Commit

Permalink
feat(forceWifiUsage): remove need of the WRITE_SETTINGS. Api calls to…
Browse files Browse the repository at this point in the history
… a wifi network without internet access can perfectly be done without
  • Loading branch information
Elias Lecomte committed Mar 19, 2020
1 parent 0b9349f commit 7c9daef
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 76 deletions.
23 changes: 8 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -289,18 +289,11 @@ Called when the network status is resolved. It contains a boolean argument

### `isRemoveWifiNetwork`

### forceWifiUsage(useWifi: bool)

Method to force wifi usage if the user needs to send requests via wifi if it does not have internet connection.

If you want to use it, you need to add the `android.permission.WRITE_SETTINGS` permission to your AndroidManifest.xml.

```xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android">

<uses-permission android:name="android.permission.WRITE_SETTINGS" />

</manifest>

```
<details>
<summary>forceWifiUsage(useWifi: boolean): Promise</summary>

Use this to execute api calls to a wifi network that does not have internet access.
Useful for commissioning IoT devices.
This will route all app network requests to the network (instead of the mobile connection).
It is important to disable it again after using as even when the app disconnects from the wifi network it will keep on routing everything to wifi.
</details>
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.reactlibrary.rnwifi;

public enum ForceWifiUsageErrorCodes {
couldNotGetConnectivityManager,
}
88 changes: 34 additions & 54 deletions android/src/main/java/com/reactlibrary/rnwifi/RNWifiModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,11 @@
import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
import android.net.NetworkRequest;
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 androidx.annotation.NonNull;

Expand Down Expand Up @@ -88,71 +86,53 @@ public void loadWifiList(Callback successCallback, Callback errorCallback) {
}

/**
* Method to force wifi usage if the user needs to send requests via wifi
* if it does not have internet connection. Useful for IoT applications, when
* the app needs to communicate and send requests to a device that have no
* internet connection via wifi.
* <p>
* Receives a boolean to enable forceWifiUsage if true, and disable if false.
* Is important to enable only when communicating with the device via wifi
* and remember to disable it when disconnecting from device.
* Use this to execute api calls to a wifi network that does not have internet access.
*
* @param useWifi
* Useful for commissioning IoT devices.
*
* This will route all app network requests to the network (instead of the mobile connection).
* It is important to disable it again after using as even when the app disconnects from the wifi
* network it will keep on routing everything to wifi.
*
* @param useWifi boolean to force wifi off or on
*/
@ReactMethod
public void forceWifiUsage(boolean useWifi) {
boolean canWriteFlag = false;

if (useWifi) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
public void forceWifiUsage(final boolean useWifi, final Promise promise) {
final ConnectivityManager connectivityManager = (ConnectivityManager) context
.getSystemService(Context.CONNECTIVITY_SERVICE);

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
canWriteFlag = Settings.System.canWrite(context);

if (!canWriteFlag) {
Intent intent = new Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS);
intent.setData(Uri.parse("package:" + context.getPackageName()));
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
if (connectivityManager == null) {
promise.reject(ForceWifiUsageErrorCodes.couldNotGetConnectivityManager.toString(), "Failed to get the ConnectivityManager.");
return;
}

context.startActivity(intent);
if (useWifi) {
NetworkRequest networkRequest = new NetworkRequest.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
.build();
connectivityManager.requestNetwork(networkRequest, new ConnectivityManager.NetworkCallback() {
@Override
public void onAvailable(@NonNull final Network network) {
super.onAvailable(network);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
connectivityManager.bindProcessToNetwork(network);
} else {
ConnectivityManager.setProcessDefaultNetwork(network);
}
}

connectivityManager.unregisterNetworkCallback(this);

if (((Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) && canWriteFlag) || ((Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) && !(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M))) {
final ConnectivityManager manager = (ConnectivityManager) context
.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkRequest.Builder builder;
builder = new NetworkRequest.Builder();
//set the transport type to WIFI
builder.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);


manager.requestNetwork(builder.build(), new ConnectivityManager.NetworkCallback() {
@Override
public void onAvailable(@NonNull final Network network) {
// FIXME: should this be try catch?
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
manager.bindProcessToNetwork(network);
} else {
//This method was deprecated in API level 23
ConnectivityManager.setProcessDefaultNetwork(network);
}
manager.unregisterNetworkCallback(this);
}
});
promise.resolve(null);
}


}
});
} else {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
ConnectivityManager manager = (ConnectivityManager) context
.getSystemService(Context.CONNECTIVITY_SERVICE);
manager.bindProcessToNetwork(null);
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
connectivityManager.bindProcessToNetwork(null);
} else {
ConnectivityManager.setProcessDefaultNetwork(null);
}

promise.resolve(null);
}
}

Expand Down
25 changes: 18 additions & 7 deletions lib/types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,15 +81,26 @@ declare module 'react-native-wifi-reborn' {
export function connectionStatus(callback: (isConnected: boolean) => void): void;
export function disconnect(): void;
export function isRemoveWifiNetwork(SSID: string): Promise<void>;

export enum FORCE_WIFI_USAGE_ERRORS {
couldNotGetConnectivityManager = 'couldNotGetConnectivityManager',
}

interface ForceWifiUsageError extends Error {
code?: FORCE_WIFI_USAGE_ERRORS;
}

/**
* Force wifi usage if the user needs to send requests via WiFi
* if it does not have internet connection. Useful for IoT applications, when
* the app needs to communicate and send requests to a device that have no
* internet connection via WiFi.
* Use this to execute api calls to a wifi network that does not have internet access.
*
* Useful for commissioning IoT devices.
*
* This will route all app network requests to the network (instead of the mobile connection).
* It is important to disable it again after using as even when the app disconnects from the wifi
* network it will keep on routing everything to wifi.
*
* Receives a boolean to enable forceWifiUsage if true, and disable if false.
* Is important to disable it when disconnecting from IoT device.
* @param useWifi boolean to force wifi off or on
*/
export function forceWifiUsage(force: boolean): Promise<void>;
export function forceWifiUsage(useWifi: boolean): Promise<void>;
//#endregion
}

0 comments on commit 7c9daef

Please sign in to comment.