Android: Почему SDK не позволяет программисту легко добавлять профили WiFi (EAP)?

Я пытаюсь программно создавать корпоративные профили WiFi на Android (WPA-Enterprise, WPA2-Enterprise).

Я видел довольно известное решение, которое должно использовать отражение для достижения этого. Насколько я понимаю, если это необходимо сделать таким косвенным образом, что предполагает получение доступа к частям API, которым было отказано в доступе, для этого должна быть веская причина.

Означает ли это, что Google НЕ хочет, чтобы разработчики могли программно настраивать настройки WiFi? Если да, то в чем причина этого?

Android JellyBean 4.3 добавила эту функциональность в свой API:

http://developer.android.com/reference/android/net/wifi/WifiEnterpriseConfig.html

Я написал класс со статическим методом, который позволит вам это сделать. Вот. Вам нужно будет передать SSID, Username и Password в этот метод. Существуют и другие параметры, которые вы можете установить, если вам нужно установить EAP в TLS или PEAP. Следует отметить, что этот код является основой кода здесь: Как программно создавать и читать конфигурации WEP / EAP WiFi в Android? , Разница заключается в том, что мой код позволяет вам настроить параметры конфигурации IP и настройки прокси-сервера. Используя этот код, вы можете автоматически подключиться к Wi-Fi-сети с настройками WPA_EAP.

Надеюсь это поможет:

