web-dev-qa-db-fra.com

Définir une IP statique et une passerelle par programme dans Android 6.x (Marshmallow)

Quelqu'un peut-il me dire comment définir une adresse IP statique et une passerelle par programme dans Android 6?

J'ai lu ici et ici .

Settings.System ne fonctionne plus et goolgle indique que WIFI_STATIC_IP est obsolète dans l'API de niveau 17 et que vous utilisez plutôt WifiManger. Malheureusement, je ne trouve rien à ce sujet dans les classes WifiManger et WifiConfiguration.

15
WonderfulMe

Puisqu'il n'y a pas d'API officielle, je dois trouver une solution en modifiant des échantillons à partir du code snipet et cette réponse . Cette solution fonctionne sur les appareils à partir de Lollipop. 

 @SuppressWarnings("unchecked")
 public static void setStaticIpConfiguration(WifiManager manager, WifiConfiguration config, InetAddress ipAddress, int prefixLength, InetAddress gateway, InetAddress[] dns) throws ClassNotFoundException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, NoSuchFieldException, InstantiationException {
        // First set up IpAssignment to STATIC.
        Object ipAssignment = getEnumValue("Android.net.IpConfiguration$IpAssignment", "STATIC");
        callMethod(config, "setIpAssignment", new String[]{"Android.net.IpConfiguration$IpAssignment"}, new Object[]{ipAssignment});

        // Then set properties in StaticIpConfiguration.
        Object staticIpConfig = newInstance("Android.net.StaticIpConfiguration");
        Object linkAddress = newInstance("Android.net.LinkAddress", new Class<?>[]{InetAddress.class, int.class}, new Object[]{ipAddress, prefixLength});

        setField(staticIpConfig, "ipAddress", linkAddress);
        setField(staticIpConfig, "gateway", gateway);
        getField(staticIpConfig, "dnsServers", ArrayList.class).clear();
        for (int i = 0; i < dns.length; i++)
            getField(staticIpConfig, "dnsServers", ArrayList.class).add(dns[i]);

        callMethod(config, "setStaticIpConfiguration", new String[]{"Android.net.StaticIpConfiguration"}, new Object[]{staticIpConfig});

        int netId = manager.updateNetwork(config);
        boolean result = netId != -1;
        if (result) {
            boolean isDisconnected = manager.disconnect();
            boolean configSaved = manager.saveConfiguration();
            boolean isEnabled = manager.enableNetwork(config.networkId, true);
            boolean isReconnected = manager.reconnect();
        }
    }

Fonctions d'assistance,

    public static WifiConfiguration getCurrentWiFiConfiguration(Context context) {
            WifiConfiguration wifiConf = null;
            ConnectivityManager connManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
            NetworkInfo networkInfo = connManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
            if (networkInfo.isConnected()) {
                final WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
                final WifiInfo connectionInfo = wifiManager.getConnectionInfo();
                if (connectionInfo != null && !TextUtils.isEmpty(connectionInfo.getSSID())) {
                    List<WifiConfiguration> configuredNetworks = wifiManager.getConfiguredNetworks();
                    if (configuredNetworks != null) {
                        for (WifiConfiguration conf : configuredNetworks) {
                            if (conf.networkId == connectionInfo.getNetworkId()) {
                                wifiConf = conf;
                                break;
                            }
                        }
                    }
                }
            }
            return wifiConf;
        }

 private static Object newInstance(String className) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, IllegalArgumentException, InvocationTargetException {
        return newInstance(className, new Class<?>[0], new Object[0]);
    }

    private static Object newInstance(String className, Class<?>[] parameterClasses, Object[] parameterValues) throws NoSuchMethodException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, ClassNotFoundException {
        Class<?> clz = Class.forName(className);
        Constructor<?> constructor = clz.getConstructor(parameterClasses);
        return constructor.newInstance(parameterValues);
    }

    @SuppressWarnings({"unchecked", "rawtypes"})
    private static Object getEnumValue(String enumClassName, String enumValue) throws ClassNotFoundException {
        Class<Enum> enumClz = (Class<Enum>) Class.forName(enumClassName);
        return Enum.valueOf(enumClz, enumValue);
    }

    private static void setField(Object object, String fieldName, Object value) throws IllegalAccessException, IllegalArgumentException, NoSuchFieldException {
        Field field = object.getClass().getDeclaredField(fieldName);
        field.set(object, value);
    }

    private static <T> T getField(Object object, String fieldName, Class<T> type) throws IllegalAccessException, IllegalArgumentException, NoSuchFieldException {
        Field field = object.getClass().getDeclaredField(fieldName);
        return type.cast(field.get(object));
    }

    private static void callMethod(Object object, String methodName, String[] parameterTypes, Object[] parameterValues) throws ClassNotFoundException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException {
        Class<?>[] parameterClasses = new Class<?>[parameterTypes.length];
        for (int i = 0; i < parameterTypes.length; i++)
            parameterClasses[i] = Class.forName(parameterTypes[i]);

        Method method = object.getClass().getDeclaredMethod(methodName, parameterClasses);
        method.invoke(object, parameterValues);
    }

