2014-12-22 1 views
5

Wie kann eine statische IP-Adresse, Netzmaske, Gateway, DNS programmgesteuert auf Android 5.x konfiguriert werden für Wi-Fi-Verbindung? Gibt es eine offene API (nicht gefunden) oder versteckt kann dafür verwendet werden? Könnten Sie bitte auch einige Beispiele nennen, wenn möglich.Konfigurieren einer statischen IP-Adresse, Netzmaske, Gateway, DNS programmgesteuert auf Android 5.x (Lollipop) für Wi-Fi-Verbindung

Ich weiß, es ist possible on Android 4.0+ aber es funktioniert nicht auf Android 5.0

Antwort

19

Es gibt leider immer noch keine offene API.

Die Lösung für Android 4.0 funktioniert in LOLLIPOP nicht, da Dinge verschoben wurden. Insbesondere die neue Klasse IpConfiguration enthält jetzt die StaticIpConfiguration und all diese Felder. Sie können immer noch zugänglich gemacht werden, indem Reflektion (mit all der damit verbundenen Sprödigkeit) mit so etwas verwendet wird.

Warnung, dieser Code ist nur Android 5.0. Sie müssen Build.VERSION.SDK_INT überprüfen und entsprechend handeln.

@SuppressWarnings("unchecked") 
private 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 }); 
    manager.updateNetwork(config); 
    manager.saveConfiguration(); 
} 

Mit den folgenden Hilfsmethoden Reflexion zu handhaben:

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); 
} 

Zum Beispiel können Sie es so nennen:

public void test(Context context) 
{ 
    WifiManager manager = (WifiManager)context.getSystemService(Context.WIFI_SERVICE); 
    WifiConfiguration wifiConf = ... /* Get Wifi configuration you want to update */ 

    if (wifiConf != null) 
    { 
     try 
     { 
      setStaticIpConfiguration(manager, wifiConf, 
       InetAddress.getByName("10.0.0.1"), 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(); 
     } 
    } 
} 

Als Referenz, könnten Sie nehmen wollen ein Blick auf die WifiConfigController Klasse im Framework (obwohl es diese Klassen direkt anstelle von Reflektion verwendet).

+0

Mann das ist erstaunlich, getestet Ihren Code und es funktioniert! Du bist der Beste :) – KennyPowers

+0

Dies wäre auch ein gutes Beispiel für mich, wie versteckte Android-Klassen zu reflektieren. – KennyPowers

+0

Ich weiß, es ist eine andere Frage, aber 100% bezogen auf das Thema: Wie bekomme ich die derzeit funktionierenden DNS-ID-Adressen? – KennyPowers

0

IP-Adressen auf einer Schnittstelle konfiguriert werden, nicht auf Telefonbasis. Sie können keine IP-Adresse für die mobile Datenverbindung und alle drahtlosen Verbindungen (Bluetooth usw.), die ebenfalls erstellt werden, festlegen.

Da die IP-Adresse von der Schnittstelle abhängig ist, wird dort auch die Adresse konfiguriert.

Für die Datenverbindung wird die IP-Adresse (ich glaube, nicht bestätigt) vom Mobilfunknetz an das Telefon übermittelt und ist auf dem Gerät nicht konfigurierbar.

Bei normalen Wi-Fi-Verbindungen können Sie für jedes Netzwerk die Standardvorgabe (DHCP) oder eine andere Form der IP-Adressbereitstellung wählen, z. B. ob Sie die IP-Adresse manuell oder über das Dynamische konfigurieren möchten Systeme an Ort und Stelle.

Da das Gateway und die Netzmaske auch im Netzwerk eingerichtet sind, ist es sinnvoll, die 'statische' IP-Adresse für ein bestimmtes Netzwerk auf der Netzwerkseite zu konfigurieren. Bei den meisten Netzwerk-DHCP-Servern können Sie sie so konfigurieren, dass sie immer dieselbe Netzwerk-IP für jedes Gerät bereitstellen.

Das ist was ich tue, ich habe bestimmte Geräte bekommen ihre IP-Adresse durch DHCP, aber der DHCP-Server immer die gleiche vorkonfigurierte und 'statische' IP-Adresse zu den Geräten, die ich möchte konstant (und andere Geräte ziehen ein IP aus dem verfügbaren "Pool").

+0

Ich musste genauer sein, was ich will, ist IP-Zuordnung von DHCP zu STATIC ändern (ich weiß, wie das mit den Reflexionen von versteckten Android-Klassen zu tun), Gateway, Dnses und IP ändern. Ich werde meine Frage jetzt aktualisieren. – KennyPowers