import java.lang.reflect.Field; import java.lang.reflect.Method; import android.net.wifi.WifiConfiguration; import android.util.Log; public class WPAConfiguration { private static final String INT_PRIVATE_KEY = "private_key"; private static final String INT_PHASE2 = "phase2"; private static final String INT_PASSWORD = "password"; private static final String INT_IDENTITY = "identity"; private static final String INT_EAP = "eap"; private static final String INT_CLIENT_CERT = "client_cert"; private static final String INT_CA_CERT = "ca_cert"; private static final String INT_ANONYMOUS_IDENTITY = "anonymous_identity"; private static final String INT_ENTERPRISEFIELD_NAME = "android.net.wifi.WifiConfiguration$EnterpriseField"; private static final String INT_IPASSIGNMENT_NAME = "android.net.wifi.WifiConfiguration$IpAssignment"; private static final String INT_PROXYSETTINGS_NAME = "android.net.wifi.WifiConfiguration$ProxySettings"; //change this to TLS,PEAP, or other options that are listed when you connect via a device private static final String ENTERPRISE_EAP = "PEAP"; private static final String INT_IP_ASSIGNMENT = "ipAssignment"; private static final String INT_PROXY_SETTINGS = "proxySettings"; public static WifiConfiguration setWifiConfigurations(WifiConfiguration wifiConfig, String SSID, String userName, String userPass) { /*define basic configuration settings*/ /*Access Point*/ wifiConfig.SSID = SSID; wifiConfig.networkId = 0; /*Priority*/ wifiConfig.priority = 0; /*Enable Hidden SSID's*/ wifiConfig.hiddenSSID = false; /*Key Management*/ wifiConfig.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.IEEE8021X); wifiConfig.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP); /*Set Group Ciphers*/ wifiConfig.allowedGroupCiphers.clear(); wifiConfig.allowedGroupCiphers.clear(); wifiConfig.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP); wifiConfig.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP); wifiConfig.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104); wifiConfig.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40); /*Set Pairwise Ciphers*/ wifiConfig.allowedPairwiseCiphers.clear(); wifiConfig.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP); wifiConfig.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP); /*Set Protocols*/ wifiConfig.allowedProtocols.clear(); wifiConfig.allowedProtocols.set(WifiConfiguration.Protocol.RSN); wifiConfig.allowedProtocols.set(WifiConfiguration.Protocol.WPA); /*Set Enterprise Settings Using Reflection*/ try { Class<?> wifiEnterpriseField = null; Class<?> wifiIpAssignmentField = null; Class<?> wifiProxySettingsField = null; boolean enterpriseFieldType = true; boolean ipAssignmentFieldType = true; boolean proxySettingsFieldType = true; Field anonymousId = null, caCert = null, clientCert = null, eap = null, identity = null, password = null, phase2 = null, privateKey = null, ipAssignment = null, proxy = null; Method setValue = null; Class<?>[] wifiClasses = WifiConfiguration.class.getClasses(); /*Get Enterprise/IP Assignment/Proxy Setting Field Class to Modify*/ for(Class<?> wifiClass : wifiClasses) { if(wifiClass.getName().equals(INT_ENTERPRISEFIELD_NAME)) { wifiEnterpriseField = wifiClass; } else if(wifiClass.getName().equals(INT_IPASSIGNMENT_NAME)) { wifiIpAssignmentField = wifiClass; } else if(wifiClass.getName().equals(INT_PROXYSETTINGS_NAME)) { wifiProxySettingsField = wifiClass; } } /*Certain OS (Cupcake & Doughnut) access the enterprise field directly*/ if(wifiEnterpriseField == null) { enterpriseFieldType = false; } if(wifiIpAssignmentField == null) { ipAssignmentFieldType = false; } if(wifiProxySettingsField == null) { proxySettingsFieldType = false; } /*Get Fields*/ Log.d("Enterprise Setting", "Getting Fields "); Field[] wifiFields = WifiConfiguration.class.getFields(); for(Field wifiField : wifiFields) { if(wifiField.getName().equals(INT_ANONYMOUS_IDENTITY)) { anonymousId = wifiField; Log.d("Enterprise Setting", "Getting Field: " + wifiField); } else if(wifiField.getName().equals(INT_CA_CERT)) { caCert = wifiField; Log.d("Enterprise Setting", "Getting Field: " + wifiField); } else if(wifiField.getName().equals(INT_CLIENT_CERT)) { clientCert = wifiField; Log.d("Enterprise Setting", "Getting Field: " + wifiField); } else if(wifiField.getName().equals(INT_EAP)) { eap = wifiField; Log.d("Enterprise Setting", "Getting Field: " + wifiField); } else if(wifiField.getName().equals(INT_IDENTITY)) { identity = wifiField; Log.d("Enterprise Setting", "Getting Field: " + wifiField); } else if(wifiField.getName().equals(INT_PASSWORD)) { password = wifiField; Log.d("Enterprise Setting", "Getting Field: " + wifiField); } else if(wifiField.getName().equals(INT_PHASE2)) { phase2 = wifiField; Log.d("Enterprise Setting", "Getting Field: " + wifiField); } else if(wifiField.getName().equals(INT_PRIVATE_KEY)) { privateKey = wifiField; Log.d("Enterprise Setting", "Getting Field: " + wifiField); } else if(wifiField.getName().equals(INT_IP_ASSIGNMENT)) { ipAssignment = wifiField; Log.d("Enterprise Setting", "Getting Field: " + wifiField); } else if(wifiField.getName().equals(INT_PROXY_SETTINGS)) { proxy = wifiField; Log.d("Enterprise Setting", "Getting Field: " + wifiField); } } /*Get method to set value of enterprise fields*/ if(enterpriseFieldType) { for(Method method : wifiEnterpriseField.getMethods()) { Log.d("Get Methods", "Enterprise Method: " + method); if(method.getName().trim().equals("setValue")) { setValue = method; break; } } } /*Set EAP*/ if(enterpriseFieldType) { setValue.invoke(eap.get(wifiConfig), ENTERPRISE_EAP); Log.d("Enterprise Setting", "Setting " + ENTERPRISE_EAP); } else { eap.set(wifiConfig, ENTERPRISE_EAP); } /*Set Identity*/ if(enterpriseFieldType) { setValue.invoke(identity.get(wifiConfig), userName); Log.d("Enterprise Setting", "Setting " + userName); } else { identity.set(wifiConfig, userName); } /*Set user password*/ if(enterpriseFieldType) { setValue.invoke(password.get(wifiConfig), userPass); Log.d("Enterprise Setting", "Setting " + userPass); } else { password.set(wifiConfig, userPass); } /*Set IP Protocol*/ if(ipAssignmentFieldType) { /*Change the literal string in here to change the value of obtaining and IP address*/ ipAssignment.set(wifiConfig, Enum.valueOf((Class<Enum>) ipAssignment.getType().asSubclass(Enum.class), "DHCP")); Log.d("Enterprise Setting", "Setting " + ipAssignment); } else { ipAssignment.set(wifiConfig, "DHCP"); } /*Set Proxy Protocol*/ if(proxySettingsFieldType) { /*Change the literal string in here to change the value of proxy settingss*/ proxy.set(wifiConfig, Enum.valueOf((Class<Enum>) proxy.getType().asSubclass(Enum.class), "NONE")); Log.d("Enterprise Setting", "Setting " + proxy); } else { proxy.set(wifiConfig, "NONE"); } } catch(Exception e) { Log.e("ERROR!!!", "Error: " + e); } Log.d("WIFI", "Configuration Settings " + wifiConfig.toString()); return wifiConfig; } } 

Возможно, мне не хватает чего-то в этом вопросе или в деталях, поскольку мне не нужно было это делать самому, но классы WifiManager и WifiConfiguration не делают то, что вам нужно? Например:

 WifiManager wMan = getSystemService(Context.WIFI_SERVICE); WifiConfiguration config = new WifiConfiguration(); config.SSID = "your ssid"; //continue setting up the configuration wMan.addNetwork(config); 

EDIT: ответ, который вы указали, использует только отражение для конфигураций EAP (обычно, с использованием безопасности WPA-Enterprise или WPA2-Enterprise). Для типичных соединений вам не нужно использовать отражение.