Pour l'utiliser,

WifiManager wifiManager = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
WifiConfiguration wifiConf = WifiHelper.getCurrentWiFiConfiguration(getApplicationContext());

        try {
            setStaticIpConfiguration(wifiManager, wifiConf,
                    InetAddress.getByName("192.168.0.100"),
                    24,
                    InetAddress.getByName("10.0.0.2"),
                    new InetAddress[]{InetAddress.getByName("10.0.0.3"), InetAddress.getByName("10.0.0.4")});

        } catch (Exception e) {
            e.printStackTrace();
        }

Enfin, vous devez ajouter ces autorisations dans le manifeste,

  <uses-permission Android:name="Android.permission.ACCESS_WIFI_STATE" />
  <uses-permission Android:name="Android.permission.ACCESS_NETWORK_STATE" />
  <uses-permission Android:name="Android.permission.CHANGE_WIFI_STATE" />
  <uses-permission Android:name="Android.permission.WRITE_SETTINGS" />
12
Prokash Sarkar

Je me suis plongé dans le problème et mes conclusions sont que le code qui fonctionnait auparavant pour Andrdoi 5.x pourrait fonctionner si l'application est définie pour être le propriétaire du périphérique. 

Solution:

La solution consiste à ajouter le périphérique en tant que deviceOwner. Cela permettra de définir une adresse IP statique en utilisant les hacks 5.x référencés par Mogi. Un bon exemple de la façon dont cela est fait est d'utiliser l'exemple trouvé ici:

https://github.com/googlesamples/Android-DeviceOwner/

En utilisant adb Shell et en exécutant la commande:

dpm set-device-owner com.example.Android.deviceowner/.DeviceOwnerReceiver

le rendra prêt à être autorisé à faire son travail.

2
Knubo

J'ai ajouté et connecté avec succès aux réseaux ouverts et PSK par programmation dans mon application (essayé sur des appareils fonctionnant sous les versions 5.1 ainsi que 6.0). Cependant, lorsque j'essaie ceci pour le réseau d'entreprise, cela ne fonctionne pas. Je vois que addNetwork () réussit (renvoie un identifiant net positif), mais lorsque je regarde sous Paramètres-> Wi-Fi, je ne vois pas le SSID comme je le fais pour les autres SSID que j'ai ajoutés. Quelqu'un sait pourquoi ce serait? Si je recherche par programme la liste WiFiConfiguration, elle trouve le SSID. Voici le code que j'utilise:

wifiConf = new WifiConfiguration();
wifiConf.SSID = "\"dot1x-test\"";
wifiConf.BSSID = "c4:e9:84:43:48:e8";
if (Android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
    wifiConf.enterpriseConfig.setIdentity("name");
    wifiConf.enterpriseConfig.setPassword("testpassword");
    wifiConf.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.PEAP);
    wifiConf.enterpriseConfig.setPhase2Method(WifiEnterpriseConfig.Phase2.MSCHAPV2);
}

netId = wifiMgr.addNetwork(wifiConf);
wifiMgr.disconnect();
wifiMgr.enableNetwork(netId, true);
wifiMgr.saveConfiguration();
wifiMgr.reconnect();
0
Akshay Chopde