Android 系统中新增广播提供给应用设置静态ip

Posted by 陈宇瀚 on March 9, 2020

系统中新增静态ip设置

本文主要目的是开发提供给应用开发使用修改连接Wifi或以太网时的静态ip设置,采用广播的方式控制,在Setting是内同实现时仿照Settings应用内部的修改方式实现。
新增两个广播:
1.com.cyh.wifi_static_ip:wifi静态ip设置广播 2.com.cyh.eth_static_ip:以太网静态ip设置广播 在Settings内新增一个广播接收NetworkStaticReceiver.java

AndroidManifest.xml

AndroidManifest.xml文件内添加上我们新增的NetworkStaticReceiver和相关广播

1
2
3
4
5
6
 <receiver android:name="NetworkStaticReceiver">
            <intent-filter android:priority="1000">
                <action android:name="com.cyh.wifi_static_ip"/>
                <action android:name="com.cyh.eth_static_ip" />
            </intent-filter>
       </receiver>

之后来看NetworkStaticReceiver.java文件的内容

NetworkStaticReceiver.java

路径:packages/apps/Settings/src/com/android/settings/NetworkStaticReceiver.java,只发逻辑部分,省略了import部分。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
public class NetworkStaticReceiver extends BroadcastReceiver{
     private final String WIFI_STATIC_IP = "com.cyh.wifi_static_ip";
     private final String ETH_STATIC_IP = "com.cyh.eth_static_ip";
     private final String TAG="NetworkStaticReceiver";
     
