Open preetlotey999 opened 5 years ago
I fixed it.
Can you tell me how you fixed it?
Can you tell me how you fixed it? i am facing same issue
I have resolved the issue, now it is working fine for me we need to make the changes in AndroidWifiModule class. Try to replace the code with below code.
package com.devstepbcn.wifi;
import com.facebook.react.uimanager.; import com.facebook.react.bridge.; import com.facebook.systrace.Systrace; import com.facebook.systrace.SystraceMessage; import com.facebook.react.ReactInstanceManager; import com.facebook.react.ReactRootView; import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler; import com.facebook.react.modules.core.DeviceEventManagerModule; import com.facebook.react.shell.MainReactPackage; import com.facebook.soloader.SoLoader; import android.provider.Settings; import android.net.wifi.ScanResult; import android.net.wifi.WifiManager; import android.net.wifi.WifiConfiguration; import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.net.NetworkRequest; import android.net.NetworkCapabilities; import android.net.Network; import android.net.Uri; import android.net.wifi.WifiInfo; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.BroadcastReceiver; import android.os.Build; import android.os.Bundle; import android.widget.Toast; import java.util.List; import java.lang.Thread; import android.net.DhcpInfo;
import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject;
public class AndroidWifiModule extends ReactContextBaseJavaModule {
//WifiManager Instance WifiManager wifi; ReactApplicationContext reactContext;
//Constructor public AndroidWifiModule(ReactApplicationContext reactContext) { super(reactContext);
wifi = (WifiManager)reactContext.getApplicationContext().getSystemService(Context.WIFI_SERVICE); this.reactContext = reactContext; }
//Name for module register to use: @Override public String getName() { return "AndroidWifiModule"; }
//Method to load wifi list into string via Callback. Returns a stringified JSONArray @ReactMethod public void loadWifiList(Callback successCallback, Callback errorCallback) { try { List < ScanResult > results = wifi.getScanResults(); JSONArray wifiArray = new JSONArray();
for (ScanResult result: results) { JSONObject wifiObject = new JSONObject(); if(!result.SSID.equals("")){ try { wifiObject.put("SSID", result.SSID); wifiObject.put("BSSID", result.BSSID); wifiObject.put("capabilities", result.capabilities); wifiObject.put("frequency", result.frequency); wifiObject.put("level", result.level); wifiObject.put("timestamp", result.timestamp); //Other fields not added //wifiObject.put("operatorFriendlyName", result.operatorFriendlyName); //wifiObject.put("venueName", result.venueName); //wifiObject.put("centerFreq0", result.centerFreq0); //wifiObject.put("centerFreq1", result.centerFreq1); //wifiObject.put("channelWidth", result.channelWidth); } catch (JSONException e) { errorCallback.invoke(e.getMessage()); } wifiArray.put(wifiObject); } } successCallback.invoke(wifiArray.toString()); } catch (IllegalViewOperationException e) { errorCallback.invoke(e.getMessage()); } }
//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.
//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. @ReactMethod public void forceWifiUsage(boolean useWifi) { boolean canWriteFlag = false; System.out.println("step start "); if (useWifi) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
canWriteFlag = true;
// Only need ACTION_MANAGE_WRITE_SETTINGS on 6.0.0, regular permissions suffice on later versions
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
canWriteFlag = Settings.System.canWrite(reactContext);
if (!canWriteFlag) {
Intent intent = new Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS);
intent.setData(Uri.parse("package:" + reactContext.getPackageName()));
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
reactContext.startActivity(intent);
}
}
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) reactContext
.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkRequest.Builder builder;
builder = new NetworkRequest.Builder();
//set the transport type do WIFI
builder.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
//builder.addCapability(NetworkCapabilities.TRANSPORT_WIFI); System.out.println("called in if "+ builder); manager.requestNetwork(builder.build(), new ConnectivityManager.NetworkCallback() { @Override public void onAvailable(Network network) { try { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { System.out.println("onAvailable in if called "+manager); manager.bindProcessToNetwork(network); } else { System.out.println("onAvailable in else called "); //This method was deprecated in API level 23 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { ConnectivityManager.setProcessDefaultNetwork(network); } } /if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { manager.unregisterNetworkCallback(this); }/ }catch (Exception e){ System.out.println("Exception called "+ e); } } }); } } } else { System.out.println("useWifi false called "); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { ConnectivityManager manager = (ConnectivityManager) reactContext .getSystemService(Context.CONNECTIVITY_SERVICE); manager.bindProcessToNetwork(null); } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { ConnectivityManager.setProcessDefaultNetwork(null); } } }
//Use this method to make sure that your forced network already bound @ReactMethod public void connectionStatusOfBoundNetwork(Callback connectionStatusResult) { ConnectivityManager connManager = (ConnectivityManager) getReactApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE); Network network = null; if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) { network = connManager.getBoundNetworkForProcess(); } if (network != null) { connectionStatusResult.invoke(true); } else { connectionStatusResult.invoke(false); } }
//Method to check if wifi is enabled @ReactMethod public void isEnabled(Callback isEnabled) { isEnabled.invoke(wifi.isWifiEnabled()); }
//Method to connect/disconnect wifi service @ReactMethod public void setEnabled(Boolean enabled) { wifi.setWifiEnabled(enabled); }
//Send the ssid and password of a Wifi network into this to connect to the network. //Example: wifi.findAndConnect(ssid, password); //After 10 seconds, a post telling you whether you are connected will pop up. //Callback returns true if ssid is in the range @ReactMethod public void findAndConnect(String ssid, String password, Callback ssidFound) { System.out.println("step 1 "); List < ScanResult > results = wifi.getScanResults(); System.out.println("step 2 "); boolean connected = false; System.out.println("step 3 "); for (ScanResult result: results) { System.out.println("step 4 "); String resultString = "" + result.SSID; System.out.println("step 5 "); if (ssid.equals(resultString)) { System.out.println("step 6 "+resultString); connected = connectTo(result, password, ssid); } } ssidFound.invoke(connected); }
//Use this method to check if the device is currently connected to Wifi. @ReactMethod public void connectionStatus(Callback connectionStatusResult) { ConnectivityManager connManager = (ConnectivityManager) getReactApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo mWifi = connManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI); if (mWifi.isConnected()) { connectionStatusResult.invoke(true); } else { connectionStatusResult.invoke(false); } }
//Method to connect to WIFI Network public Boolean connectTo(ScanResult result, String password, String ssid) { //Make new configuration WifiConfiguration conf = new WifiConfiguration();
//clear alloweds
conf.allowedAuthAlgorithms.clear(); conf.allowedGroupCiphers.clear(); conf.allowedKeyManagement.clear(); conf.allowedPairwiseCiphers.clear(); conf.allowedProtocols.clear();
// Quote ssid and password
conf.SSID = String.format("\"%s\"", ssid); WifiConfiguration tempConfig = this.IsExist(conf.SSID); if (tempConfig != null) { wifi.removeNetwork(tempConfig.networkId); }
String capabilities = result.capabilities; // appropriate ciper is need to set according to security type used if (capabilities.contains("WPA") || capabilities.contains("WPA2") || capabilities.contains("WPA/WPA2 PSK")) { System.out.println("step 7 "); // This is needed for WPA/WPA2 // Reference - https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/wifi/java/android/net/wifi/WifiConfiguration.java#149 conf.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
conf.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP); conf.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
conf.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
conf.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP); conf.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
conf.allowedProtocols.set(WifiConfiguration.Protocol.RSN); conf.allowedProtocols.set(WifiConfiguration.Protocol.WPA); conf.status = WifiConfiguration.Status.ENABLED; conf.preSharedKey = String.format("\"%s\"", password);
} else if (capabilities.contains("WEP")) { System.out.println("step 8 "); // This is needed for WEP // Reference - https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/wifi/java/android/net/wifi/WifiConfiguration.java#149 conf.wepKeys[0] = "\"" + password + "\""; conf.wepTxKeyIndex = 0; conf.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN); conf.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.SHARED); conf.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); conf.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40); } else { System.out.println("step 9 "); conf.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); }
List
int updateNetwork = -1;
// Use the existing network config if exists for (WifiConfiguration wifiConfig : mWifiConfigList) { if (wifiConfig.SSID.equals(conf.SSID)) { conf=wifiConfig; updateNetwork=conf.networkId; } }
// If network not already in configured networks add new network if ( updateNetwork == -1 ) { updateNetwork = wifi.addNetwork(conf); wifi.saveConfiguration(); }
// if network not added return false
if ( updateNetwork == -1 ) { return false; }
// disconnect current network
boolean disconnect = wifi.disconnect(); if ( !disconnect ) { return false; }
// enable new network boolean enableNetwork = wifi.enableNetwork(updateNetwork, true); if ( !enableNetwork ) { return false; }
return true; } //add configuration of hidden network and return it's networkId public int setWifiConfig(String ssid, String sharedKey) { WifiConfiguration conf = new WifiConfiguration();
conf.SSID = "\"" + ssid + "\""; conf.preSharedKey = "\"" + sharedKey + "\""; conf.hiddenSSID = true; conf.status = WifiConfiguration.Status.ENABLED; conf.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP); conf.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP); conf.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK); conf.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP); conf.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP); conf.allowedProtocols.set(WifiConfiguration.Protocol.RSN); conf.allowedProtocols.set(WifiConfiguration.Protocol.WPA); return wifi.addNetwork(conf); }
//Add a hidden wifi network and connect to it
//Example: wifi.connectToHiddenNetwork(ssid, password, (networkAdded) => {});
//Callback returns true if network added and tried to connect to it successfully
//It may take up to 15s to connect to hidden networks
@ReactMethod
public void connectToHiddenNetwork(String ssid, String password, Callback networkAdded) {
List
int updateNetwork = -1;
// check if network config exists and it's hidden for (WifiConfiguration wifiConfig : list) { if (wifiConfig.SSID.equals("\"" + ssid + "\"") && wifiConfig.hiddenSSID) { updateNetwork = wifiConfig.networkId; } }
// If network not already in configured networks add new network if (updateNetwork == -1) { updateNetwork = setWifiConfig(ssid, password); }
// if network not added return false if (updateNetwork == -1) { networkAdded.invoke(false); return; } // disconnect current network boolean disconnect = wifi.disconnect(); if (!disconnect) { networkAdded.invoke(false); return; }
// enable new network boolean enableNetwork = wifi.enableNetwork(updateNetwork, true); if (!enableNetwork) { networkAdded.invoke(false); return; } // reconnect to new network boolean reconnect = wifi.reconnect(); if (!reconnect) { networkAdded.invoke(false); return; }
wifi.saveConfiguration();
networkAdded.invoke(true); }
//Disconnect current Wifi. @ReactMethod public void disconnect() { wifi.disconnect(); }
//This method will return current ssid @ReactMethod public void getSSID(final Callback callback) { WifiInfo info = wifi.getConnectionInfo();
// This value should be wrapped in double quotes, so we need to unwrap it. String ssid = info.getSSID(); if (ssid.startsWith("\"") && ssid.endsWith("\"")) { ssid = ssid.substring(1, ssid.length() - 1); }
callback.invoke(ssid); }
//This method will return the basic service set identifier (BSSID) of the current access point @ReactMethod public void getBSSID(final Callback callback) { WifiInfo info = wifi.getConnectionInfo();
String bssid = info.getBSSID();
callback.invoke(bssid.toUpperCase()); }
//This method will return current wifi signal strength @ReactMethod public void getCurrentSignalStrength(final Callback callback) { int linkSpeed = wifi.getConnectionInfo().getRssi(); callback.invoke(linkSpeed); }
//This method will return current wifi frequency @ReactMethod public void getFrequency(final Callback callback) { WifiInfo info = wifi.getConnectionInfo(); int frequency = 0; if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) { frequency = info.getFrequency(); } callback.invoke(frequency); }
//This method will return current IP @ReactMethod public void getIP(final Callback callback) { WifiInfo info = wifi.getConnectionInfo(); String stringip = longToIP(info.getIpAddress()); callback.invoke(stringip); }
//This method will remove the wifi network as per the passed SSID from the device list
@ReactMethod
public void isRemoveWifiNetwork(String ssid, final Callback callback) {
List
for (WifiConfiguration wifiConfig : mWifiConfigList) { String comparableSSID = ('"' + ssid + '"'); //Add quotes because wifiConfig.SSID has them if(wifiConfig.SSID.equals(comparableSSID)) { wifi.removeNetwork(wifiConfig.networkId); wifi.saveConfiguration(); callback.invoke(true); return; } } callback.invoke(false); }
@ReactMethod public void reScanAndLoadWifiList(Callback successCallback, Callback errorCallback) { WifiReceiver receiverWifi = new WifiReceiver(wifi, successCallback, errorCallback); getCurrentActivity().registerReceiver(receiverWifi, new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)); wifi.startScan(); }
@ReactMethod public void getDhcpServerAddress(Callback callback) { DhcpInfo dhcpInfo = wifi.getDhcpInfo(); String ip = longToIP(dhcpInfo.serverAddress); callback.invoke(ip); }
public static String longToIP(int longIp){ StringBuffer sb = new StringBuffer(""); String[] strip=new String[4]; strip[3]=String.valueOf((longIp >>> 24)); strip[2]=String.valueOf((longIp & 0x00FFFFFF) >>> 16); strip[1]=String.valueOf((longIp & 0x0000FFFF) >>> 8); strip[0]=String.valueOf((longIp & 0x000000FF)); sb.append(strip[0]); sb.append("."); sb.append(strip[1]); sb.append("."); sb.append(strip[2]); sb.append("."); sb.append(strip[3]); return sb.toString(); }
private WifiConfiguration IsExist(String SSID) {
List
for (WifiConfiguration existingConfig : existingConfigs) { if (existingConfig.SSID.equals("\"" + SSID + "\"")) { return existingConfig; } } return null; }
class WifiReceiver extends BroadcastReceiver {
private Callback successCallback; private Callback errorCallback; private WifiManager wifi;
public WifiReceiver(final WifiManager wifi, Callback successCallback, Callback errorCallback) { super(); this.successCallback = successCallback; this.errorCallback = errorCallback; this.wifi = wifi; }
// This method call when number of wifi connections changed public void onReceive(Context c, Intent intent) { c.unregisterReceiver(this);
try { List < ScanResult > results = this.wifi.getScanResults(); JSONArray wifiArray = new JSONArray();
for (ScanResult result: results) { JSONObject wifiObject = new JSONObject(); if(!result.SSID.equals("")){ try { wifiObject.put("SSID", result.SSID); wifiObject.put("BSSID", result.BSSID); wifiObject.put("capabilities", result.capabilities); wifiObject.put("frequency", result.frequency); wifiObject.put("level", result.level); wifiObject.put("timestamp", result.timestamp); } catch (JSONException e) { this.errorCallback.invoke(e.getMessage()); return; } wifiArray.put(wifiObject); } } this.successCallback.invoke(wifiArray.toString()); return; } catch (IllegalViewOperationException e) { this.errorCallback.invoke(e.getMessage()); return; } } } }
@Pankajmalhan could you please explain the change that you made or paste it again within a code block? It seems like Github formatting stripped some of the code. Thanks!
Hi @gpawlik following is the list of changes that I made. Change 1: Replace Constructor code with following `public AndroidWifiModule(ReactApplicationContext reactContext) { super(reactContext);
wifi = (WifiManager)reactContext.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
this.reactContext = reactContext;
}`
Change 2: Replace Force Wifi Usage with below code `@ReactMethod public void forceWifiUsage(boolean useWifi) { boolean canWriteFlag = false;
if (useWifi) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
canWriteFlag = true;
// Only need ACTION_MANAGE_WRITE_SETTINGS on 6.0.0, regular permissions suffice on later versions
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
canWriteFlag = Settings.System.canWrite(reactContext);
if (!canWriteFlag) {
Intent intent = new Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS);
intent.setData(Uri.parse("package:" + reactContext.getPackageName()));
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
reactContext.startActivity(intent);
}
}
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) reactContext
.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkRequest.Builder builder;
builder = new NetworkRequest.Builder();
//set the transport type do WIFI
builder.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
manager.requestNetwork(builder.build(), new ConnectivityManager.NetworkCallback() {
@Override
public void onAvailable(Network network) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
manager.bindProcessToNetwork(network);
} else {
//This method was deprecated in API level 23
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){
ConnectivityManager.setProcessDefaultNetwork(network);
}
}
try {
} catch (Exception e) {
e.printStackTrace();
}
// manager.unregisterNetworkCallback(this);
}
});
}
}
} else {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
ConnectivityManager manager = (ConnectivityManager) reactContext
.getSystemService(Context.CONNECTIVITY_SERVICE);
manager.bindProcessToNetwork(null);
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
ConnectivityManager.setProcessDefaultNetwork(null);
}
}
}`
Change 3: Replace code of connectionStatusOfBoundNetwork method with the following code
These are the changes that you need to make and this is code how I am connecting to devices.
connectToInternet = () => { wifi.reScanAndLoadWifiList((wifiStringList) => { wifi.forceWifiUsage(true); wifi.findAndConnect(this.wifiname, API.pIDevicePassword, (found) => { if (found) { ToastAndroid.show(strings("checkInstall.wifiFind", lang), ToastAndroid.SHORT); setTimeout(() => { wifi.connectionStatusOfBoundNetwork((isBound) => { wifi.getSSID((ssid) => { if (ssid == this.wifiname) { // call your method here that you want ot run after making the connection } else { this.connectToInternet(); } }); }); }, 15000); } else { } }); }, () => { alert('can not rescan') }) }
I need to implement setTimeout here because forceWifiUsage some time to make a force connections.
I don't why this code is formatting, you can download file from here AndoirdWifiModule.java
connectToInternet = () => { wifi.reScanAndLoadWifiList((wifiStringList) => { wifi.forceWifiUsage(true); wifi.findAndConnect(this.wifiname, API.pIDevicePassword, (found) => { if (found) { ToastAndroid.show(strings("checkInstall.wifiFind", lang), ToastAndroid.SHORT); setTimeout(() => { wifi.connectionStatusOfBoundNetwork((isBound) => { wifi.getSSID((ssid) => { if (ssid == this.wifiname) { // call your method here that you want ot run after making the connection } else { this.connectToInternet(); } }); }); }, 15000); } else { } }); }, () => { alert('can not rescan') }) }
@Pankajmalhan given code doesn't work for do we need to make any other changes in AndroidManifest.xml or another file?
@preetlotey999 can you please help on this? I am also having the same scenario, could you please post your fix?
I'm also having issues with Android 9. forceWifiUsage(true)
is not prompting to enable write settings.
I am trying to connect with IOT device its working in some devices but not working specifically in OS 9 and some OS 8 versions. Please assist.
Thanks