【问题标题】:How to configure a static IP address, netmask, gateway, DNS programmatically on Android 5.x (Lollipop) for Wi-Fi connection如何在 Android 5.x (Lollipop) 上以编程方式配置静态 IP 地址、网络掩码、网关、DNS 以进行 Wi-Fi 连接
【发布时间】:2015-02-20 08:49:44
【问题描述】:

如何在 Android 5.x 上以编程方式配置静态 IP 地址、网络掩码、网关、DNS 以实现 Wi-Fi 连接?是否有开放的 API(没有找到)或隐藏的可以用于此?如果可能的话,请您举一些例子。

我知道它是 possible on Android 4.0+,但它不适用于 Android 5.0

【问题讨论】:

    标签: java android android-5.0-lollipop


    【解决方案1】:

    遗憾的是,仍然没有开放的 API。

    Android 4.0 的解决方案在 LOLLIPOP 中不起作用,因为事情已经转移了。特别是新的IpConfiguration 类现在包含StaticIpConfiguration 和所有这些字段。它们仍然可以通过像这样使用反射(具有所有的脆弱性)来访问。

    警告,此代码仅适用于 Android 5.0。您需要检查Build.VERSION.SDK_INT 并采取相应措施。

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

    使用以下辅助方法来处理反射:

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

    例如,你可以这样称呼它:

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

    作为参考,您可能需要查看框架中的 WifiConfigController 类(尽管它直接使用这些类而不是通过反射)。

    【讨论】:

    • 太棒了,测试了你的代码,它可以工作了!你是最棒的:)
    • 这也是我如何反映隐藏的 android 类的一个很好的例子。
    • 我知道这是另一个问题,但 100% 与主题相关:如何获取当前工作的 DNS 的 ID 地址?
    • @KennyPowers 很高兴能帮上忙。 :)
    • 您的代码在第一次尝试时完美运行,我只需要检查 Build.VERSION.SDK_INT > 20 (21+),正如您最初指出的那样。感谢分享!
    【解决方案2】:

    IP 地址是在接口而不是电话基础上配置的。您不能设置一个 IP 地址用于蜂窝数据连接,以及可能创建的所有无线(蓝牙等)连接。

    由于IP地址依赖于接口,所以地址也是在那里配置的。

    对于数据连接,IP 地址(我相信,未确认)由蜂窝运营商传送到手机,并且无法在设备上配置。

    对于常规 wi-fi 类型的连接,对于每个网络,您可以选择使用默认 (DHCP) 或其他形式的 IP 地址配置,包括您是要手动配置 IP 地址,还是通过动态系统配置 IP 地址到位。

    由于网关和网络掩码也在网络上设置,因此为给定网络配置“静态”IP 地址的“最佳”方法是在网络端进行配置。对于大多数网络 DHCP 服务器,您可以将它们配置为始终为同一设备提供相同的网络 IP。

    这就是我所做的,我有某些设备通过 DHCP 获取它们的 IP 地址,但是 DHCP 服务器总是为我想要恒定的设备分配相同的预配置和“静态”IP 地址(其他设备拉 IP来自可用的“池”)。

    【讨论】:

    • 我必须更具体一点,我想要将 IP 分配从 DHCP 更改为 STATIC(我知道如何使用隐藏的 android 类的反射来做到这一点),更改网关、dnses 和 IP。我现在会更新我的问题。
    猜你喜欢
    • 2012-05-03
    • 2019-10-07
    • 2012-02-07
    • 1970-01-01
    • 2012-01-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多