Android7.1.2修改以太网静态设置

如何设置以太网有线网络静态配置

从源码看设置以太网配置调用的是EthernetManager的setConfiguration方法,在这里插入图片描述
所以我们就只需要创建IpConfiguration这个实例,他的构造方法传入值是
在这里插入图片描述
最终配置的参数就是StaticIpConfiguration这个类来配置ipAddress,gateway,dnsServers这三个值
在这里插入图片描述
涉及的类主要有,但这些都是隐藏的apk无法调用,只能通过反射进行调用,但前提是你的apk是系统apk,不然没有权限。

    private static final String ClassName_EthernetManager = "android.net.EthernetManager";
    private static final String ClassName_StaticIpConfiguration = "android.net.StaticIpConfiguration";
    private static final String ClassName_IpConfiguration = "android.net.IpConfiguration";
    private static final String ClassName_IpAssignment = "android.net.IpConfiguration$IpAssignment";
    private static final String ClassName_ProxySettings = "android.net.IpConfiguration$ProxySettings";
    private static final String ClassName_ProxyInfo = "android.net.ProxyInfo";

通过反射设置以太网静态配置的值

import android.content.Context;
import android.net.LinkAddress;
import android.util.Log;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.List;
import com.das.function.reflection.ReflectionFunctions;

public class EthernetFunctions extends ReflectionFunctions{
    private static final String ClassName_EthernetManager = "android.net.EthernetManager";
    private static final String ClassName_StaticIpConfiguration = "android.net.StaticIpConfiguration";
    private static final String ClassName_IpConfiguration = "android.net.IpConfiguration";
    private static final String ClassName_IpAssignment = "android.net.IpConfiguration$IpAssignment";
    private static final String ClassName_ProxySettings = "android.net.IpConfiguration$ProxySettings";
    private static final String ClassName_ProxyInfo = "android.net.ProxyInfo";
    EthernetFunctions(Context context) {
        super(context);
        //设置信息
    }

