以编程方式在Android 5(L)上更改WiFi的配置 [英] Change WiFi's configuration on Android 5 (L) programmatically

查看:279
本文介绍了以编程方式在Android 5(L)上更改WiFi的配置的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Android 4.0.2..4.4.4上运行的代码存在一些问题,但在Android 5上并没有真正起作用,我不知道为什么。基本上,下面的代码允许设置新的WiFi的IP分配类型:STATIC或DHCP。我在下面的答案中详细介绍了我使用的代码: https://stackoverflow.com/a/10309323/876360

There're some problems with the code worked on android 4.0.2..4.4.4, but doesn't really work on Android 5 and I don't know why. Basically, the code below allows to set new WiFi's IP assignment type: STATIC or DHCP. The code I used is fully covered in this answer: https://stackoverflow.com/a/10309323/876360

我会尝试使用输出信息将最重要的代码放在这里。

I'll try to put here the most important pats of the code with the output info.

...
WifiConfigurator.setIpAssignment("STATIC", wifiConf);
...

其中wifiConf是

where wifiConf is

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

所以 WifiConfigurator.setIpAssigment()调用下一个代码:

public static void setIpAssignment(String assign, WifiConfiguration wifiConf)
        throws SecurityException, IllegalArgumentException, NoSuchFieldException, IllegalAccessException {

    setEnumField(wifiConf, assign, "ipAssignment");
}

public static void setEnumField(Object obj, String value, String name)
        throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
    Log.d("myApp", obj.getClass().toString());
    Field f = obj.getClass().getField(name);
    f.set(obj, Enum.valueOf((Class<Enum>) f.getType(), value));
}

但由于某种原因无法找到字段ipAssignment:

But for some reason the field "ipAssignment" cannot be found:

11-30 12:40:54.343    5941-5941/com.myApp D/myApp﹕ class android.net.wifi.WifiConfiguration
11-30 12:40:54.344    5941-5941/com.myApp D/myApp﹕ Can't update network configuration. java.lang.NoSuchFieldException: ipAssignment
            at java.lang.Class.getField(Class.java:1048)
            at com.myApp.WifiConfigurator.setEnumField(WifiConfigurator.java:141)
            at com.myApp.WifiConfigurator.setIpAssignment(WifiConfigurator.java:25)
            at com.myApp.WifiConfigurator.updateWifiNetwork(WifiConfigurator.java:220)
            at com.myApp.ui.MainScreen.onAsyncTaskCompleted(MainScreen.java:251)
            at com.myApp.myAPI$UpdateIPTask.onPostExecute(myAPI.java:257)
            at com.myApp.myAPI$UpdateIPTask.onPostExecute(myAPI.java:194)
            at android.os.AsyncTask.finish(AsyncTask.java:632)
            at android.os.AsyncTask.access$600(AsyncTask.java:177)
            at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:645)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:135)
            at android.app.ActivityThread.main(ActivityThread.java:5221)
            at java.lang.reflect.Method.invoke(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:372)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)

起初,我认为谷歌改变了该字段的名称。然后我检查了 Android L预览源代码,该字段就在那里。我很困惑为什么会发生这种情况。

At first, I thought google changed the field's name. Then I checked the Android L preview source code, the field is there. I'm confused why this is happening.

更新

感谢Matiash对于某些输入,我能够更新ipAssignment类型,但我无法更新DNS。要更新DNS,ipAssigment应该是静态的。根据,Google停止使用LinkProperties进行静态配置,他们现在使用StaticIpConfiguration类。

Thanks to Matiash for some input, I am able to update ipAssignment type, but I'm not able to update DNSes. To update DNSes the ipAssigment should be static. According to this Google stopped using LinkProperties for static configuration, they use StaticIpConfiguration class now.

所以我做的是:

public static void setDNS(InetAddress dns1, InetAddress dns2, WifiConfiguration wifiConf)
        throws SecurityException, IllegalArgumentException, NoSuchMethodException, InvocationTargetException,
        NoSuchFieldException, IllegalAccessException {

    Object linkProperties = null;
    ArrayList<InetAddress> mDnses;

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        staticIpConf = wifiConf.getClass().getMethod("getStaticIpConfiguration").invoke(wifiConf);
        mDnses = (ArrayList<InetAddress>) getDeclaredField(staticIpConf, "dnsServers");
    }
    else{
        linkProperties = getField(wifiConf, "linkProperties");
        mDnses = (ArrayList<InetAddress>) getDeclaredField(linkProperties, "mDnses");
    }

    mDnses.clear();
    mDnses.add(dns1);
    mDnses.add(dns2);
}
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;
}

我在错误日志中看到的下一个:

The next I see in error log:

12-22 09:00:49.854  25815-25815/com.myapp D/myapp﹕ Can't update network configuration. java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String java.lang.Object.toString()' on a null object reference
            at com.myapp.WifiConfigurator.getDeclaredField(WifiConfigurator.java:245)
            at com.myapp.WifiConfigurator.setDNS(WifiConfigurator.java:78)
            at com.myapp.WifiConfigurator.updateWifiNetwork(WifiConfigurator.java:356)

我的猜测是 staticIpConfiguration 在我调用它时不存在。我必须以某种方式初始化它。
如何更新DNS的任何想法?

My guess is staticIpConfiguration doesn't exists when I call it. I have to initialize it somehow. Any ideas how to update DNSes?

推荐答案

虽然 ipAssignment 字段仍然存在于L预览中(至少是grepcode中的版本),它不在发布的版本中,您可以在master分支源代码 Github镜像

Although the ipAssignment field was still present in the L preview (at least the version in grepcode), it's not in the released version, as you can see in the "master" branch of the source code or in the Github mirror.

Enum定义和字段现在都在一个内部对象中,类型为 IpConfiguration (也是新的)。这些是使用反射来访问未记录的水域的危险......:)

Both the Enum definition and the field are now inside an inner object, of type IpConfiguration (also new). These are the dangers of using reflection to access undocumented waters... :)

然而,调整代码以通过反射访问它并将其设置在那里很简单:

However, it's simple to tweak the code to access it by reflection and set it there:

public static void setIpAssignment(String assign, WifiConfiguration wifiConf)
        throws SecurityException, IllegalArgumentException, NoSuchFieldException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        Object ipConfiguration = wifiConf.getClass().getMethod("getIpConfiguration").invoke(wifiConf);
        setEnumField(ipConfiguration, assign, "ipAssignment");
    } else {
        setEnumField(wifiConf, assign, "ipAssignment");
    }
}

此代码有效(从某种意义上说)不会抛出异常)但我还没有进一步测试过。

This code "works" (in the sense that it does not throw an exception) but I haven't tested it any further.

参见如何在Android 5.x(Lollipop)上以编程方式配置静态IP地址,网络掩码,网关,DNS以进行Wi-Fi连接详细解决方案。

See How to configure a static IP address, netmask, gateway, DNS programmatically on Android 5.x (Lollipop) for Wi-Fi connection for a more detailed solution.

这篇关于以编程方式在Android 5(L)上更改WiFi的配置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