     @Override
        public void onReceive(Context context, Intent intent){
                String action = intent.getAction();
                switch(action){
                    if(WIFI_STATIC_IP.equals(action)){
                //Wi-Fi静态设置
                 //获得是否设置为静态模式
                        boolean isStatic =  intent.getBooleanExtra("Static",false);
                        //获取连接wifi的config
                        WifiManager mWifiManager = (WifiManager)context.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
                        WifiConfiguration config = new WifiConfiguration();
                        WifiInfo connectionInfo= mWifiManager.getConnectionInfo();
                                List<WifiConfiguration> configuredNetworks=mWifiManager.getConfiguredNetworks();
                                for (WifiConfiguration conf : configuredNetworks) {
                                        if (conf.networkId==connectionInfo.getNetworkId()) {
                                                config=conf;
                                                break;
                                        }
                                }
                        if(isStatic){
                                 //获得设置的Wi-Fi静态ip,网关,DNS1,DNS2
                                String ip = intent.getStringExtra("staticIp");
                                String gateway = intent.getStringExtra("gateway");
                                String dns1 = intent.getStringExtra("dns1");
                                String dns2 = intent.getStringExtra("dns2");
                                //判断传入参数是否为空,空的话给默认值
                                ip = ip ==null?"192.168.0.123":ip;
                                gateway = gateway ==null?"192.168.1.1":gateway;
                                dns1 = dns1 ==null?"8.8.8.8":dns1;
                                dns2 = dns2 ==null?"8.8.4,4":dns2;
                                //validateIpConfigFields用于验证ip,网管,dns1,dns2,并将相关设置项转换成StaticIpConfiguration
                                StaticIpConfiguration mStaticIpConfiguration = validateIpConfigFields(ip,gateway,dns1,dns2);
                               
                               if(mStaticIpConfiguration == null){
                                        //设置相关内容有问题时mStaticIpConfiguration会为null
                                        return;
                                }
                                config.setStaticIpConfiguration(mStaticIpConfiguration);
                                mWifiManager.updateNetwork(config);
                                boolean saveConfiguration = mWifiManager.saveConfiguration();

                                int netId = mWifiManager.addNetwork(config);
                                //断开网络
                                mWifiManager.disableNetwork(netId);
                                //重新连接
                                mWifiManager.enableNetwork(netId, true);
                        }else{
                                //动态IP模式(DHCP)
                                config.setIpAssignment(IpAssignment.DHCP);
                                mWifiManager.updateNetwork(config);
                                mWifiManager.saveConfiguration();
                                int netId = mWifiManager.addNetwork(config);
                                //断开网络
                                mWifiManager.disableNetwork(netId);
                                //重新连接
                                mWifiManager.enableNetwork(netId, true);
                        }
                } else if(ETH_STATIC_IP.equals(action)){
                        //获得是否设置为静态模式
                        boolean isStatic =  intent.getBooleanExtra("Static",false);
                        Log.i(TAG,"ETH_STATIC_IP isStatic:"+isStatic);
                        EthernetManager mEthManager = (EthernetManager)context.getApplicationContext().getSystemService(Context.ETHERNET_SERVICE);
                        if(isStatic){
                                String ip = intent.getStringExtra("staticIp");
                                String gateway = intent.getStringExtra("gateway");
                                String dns1 = intent.getStringExtra("dns1");
                                String dns2 = intent.getStringExtra("dns2");
                                //判断传入参数是否为空,空的话给默认值
                                ip = ip ==null?"192.168.0.123":ip;
                                gateway = gateway ==null?"192.168.1.1":gateway;
                                dns1 = dns1 ==null?"8.8.8.8":dns1;
                                dns2 = dns2 ==null?"8.8.4,4":dns2;
                                StaticIpConfiguration mStaticIpConfiguration = validateIpConfigFields(ip,gateway,dns1,dns2);
                                  if(mStaticIpConfiguration == null){
                                        //设置相关内容有问题时mStaticIpConfiguration会为null
                                        return;
                                }
                                IpConfiguration mIpConfiguration = new IpConfiguration(IpAssignment.STATIC, ProxySettings.NONE,mStaticIpConfiguration,null);
                                mEthManager.setConfiguration(mIpConfiguration);
                        }else{
                                //动态IP模式(DHCP)
                                mEthManager.setConfiguration(new IpConfiguration(IpAssignment.DHCP, ProxySettings.NONE,null,null));
                        }
                }
        }
    }
    //验证ip,网管,dns1,dns2,并将相关设置项转换成StaticIpConfiguration
    public StaticIpConfiguration validateIpConfigFields(String ipAddr,String gateway,String dns1,String dns2){
        StaticIpConfiguration staticIpConfiguration = new StaticIpConfiguration();
         //ip地址
        if (TextUtils.isEmpty(ipAddr)){
                Log.i(TAG,"Type a valid IP address.");
                return null;
        }
        Inet4Address inetAddr = getIPv4Address(ipAddr);
        if (inetAddr == null) {
            Log.i(TAG,"Type a valid IP address.");
            return null;
        }
        
        int networkPrefixLength = -1;
        try {
            networkPrefixLength = 24;
            if (networkPrefixLength < 0 || networkPrefixLength > 32) {
                Log.i(TAG,"Type a network prefix length between 0 and 32.");
                return null;
            }
            staticIpConfiguration.ipAddress = new LinkAddress(inetAddr, networkPrefixLength);
        } catch (NumberFormatException e) {
             Log.i(TAG,"24");
        }
        //网关
        if (TextUtils.isEmpty(gateway)) {
            try {
                //Extract a default gateway from IP address
                InetAddress netPart = NetworkUtils.getNetworkPart(inetAddr, networkPrefixLength);
                byte[] addr = netPart.getAddress();
                addr[addr.length-1] = 1;
            } catch (RuntimeException ee) {
                }
        } else {
            InetAddress gatewayAddr = getIPv4Address(gateway);
            if (gatewayAddr == null) {
                  Log.i(TAG,"ype a valid gateway address.");
                return null;
            }
            staticIpConfiguration.gateway = gatewayAddr;
        }
        //dns1
        InetAddress dnsAddr = null;
        if (TextUtils.isEmpty(dns1)) {
             Log.i(TAG,"8.8.8.8");
        } else {
            dnsAddr = getIPv4Address(dns1);
            if (dnsAddr == null) {
                Log.i(TAG,"Type a valid DNS address.");
                return null;
            }
            staticIpConfiguration.dnsServers.add(dnsAddr);
        }
        
        //dns2
        if (!TextUtils.isEmpty(dns2)) {
            dnsAddr = getIPv4Address(dns2);
            if (dnsAddr == null) {
                Log.i(TAG,"Type a valid DNS address.");
                return null;
            }
            staticIpConfiguration.dnsServers.add(dnsAddr);
        }
        return staticIpConfiguration;
    }
    