    public void updateEthDevInfo(boolean dhcp, String ip, String gatewayConfig, String subnetmask, String[] dns) {
        //获取EthernetManager
        try {
            final Class<?> classEthernetManager = getClass(ClassName_EthernetManager);//获取EthernetManager
            Object IEthernetManager = getSystemServiceInstance("ethernet");//获取EthernetManager实例
            Method MSetEthEnabled = getMethod(classEthernetManager, "isAvailable");
            //获取StaticIpConfiguration
            final Class<?> classStaticIpConfiguration = getClass(ClassName_StaticIpConfiguration);

            Object IStaticIpConfiguration = getNewInstance(classStaticIpConfiguration);

            Field ipAddress = getField(classStaticIpConfiguration, "ipAddress"); //获取ipAddress
            Field gateway = getField(classStaticIpConfiguration, "gateway"); //获取gateway
            Field dnsServers = getField(classStaticIpConfiguration, "dnsServers"); //获取dnsServers

            Class clazz = null;

            clazz = Class.forName("android.net.LinkAddress");

            Class[] cl = new Class[]{InetAddress.class, int.class};
            Constructor cons = null;


            cons = clazz.getConstructor(cl);

            InetAddress ipAddressValue = InetAddress.getByName("192.168.249.5");
            Object[] x = {ipAddressValue, 16};
            setField(IStaticIpConfiguration, ipAddress, (LinkAddress) cons.newInstance(x));  //ipAddress赋值

            InetAddress gatewayValue = InetAddress.getByName("192.168.249.2");
            setField(IStaticIpConfiguration, gateway, gatewayValue);  //gateway赋值

            InetAddress dnsServersValue1 = InetAddress.getByName("192.168.249.3"); //dns1
            InetAddress dnsServersValue2 = InetAddress.getByName("192.168.249.4"); //dns2
            List<InetAddress> dnsValues = new ArrayList<>();
            dnsValues.add(dnsServersValue1);
            dnsValues.add(dnsServersValue2);

            setField(IStaticIpConfiguration, dnsServers, dnsValues);  //dnsServers赋值
            Method MToString = getMethod(classStaticIpConfiguration, "toString");
            Log.i("MSetIfName", "EthernetFunctions: " + MToString.invoke(IStaticIpConfiguration));

            //获取IpConfiguration

            final Class<?> classIpConfiguration = getClass(ClassName_IpConfiguration);
            final Class<?> classIpAssignment = getClass(ClassName_IpAssignment);
            final Class<?> classProxySettings = getClass(ClassName_ProxySettings);
            final Class<?> classProxyInfo = getClass(ClassName_ProxyInfo);

            Object[] assignments = classIpAssignment.getEnumConstants();  //获取枚举值
            Object[] proxySettings = classProxySettings.getEnumConstants(); //获取枚举值

            Constructor constructor = classIpConfiguration.getConstructor(classIpAssignment, classProxySettings, classStaticIpConfiguration, classProxyInfo);
            Object IIpConfiguration = constructor.newInstance(assignments[0], proxySettings[1], IStaticIpConfiguration, null);
            Method MSetConfiguration = getMethod(classEthernetManager, "setConfiguration",classIpConfiguration);


            invokeMethod(MSetConfiguration, IEthernetManager, IIpConfiguration);//设置值


        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

反射工具类

import android.content.Context;
import android.util.Log;

import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class ReflectionFunctions {

    public static Process ExecRuntimeCommand(String command) {
        try {
            return Runtime.getRuntime().exec(command);
        } catch (IOException e) {
            Log.e("execRuntimeCommand", e.getMessage());
        }
        return null;
    }

    public static Process ExecRuntimeSUCommand(String command) {
        try {
            return Runtime.getRuntime().exec(new String[]{"su", "-c", command});
        } catch (IOException e) {
            Log.e("execRuntimeCommand", e.getMessage());
        }
        return null;
    }

    private Context context;

    public static Boolean TRUE = Boolean.TRUE;
    public static Boolean FALSE = Boolean.FALSE;
    public static Class<?> BOOLEAN = Boolean.TYPE;
    public static Class<?> CHAR = char.class;
    public static Class<?> INT = int.class;
    public static Class<?> SHORT = short.class;
    public static Class<?> LONG = long.class;
    public static Class<?> FLOAT = float.class;
    public static Class<?> DOUBLE = double.class;
    public static Class<?> BYTE = byte.class;
    public static Class<?> STRING = String.class;

    public ReflectionFunctions(Context context) {
        this.context = context;
    }

    public Context getContext() {
        return context;
    }

    protected Process execRuntimeCommand(String command) {
        return ReflectionFunctions.ExecRuntimeCommand(command);
    }

    protected Process execRuntimeSUCommand(String command) {
        return ReflectionFunctions.ExecRuntimeSUCommand(command);
    }

    protected Class<?> getClass(String className) throws ClassNotFoundException {
        return Class.forName(className);
    }

    protected Object getNewInstance(Class<?> classType) throws IllegalAccessException, InstantiationException {
        return classType.newInstance();
    }

    protected Object getSystemServiceInstance(String name) {
        return getContext().getSystemService(name);
    }

    protected Method getMethod(String className, String methodName, Class<?>... params) throws ClassNotFoundException, NoSuchMethodException {
        return getMethod(getClass(className), methodName, params);
    }

    protected Method getMethod(Class<?> classType, String methodName, Class<?>... params) throws NoSuchMethodException {
        return classType.getMethod(methodName, params);
    }

    protected Field getField(Class<?> classType,String fieldName) throws NoSuchFieldException {
        return classType.getField(fieldName);
    }

    protected void setField(Object classInstance,Field field,Object value) throws NoSuchFieldException, IllegalAccessException {
        field.setAccessible(true);
        field.set(classInstance,value);
    }

    protected Object invokeMethod(Method method, Object classInstance, Object... methodParams) throws InvocationTargetException, IllegalAccessException {
        try {
            return method.invoke(classInstance, methodParams);
        } catch (SecurityException e) {
            new ReflectionException("", e).printStackTrace();
            method.setAccessible(true);
            return invokeMethod(method, classInstance, methodParams);
        }
    }

    private static class ReflectionException extends RuntimeException {
        private ReflectionException(String message, Exception exception) {
            super(message, exception);
        }
    }

附主要类源码

/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.net;

import android.content.Context;
import android.net.IEthernetManager;
import android.net.IEthernetServiceListener;
import android.net.IpConfiguration;
import android.os.Handler;
import android.os.Message;
import android.os.RemoteException;

import java.util.ArrayList;

/**
 * A class representing the IP configuration of the Ethernet network.
 *
 * @hide
 */
public class EthernetManager {
    private static final String TAG = "EthernetManager";
    private static final int MSG_AVAILABILITY_CHANGED = 1000;

    private final Context mContext;
    private final IEthernetManager mService;
    private final Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            if (msg.what == MSG_AVAILABILITY_CHANGED) {
                boolean isAvailable = (msg.arg1 == 1);
                for (Listener listener : mListeners) {
                    listener.onAvailabilityChanged(isAvailable);
                }
            }
        }
    };
    private final ArrayList<Listener> mListeners = new ArrayList<Listener>();
    private final IEthernetServiceListener.Stub mServiceListener =
            new IEthernetServiceListener.Stub() {
                @Override
                public void onAvailabilityChanged(boolean isAvailable) {
                    mHandler.obtainMessage(
                            MSG_AVAILABILITY_CHANGED, isAvailable ? 1 : 0, 0, null).sendToTarget();
                }
            };

    /**
     * A listener interface to receive notification on changes in Ethernet.
     */
    public interface Listener {
        /**
         * Called when Ethernet port's availability is changed.
         * @param isAvailable {@code true} if one or more Ethernet port exists.
         */
        public void onAvailabilityChanged(boolean isAvailable);
    }

    /**
     * Create a new EthernetManager instance.
     * Applications will almost always want to use
     * {@link android.content.Context#getSystemService Context.getSystemService()} to retrieve
     * the standard {@link android.content.Context#ETHERNET_SERVICE Context.ETHERNET_SERVICE}.
     */
    public EthernetManager(Context context, IEthernetManager service) {
        mContext = context;
        mService = service;
    }

    /**
     * Get Ethernet configuration.
     * @return the Ethernet Configuration, contained in {@link IpConfiguration}.
     */
    public IpConfiguration getConfiguration() {
        try {
            return mService.getConfiguration();
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Set Ethernet configuration.
     */
    public void setConfiguration(IpConfiguration config) {
        try {
            mService.setConfiguration(config);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Indicates whether the system currently has one or more
     * Ethernet interfaces.
     */
    public boolean isAvailable() {
        try {
            return mService.isAvailable();
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Adds a listener.
     * @param listener A {@link Listener} to add.
     * @throws IllegalArgumentException If the listener is null.
     */
    public void addListener(Listener listener) {
        if (listener == null) {
            throw new IllegalArgumentException("listener must not be null");
        }
        mListeners.add(listener);
        if (mListeners.size() == 1) {
            try {
                mService.addListener(mServiceListener);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }
    }

    /**
     * Removes a listener.
     * @param listener A {@link Listener} to remove.
     * @throws IllegalArgumentException If the listener is null.
     */
    public void removeListener(Listener listener) {
        if (listener == null) {
            throw new IllegalArgumentException("listener must not be null");
        }
        mListeners.remove(listener);
        if (mListeners.isEmpty()) {
            try {
                mService.removeListener(mServiceListener);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }
    }
}

/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.net;

import android.net.StaticIpConfiguration;
import android.os.Parcel;
import android.os.Parcelable;

import java.util.Objects;

/**
 * A class representing a configured network.
 * @hide
 */
public class IpConfiguration implements Parcelable {
    private static final String TAG = "IpConfiguration";

    public enum IpAssignment {
        /* Use statically configured IP settings. Configuration can be accessed
         * with staticIpConfiguration */
        STATIC,
        /* Use dynamically configured IP settigns */
        DHCP,
        /* no IP details are assigned, this is used to indicate
         * that any existing IP settings should be retained */
        UNASSIGNED
    }

    public IpAssignment ipAssignment;

    public StaticIpConfiguration staticIpConfiguration;

    public enum ProxySettings {
        /* No proxy is to be used. Any existing proxy settings
         * should be cleared. */
        NONE,
        /* Use statically configured proxy. Configuration can be accessed
         * with httpProxy. */
        STATIC,
        /* no proxy details are assigned, this is used to indicate
         * that any existing proxy settings should be retained */
        UNASSIGNED,
        /* Use a Pac based proxy.
         */
        PAC
    }

    public ProxySettings proxySettings;

    public ProxyInfo httpProxy;

    private void init(IpAssignment ipAssignment,
                      ProxySettings proxySettings,
                      StaticIpConfiguration staticIpConfiguration,
                      ProxyInfo httpProxy) {
        this.ipAssignment = ipAssignment;
        this.proxySettings = proxySettings;
        this.staticIpConfiguration = (staticIpConfiguration == null) ?
                null : new StaticIpConfiguration(staticIpConfiguration);
        this.httpProxy = (httpProxy == null) ?
                null : new ProxyInfo(httpProxy);
    }

    public IpConfiguration() {
        init(IpAssignment.UNASSIGNED, ProxySettings.UNASSIGNED, null, null);
    }

    public IpConfiguration(IpAssignment ipAssignment,
                           ProxySettings proxySettings,
                           StaticIpConfiguration staticIpConfiguration,
                           ProxyInfo httpProxy) {
        init(ipAssignment, proxySettings, staticIpConfiguration, httpProxy);
    }

    public IpConfiguration(IpConfiguration source) {
        this();
        if (source != null) {
            init(source.ipAssignment, source.proxySettings,
                 source.staticIpConfiguration, source.httpProxy);
        }
    }

    public IpAssignment getIpAssignment() {
        return ipAssignment;
    }

    public void setIpAssignment(IpAssignment ipAssignment) {
        this.ipAssignment = ipAssignment;
    }

    public StaticIpConfiguration getStaticIpConfiguration() {
        return staticIpConfiguration;
    }

    public void setStaticIpConfiguration(StaticIpConfiguration staticIpConfiguration) {
        this.staticIpConfiguration = staticIpConfiguration;
    }

    public ProxySettings getProxySettings() {
        return proxySettings;
    }

    public void setProxySettings(ProxySettings proxySettings) {
        this.proxySettings = proxySettings;
    }

    public ProxyInfo getHttpProxy() {
        return httpProxy;
    }

    public void setHttpProxy(ProxyInfo httpProxy) {
        this.httpProxy = httpProxy;
    }

    @Override
    public String toString() {
        StringBuilder sbuf = new StringBuilder();
        sbuf.append("IP assignment: " + ipAssignment.toString());
        sbuf.append("\n");
        if (staticIpConfiguration != null) {
            sbuf.append("Static configuration: " + staticIpConfiguration.toString());
            sbuf.append("\n");
        }
        sbuf.append("Proxy settings: " + proxySettings.toString());
        sbuf.append("\n");
        if (httpProxy != null) {
            sbuf.append("HTTP proxy: " + httpProxy.toString());
            sbuf.append("\n");
        }

        return sbuf.toString();
    }

    @Override
    public boolean equals(Object o) {
        if (o == this) {
            return true;
        }

        if (!(o instanceof IpConfiguration)) {
            return false;
        }

        IpConfiguration other = (IpConfiguration) o;
        return this.ipAssignment == other.ipAssignment &&
                this.proxySettings == other.proxySettings &&
                Objects.equals(this.staticIpConfiguration, other.staticIpConfiguration) &&
                Objects.equals(this.httpProxy, other.httpProxy);
    }

    @Override
    public int hashCode() {
        return 13 + (staticIpConfiguration != null ? staticIpConfiguration.hashCode() : 0) +
               17 * ipAssignment.ordinal() +
               47 * proxySettings.ordinal() +
               83 * httpProxy.hashCode();
    }

    /** Implement the Parcelable interface */
    public int describeContents() {
        return 0;
    }

    /** Implement the Parcelable interface  */
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(ipAssignment.name());
        dest.writeString(proxySettings.name());
        dest.writeParcelable(staticIpConfiguration, flags);
        dest.writeParcelable(httpProxy, flags);
    }

    /** Implement the Parcelable interface */
    public static final Creator<IpConfiguration> CREATOR =
        new Creator<IpConfiguration>() {
            public IpConfiguration createFromParcel(Parcel in) {
                IpConfiguration config = new IpConfiguration();
                config.ipAssignment = IpAssignment.valueOf(in.readString());
                config.proxySettings = ProxySettings.valueOf(in.readString());
                config.staticIpConfiguration = in.readParcelable(null);
                config.httpProxy = in.readParcelable(null);
                return config;
            }

            public IpConfiguration[] newArray(int size) {
                return new IpConfiguration[size];
            }
        };
}

/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.net;

import android.net.LinkAddress;
import android.os.Parcelable;
import android.os.Parcel;

import java.net.InetAddress;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * Class that describes static IP configuration.
 *
 * This class is different from LinkProperties because it represents
 * configuration intent. The general contract is that if we can represent
 * a configuration here, then we should be able to configure it on a network.
 * The intent is that it closely match the UI we have for configuring networks.
 *
 * In contrast, LinkProperties represents current state. It is much more
 * expressive. For example, it supports multiple IP addresses, multiple routes,
 * stacked interfaces, and so on. Because LinkProperties is so expressive,
 * using it to represent configuration intent as well as current state causes
 * problems. For example, we could unknowingly save a configuration that we are
 * not in fact capable of applying, or we could save a configuration that the
 * UI cannot display, which has the potential for malicious code to hide
 * hostile or unexpected configuration from the user: see, for example,
 * http://b/12663469 and http://b/16893413 .
 *
 * @hide
 */
public class StaticIpConfiguration implements Parcelable {
    public LinkAddress ipAddress;
    public InetAddress gateway;
    public final ArrayList<InetAddress> dnsServers;
    public String domains;

    public StaticIpConfiguration() {
        dnsServers = new ArrayList<InetAddress>();
    }

    public StaticIpConfiguration(StaticIpConfiguration source) {
        this();
        if (source != null) {
            // All of these except dnsServers are immutable, so no need to make copies.
            ipAddress = source.ipAddress;
            gateway = source.gateway;
            dnsServers.addAll(source.dnsServers);
            domains = source.domains;
        }
    }

    public void clear() {
        ipAddress = null;
        gateway = null;
        dnsServers.clear();
        domains = null;
    }

    /**
     * Returns the network routes specified by this object. Will typically include a
     * directly-connected route for the IP address's local subnet and a default route. If the
     * default gateway is not covered by the directly-connected route, it will also contain a host
     * route to the gateway as well. This configuration is arguably invalid, but it used to work
     * in K and earlier, and other OSes appear to accept it.
     */
    public List<RouteInfo> getRoutes(String iface) {
        List<RouteInfo> routes = new ArrayList<RouteInfo>(3);
        if (ipAddress != null) {
            RouteInfo connectedRoute = new RouteInfo(ipAddress, null, iface);
            routes.add(connectedRoute);
            if (gateway != null && !connectedRoute.matches(gateway)) {
                routes.add(RouteInfo.makeHostRoute(gateway, iface));
            }
        }
        if (gateway != null) {
            routes.add(new RouteInfo((IpPrefix) null, gateway, iface));
        }
        return routes;
    }

    /**
     * Returns a LinkProperties object expressing the data in this object. Note that the information
     * contained in the LinkProperties will not be a complete picture of the link's configuration,
     * because any configuration information that is obtained dynamically by the network (e.g.,
     * IPv6 configuration) will not be included.
     */
    public LinkProperties toLinkProperties(String iface) {
        LinkProperties lp = new LinkProperties();
        lp.setInterfaceName(iface);
        if (ipAddress != null) {
            lp.addLinkAddress(ipAddress);
        }
        for (RouteInfo route : getRoutes(iface)) {
            lp.addRoute(route);
        }
        for (InetAddress dns : dnsServers) {
            lp.addDnsServer(dns);
        }
        lp.setDomains(domains);
        return lp;
    }

    public String toString() {
        StringBuffer str = new StringBuffer();

        str.append("IP address ");
        if (ipAddress != null ) str.append(ipAddress).append(" ");

        str.append("Gateway ");
        if (gateway != null) str.append(gateway.getHostAddress()).append(" ");

        str.append(" DNS servers: [");
        for (InetAddress dnsServer : dnsServers) {
            str.append(" ").append(dnsServer.getHostAddress());
        }

        str.append(" ] Domains ");
        if (domains != null) str.append(domains);
        return str.toString();
    }

    public int hashCode() {
        int result = 13;
        result = 47 * result + (ipAddress == null ? 0 : ipAddress.hashCode());
        result = 47 * result + (gateway == null ? 0 : gateway.hashCode());
        result = 47 * result + (domains == null ? 0 : domains.hashCode());
        result = 47 * result + dnsServers.hashCode();
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;

        if (!(obj instanceof StaticIpConfiguration)) return false;

        StaticIpConfiguration other = (StaticIpConfiguration) obj;

        return other != null &&
                Objects.equals(ipAddress, other.ipAddress) &&
                Objects.equals(gateway, other.gateway) &&
                dnsServers.equals(other.dnsServers) &&
                Objects.equals(domains, other.domains);
    }

    /** Implement the Parcelable interface */
    public static Creator<StaticIpConfiguration> CREATOR =
        new Creator<StaticIpConfiguration>() {
            public StaticIpConfiguration createFromParcel(Parcel in) {
                StaticIpConfiguration s = new StaticIpConfiguration();
                readFromParcel(s, in);
                return s;
            }

            public StaticIpConfiguration[] newArray(int size) {
                return new StaticIpConfiguration[size];
            }
        };

    /** Implement the Parcelable interface */
    public int describeContents() {
        return 0;
    }

    /** Implement the Parcelable interface */
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeParcelable(ipAddress, flags);
        NetworkUtils.parcelInetAddress(dest, gateway, flags);
        dest.writeInt(dnsServers.size());
        for (InetAddress dnsServer : dnsServers) {
            NetworkUtils.parcelInetAddress(dest, dnsServer, flags);
        }
        dest.writeString(domains);
    }

    protected static void readFromParcel(StaticIpConfiguration s, Parcel in) {
        s.ipAddress = in.readParcelable(null);
        s.gateway = NetworkUtils.unparcelInetAddress(in);
        s.dnsServers.clear();
        int size = in.readInt();
        for (int i = 0; i < size; i++) {
            s.dnsServers.add(NetworkUtils.unparcelInetAddress(in));
        }
        s.domains = in.readString();
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android 7.1.2(也被称为Nougat)是Android操作系统的一个版本,它的源代码是公开可用的。源码包含了构建和运行Android操作系统所需的所有代码文件和资源。 Android操作系统是一个基于Linux内核的开源平台,用于移动设备和嵌入式系统。它提供了一个统一的操作系统环境,使开发者能够轻松地构建和定制自己的Android设备。 Android 7.1.2源码提供了一套开发工具和框架,使开发者能够创建功能丰富、稳定和安全的应用程序。该版本中引入了一些新的功能和改进,例如通知栏的增强、多任务处理的改进、Doze模式的优化等,以提供更好的用户体验。 通过查看源代码,开发者可以深入了解Android操作系统的内部工作原理,并理解其中的各个组件和模块是如何相互协作的。例如,开发者可以研究Android的用户界面框架、应用程序生命周期管理、通信和存储机制等。 修复和优化Android 7.1.2源码也是可能的,因为它是开源的。开发者可以根据自己的需求和想法对操作系统进行修改,并参与到Android社区中,与其他开发者分享和贡献代码。 总之,Android 7.1.2源码为开发者提供了一个定制和构建Android应用的平台。通过深入了解源码,开发者能够创建出更加出色和创新的应用程序,同时也有机会参与到Android开源社区中,为整个生态系统的发展做出贡献。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值