【发布时间】:2018-04-13 13:30:32
【问题描述】:
我想更改我设备上的 DNS 服务器。理想情况下,我希望同时使用 Wifi 和 3G/4G,但我发现移动网络带来了另一个复杂性,因此我通过设置静态 IP 开始使用 WifiManager。
代码似乎工作正常,但手机没有更改 IP(查看设置->Wifi->ssid->ip 地址),不响应来自我的 linux pc 的 ping(arp 不完整)和未显示在 wifi 路由器中(dhcp 配置为 192.168.1.230)。
你认为我做错了什么?
它们是改变 DNS 服务器的其他方式吗(除了 vpnservices;))?
我正在使用下面的代码,主要来自 How to configue a static IP address, netmask, gateway programmatically on Android 3.x or 4.x 中的 Yeung
我使用的是 Android 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>
【问题讨论】:
-
你不能 - 重复你不能改变它,除非手机被植根。它是一个较旧的 API 版本
-
真的吗?我很惊讶,因为 1. 有一个 api - wifimanager 没有提到需要植根,2. 尽管被弃用,但它似乎仍然有效。你会怎么做?生根电话不是一种选择。商店里有几个 DNS 更改器应用程序,但它们似乎主要使用 vpnservices。
-
不可能 X 故事结束 X
标签: android dns wifi wifimanager static-ip-address