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

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

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

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

3 ответа

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

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

Я написал класс со статическим методом, который позволит вам сделать это. Вот. Вам нужно будет ввести свой SSID, имя пользователя и пароль в метод. Есть несколько других опций, которые вы можете установить, если вам нужно установить 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);

РЕДАКТИРОВАТЬ: Ответ, на который вы указали, использует отражение только для конфигураций EAP (соединения, использующие безопасность WPA-Enterprise или WPA2-Enterprise, как правило). Для типичных соединений вам не нужно использовать рефлексию.

Другие вопросы по тегам