如何在Android 3.x或4.x上以编程方式配置静态IP地址,网络掩码,网关 [英] How to configure a static IP address, netmask, gateway programmatically on Android 3.x or 4.x
问题描述
我已经检查了堆栈溢出问题 用于在Android应用程序中配置静态IP地址的API .
I have checked in Stack Overflow question API for configuring static IP addresses in an Android application.
它可以在Android 2.3之前运行.但是,在更高的API级别上没有运气.例如, 我把设置
It works until Android 2.3. However, there is no luck on a higher API level. For example, I put the setting
android.provider.Settings.System.putString(getContentResolver(), android.provider.Settings.System.WIFI_USE_STATIC_IP, "1");
android.provider.Settings.System.putString(getContentResolver(), android.provider.Settings.System.WIFI_STATIC_IP, "192.168.0.100");
android.provider.Settings.System.putString(getContentResolver(), android.provider.Settings.System.WIFI_STATIC_NETMASK, "255.255.255.0");
android.provider.Settings.System.putString(getContentResolver(), android.provider.Settings.System.WIFI_STATIC_DNS1, "192.168.0.254");
android.provider.Settings.System.putString(getContentResolver(), android.provider.Settings.System.WIFI_STATIC_GATEWAY, "192.168.0.254");
但是我回过头来检查:
Setting --> Wi-Fi --> Long Press Access Point SSID --> Modify Network --> check Show advanced options
IP Settings
字段仍表示为DHCP
,而不是Static
.
The IP Settings
field is still stated DHCP
but not Static
.
我可以使用android.provider.Settings.System.getString()
取回设置,这是事实.证明该设置保存在某个地方,但是系统只会忽略它.
It is true that I can use android.provider.Settings.System.getString()
to get back what I set. It prove that the setting is saved somewhere but the system just ignore it.
系统使用Android 3.x和4.x上android.provider.Settings.System
以外的设置,因为该设置是根据访问点SSID设置的.是否可以像在Android 2.3上一样修改一个SSID上的设置?
The system uses the setting other than android.provider.Settings.System
on Android 3.x and 4.x as the setting is set per Access Point SSID. Can I modify the setting on one SSID just like how it works on Android 2.3?
推荐答案
我意识到在3.x或4.x上没有针对每个SSID的那些设置的API.因此,我检查了源代码,发现每个SSID的配置存储在从android.net.wifi.WifiManager
获取的android.net.wifi.WifiConfiguration
中.
I realise that there is no API on 3.x or 4.x for those setting per SSID. Therefore, I checked out the source code and found out that the configuration of each SSID is stored in android.net.wifi.WifiConfiguration
which is gotten from android.net.wifi.WifiManager
.
在下面的代码中,IpAssignment
是一个枚举,可以是STAIC
,DHCP
或NONE
.
linkProperties
是对象存储的IP地址,网关,DNS等...
In the below code, IpAssignment
is an Enum, either STAIC
, DHCP
or NONE
.
And linkProperties
is the object store IP address, gateway, DNS, etc...
linkAddress
是IP地址,其网络掩码为prefixLength(网络掩码中的多少位1).
linkAddress
is IP address and its netmask as prefixLength (how many bit 1 in netmask).
mRoutes
是RouteInfo
的ArrayList
,可以指示网关.
mRoutes
is ArrayList
of RouteInfo
that can indicate gateway.
mDnses
是DNS的InetAddress
中的ArrayList
.
首先,使用WifiConfiguration
SSID
Firstly, get the current configuration using WifiConfiguration
SSID
WifiConfiguration wifiConf = null;
WifiManager wifiManager = (WifiManager)getSystemService(Context.WIFI_SERVICE);
WifiInfo connectionInfo = wifiManager.getConnectionInfo();
List<WifiConfiguration> configuredNetworks = wifiManager.getConfiguredNetworks();
for (WifiConfiguration conf : configuredNetworks){
if (conf.networkId == connectionInfo.getNetworkId()){
wifiConf = conf;
break;
}
}
由于隐藏了IpAssignment
和linkProperties
,因此可以从反射中获取对象.
As the IpAssignment
and linkProperties
are hidden, the object can be gotten from reflection.
以下方法可以在SSID WifiConfiguration上设置声明的IP地址设置:
The following method can set the declared IP address setting on SSID WifiConfiguration:
public static void setIpAssignment(String assign , WifiConfiguration wifiConf)
throws SecurityException, IllegalArgumentException, NoSuchFieldException, IllegalAccessException{
setEnumField(wifiConf, assign, "ipAssignment");
}
public static void setIpAddress(InetAddress addr, int prefixLength, WifiConfiguration wifiConf)
throws SecurityException, IllegalArgumentException, NoSuchFieldException, IllegalAccessException,
NoSuchMethodException, ClassNotFoundException, InstantiationException, InvocationTargetException{
Object linkProperties = getField(wifiConf, "linkProperties");
if(linkProperties == null)return;
Class laClass = Class.forName("android.net.LinkAddress");
Constructor laConstructor = laClass.getConstructor(new Class[]{InetAddress.class, int.class});
Object linkAddress = laConstructor.newInstance(addr, prefixLength);
ArrayList mLinkAddresses = (ArrayList)getDeclaredField(linkProperties, "mLinkAddresses");
mLinkAddresses.clear();
mLinkAddresses.add(linkAddress);
}
public static void setGateway(InetAddress gateway, WifiConfiguration wifiConf)
throws SecurityException, IllegalArgumentException, NoSuchFieldException, IllegalAccessException,
ClassNotFoundException, NoSuchMethodException, InstantiationException, InvocationTargetException{
Object linkProperties = getField(wifiConf, "linkProperties");
if(linkProperties == null)return;
Class routeInfoClass = Class.forName("android.net.RouteInfo");
Constructor routeInfoConstructor = routeInfoClass.getConstructor(new Class[]{InetAddress.class});
Object routeInfo = routeInfoConstructor.newInstance(gateway);
ArrayList mRoutes = (ArrayList)getDeclaredField(linkProperties, "mRoutes");
mRoutes.clear();
mRoutes.add(routeInfo);
}
public static void setDNS(InetAddress dns, WifiConfiguration wifiConf)
throws SecurityException, IllegalArgumentException, NoSuchFieldException, IllegalAccessException{
Object linkProperties = getField(wifiConf, "linkProperties");
if(linkProperties == null)return;
ArrayList<InetAddress> mDnses = (ArrayList<InetAddress>)getDeclaredField(linkProperties, "mDnses");
mDnses.clear(); //or add a new dns address , here I just want to replace DNS1
mDnses.add(dns);
}
public static Object getField(Object obj, String name)
throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException{
Field f = obj.getClass().getField(name);
Object out = f.get(obj);
return out;
}
public static Object getDeclaredField(Object obj, String name)
throws SecurityException, NoSuchFieldException,
IllegalArgumentException, IllegalAccessException {
Field f = obj.getClass().getDeclaredField(name);
f.setAccessible(true);
Object out = f.get(obj);
return out;
}
private static void setEnumField(Object obj, String value, String name)
throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException{
Field f = obj.getClass().getField(name);
f.set(obj, Enum.valueOf((Class<Enum>) f.getType(), value));
}
在那之后,我可以为此SSID进行设置并更新WifiConfiguration
.
After that, I can set setting and update WifiConfiguration
for this SSID.
try{
setIpAssignment("STATIC", wifiConf); //or "DHCP" for dynamic setting
setIpAddress(InetAddress.getByName("192.168.0.100"), 24, wifiConf);
setGateway(InetAddress.getByName("4.4.4.4"), wifiConf);
setDNS(InetAddress.getByName("4.4.4.4"), wifiConf);
wifiManager.updateNetwork(wifiConf); //apply the setting
wifiManager.saveConfiguration(); //Save it
}catch(Exception e){
e.printStackTrace();
}
抱歉,我没有检查具有Android 4.x的silmilar UI的Android 3.x设备.
在Android 3.x中,网关存储在linkProperties
的mGateways
中.
mGateways
是类型InetAddress
的Arraylist
.因此,以下操作应在Android 3.x中起作用.
Sorry for I don't check for Android 3.x device that have silmilar UI with Android 4.x.
In Android 3.x, the gateway is storted in mGateways
of linkProperties
.
mGateways
is Arraylist
of type InetAddress
. Therefore, following should work in Android 3.x.
public static void setGateway(InetAddress gateway, WifiConfiguration wifiConf)
throws SecurityException, IllegalArgumentException, NoSuchFieldException, IllegalAccessException,
ClassNotFoundException, NoSuchMethodException, InstantiationException, InvocationTargetException{
Object linkProperties = getField(wifiConf, "linkProperties");
if(linkProperties == null)return;
ArrayList mGateways = (ArrayList)getDeclaredField(linkProperties, "mGateways");
mGateways.clear();
mGateways.add(gateway);
}
Edit2:方法setIpAddress
,setGateway
,setDNS
应该作为InetAddress
类型输入.
The methods setIpAddress
, setGateway
, setDNS
should be inputted as InetAddress
type.
这篇关于如何在Android 3.x或4.x上以编程方式配置静态IP地址,网络掩码,网关的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!