    private Inet4Address getIPv4Address(String text) {
        try {
            return (Inet4Address) NetworkUtils.numericToInetAddress(text);
        } catch (IllegalArgumentException|ClassCastException e) {
            return null;
        }
    }
    
}

以上就是NetworkStaticReceiver.java的逻辑内容,大体逻辑步骤可简述为:
接收广播->辨别广播是WI-FI设置还是以太网设置

  1. WI-FI设置:
    • 获得当前连接wifi的config,获得isStatic对应的值->
    • true则获取设置的ip,网关,dns等设置项的值,false则直接设置为DHCP->
    • 判断设置信息是否正常,同时封装成StaticIpConfiguration->
    • StaticIpConfiguration设置进当前Wi-Fi->
    • 通过WifiManager更新并保存配置config->
    • 断开网络连接,之后重连(只有这样设置后才有效)。
  2. 以太网设置
    • 获得isStatic对应的值->
    • true则获取设置的ip,网关,dns等设置项的值,false则直接设置为DHCP->
    • 判断设置信息是否正常,同时封装成StaticIpConfiguration->
    • 创建一个IpConfiguration用来存放StaticIpConfiguration,同时设置为STATIC模式->
    • 通过EthernetManager保存配置项;

应用内控制方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
  /**
     * 控制Wi-Fi的状态
     * @param isStatic true为STATIC模式,false为DNCP模式。只有TRUE时之后的配置项才有效,false时后面的参数设置null即可
     * @param staticIp STATIC模式下的静态ip
     * @param gateway  STATIC模式下的网关
     * @param dns1     STATIC模式下的dns
     * @param dns2     STATIC模式下的备用dns
     */
    public void controlWifiStatic(boolean isStatic,String staticIp,String gateway,String dns1,String dns2){
        Intent intent = new Intent("com.cyh.wifi_static_ip");
        intent.putExtra("Static",isStatic);
        intent.putExtra("staticIp",staticIp);
        intent.putExtra("gateway",gateway);
        intent.putExtra("dns1",dns1);
        intent.putExtra("dns2",dns2;
        sendBroadcast(intent);
    }
    
    //调用示例
    controlWifiStatic(true,"192.168.0.190","192.168.0.1","8.8.8.8","8.8.4.4");
     
     /**
     * 控制以太网的状态
     * @param isStatic true为STATIC模式,false为DNCP模式。只有TRUE时之后的配置项才有效,false时后面的参数设置null即可
     * @param staticIp STATIC模式下的静态ip
     * @param gateway  STATIC模式下的网关
     * @param dns1     STATIC模式下的dns
     * @param dns2     STATIC模式下的备用dns
     */
    public void controlEthStatic(boolean isStatic,String staticIp,String gateway,String dns1,String dns2){
        Intent intent = new Intent("com.cyh.eth_static_ip");
        intent.putExtra("Static",isStatic);
        intent.putExtra("staticIp",staticIp);
        intent.putExtra("gateway",gateway);
        intent.putExtra("dns1",dns1);
        intent.putExtra("dns2",dns2;
        sendBroadcast(intent);
    }
     //调用示例
    controlEthStatic(true,"192.168.0.190","192.168.0.1","8.8.8.8","8.8.4.4");