使用WifiManager设置静态IP配置时出现问题



我想更改设备上的DNS服务器。理想情况下,我想同时使用Wifi和3G/4G,但我看到移动网络带来了另一种复杂性,所以我从设置静态IP开始使用WifiManager。

代码似乎工作正常,但手机没有更改IP(查看设置->Wifi->ssid->IP地址),没有响应来自我的linux pc的ping(arp不完整),也没有显示在Wifi路由器中(dhcp配置到192.168.1.230)。

你认为我做错了什么?

是否有其他更改DNS服务器的方法(除了vpnsevices;))?

我使用下面的代码,主要来自杨在如何在Android 3.x或4.x 上以编程方式配置静态IP地址、网络掩码、网关

我使用的是安卓6.0

logcat输出:

11-01 09:45:17.167 12890-12890/com.narb.dns I/DNS: config:
* ID: 17 SSID: "Livebox-FB64" PROVIDER-NAME: null BSSID: any FQDN: null PRIO: 4777
numAssociation 72
validatedInternetAccess
KeyMgmt: WPA_PSK Protocols: WPA RSN WAPI
AuthAlgorithms:
PairwiseCiphers: TKIP CCMP SMS4
GroupCiphers: TKIP CCMP SMS4
PSK: *
Limited: 0
IP config:
IP assignment: STATIC
Static configuration: IP address 192.168.1.236/24 Gateway 192.168.1.1  DNS servers: [ 8.8.8.8 192.168.1.1 ] Domains
Proxy settings: NONE
autoJoinBSSID=any cuid=1000 cname=android.uid.system:1000 luid=1000 lname=android.uid.system:1000 lcuid=-1 userApproved=USER_APPROVED noInternetAccessExpected=false roamingFailureBlackListTimeMilli: 1000
triggeredLow: 0 triggeredBad: 0 triggeredNotHigh: 0
ticksLow: 0 ticksBad: 0 ticksNotHigh: 7
triggeredJoin: 0
autoJoinBailedDueToLowRssi: false
autoJoinUseAggressiveJoinAttemptThreshold: 0
11-01 09:45:17.237 12890-12965/com.narb.dns I/Adreno: QUALCOMM build                   : 8249e7b, Iacb76f3f7d
Build Date                       : 03/22/16
OpenGL ES Shader Compiler Version: XE031.06.00.05
Local Branch                     : 
Remote Branch                    : refs/tags/AU_LINUX_ANDROID_LA.BR.1.2.6_RB1.06.00.01.179.016
Remote Branch                    : NONE
Reconstruct Branch               : NOTHING
11-01 09:45:17.307 12890-12890/com.narb.dns W/art: Before Android 4.1, method int android.support.v7.widget.ListViewCompat.lookForSelectablePosition(int, boolean) would have incorrectly overridden the package-private method in android.widget.ListView

代码:我评论了manager.saveconfiguration,因为它被弃用了,文档说updatenetwork已经足够了(无论如何,我尝试了saveconfig,重新连接,关联-相同的结果)

package com.narb.dns;
import android.content.Context;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Context context = getApplicationContext();

WifiManager manager = (WifiManager)context.getSystemService(Context.WIFI_SERVICE);
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;
}
}
if (wifiConf != null)
{
try
{
setStaticIpConfiguration(manager, wifiConf,
InetAddress.getByName("192.168.1.236"), 24,
InetAddress.getByName("192.168.1.1"),
new InetAddress[] { InetAddress.getByName("8.8.8.8"),
InetAddress.getByName("192.168.1.1") });
Log.i("DNS","config:n"+wifiConf);
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
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.reassociate();
//   manager.saveConfiguration();
}
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);
}
}

清单:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.narb.dns">
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>

我发现必须将方法调用分开,等待成功响应后再调用下一个。这是牛轧糖。

callMethod(config, "setIpAssignment", new String[] { "android.net.IpConfiguration$IpAssignment" },
new Object[] { ipAssignment });
int updateNetworkResult = manager.updateNetwork(config);
if (updateNetworkResult == -1) return;
callMethod(config, "setStaticIpConfiguration", new String[] {
"android.net.StaticIpConfiguration" }, new Object[] { staticIpConfig });
manager.updateNetwork(config);

最新更新