我正在一个需要与IOT设备(Raspberry Pi)进行通信的项目中。这个IOT设备构成了一个热点,我连接了由Pi创建的Wi-Fi。但是在Android 9中,请求被重定向到移动数据,而不是Wifi。
在盯着我时,我遇到一个问题,如果移动数据也同时打开,则移动会将所有请求重定向到移动数据而不是Wifi。但是移动数据处于关闭状态,然后在Android 9中也可以正常工作。为了使其与移动数据兼容,我使用了强制方法来建立强制Wi-Fi连接(请参阅forceWifiUsage方法)。在使用(findAndConnect)方法建立连接之前使用此方法,它也开始处理移动数据。但是,即使关闭了移动数据,它也无法在Android 9中运行。在Android 9中我无法与wifi通信的原因是什么?
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.RELEASE.toString().equals("6.0.1")) {
canWriteFlag = true;
// Don't need ACTION_MANAGE_WRITE_SETTINGS on 6.0.1, if we can positively identify it treat like 7+
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
// On M 6.0.0 (N+ or higher and 6.0.1 hit above), we need ACTION_MANAGE_WRITE_SETTINGS to forceWifi.
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))) {
System.out.println("before ConnectivityManager");
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);
System.out.println("ConnectivityManager:- "+manager);
manager.requestNetwork(builder.build(), new ConnectivityManager.NetworkCallback() {
@Override
public void onAvailable(Network network) {
System.out.println("onAvailable:- "+network);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
manager.bindProcessToNetwork(network);
System.out.println("bindProcessToNetwork:- ");
} else {
//This method was deprecated in API level 23
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);
}
}
}
public void findAndConnect(String ssid, String password) {
System.out.println("bindProcessToNetwork:- ");
List < ScanResult > results = wifi.getScanResults();
boolean connected = false;
for (ScanResult result: results) {
String resultString = "" + result.SSID;
System.out.println("ScanResult:- "+resultString);
if (ssid.equals(resultString)) {
System.out.println("if ssid equals:- "+resultString);
connected = connectTo(result, password, ssid);
}
}
}
//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("WPA:-");
// 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("WEP:-");
// 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("ELSE:-");
conf.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
}
List<WifiConfiguration> mWifiConfigList = wifi.getConfiguredNetworks();
if (mWifiConfigList == null) {
return false;
}
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;
}