达到 android6.0 wifi连接外网,ethernet连接内网局域网
1、修改 framework 层代码,使得 wif 和 ethernet 同时存在
由于我们的目标时wifi连接外网,ethernet访问特定局域网,所有设置 wifi 优先,ethernet 进行单独配置。
修改wifi优先,在 NetworkAgentInfo.Java的方法getCurrentScore() 中加入:
if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
return MAXIMUM_NETWORK_SCORE;
}
这样 wifi 的分值就最高了。
修改 wifi 连接上的情况下,插入有线会主动连接。由于上面将 wifi 的优先级调到最高了,所有插入有线时,
判断当前网络连接优先级高于有线,所以不会主动连接有线。在 EthernetNetworkFactory.java的方法 updateInterfaceState
中加入
mFactory.setScoreFilter(up ? NETWORK_SCORE : -1);
if (up) {
mFactory.startNetwork();
}
这样只有已插入网线就会主动去连接
还是由于wifi优先,如果先连接有线再打开wifi,去连接wifi时会关闭有线。这个时候需要修改 ConnectivityService.java中的方法
private void teardownUnneededNetwork(NetworkAgentInfo nai) {
/*for (int i = 0; i < nai.networkRequests.size(); i++) {
NetworkRequest nr = nai.networkRequests.valueAt(i);
// Ignore listening requests.
if (!isRequest(nr)) continue;
loge(“Dead network still had at least ” + nr);
break;
}
nai.asyncChannel.disconnect();*/
}
这样就不会去关闭其他连接了。
经过以上的修改,达到了 wifi 和 ethernet 同时存在,而且 wifi 优先正常访问外网的目的。
2、wifi 和 ethernet 同时存在,考虑配置静态路由使得 ethernet 访问指定网络。
修改 dhcpcd.c 中的 main 方法,可以使 dhcp 服务器下发的静态路由添加到路由表中。
case ‘a’:
syslog(LOG_INFO, “avoid_routes one %d”, avoid_routes);
//avoid_routes = 1;
syslog(LOG_INFO, “avoid_routes two %d”, avoid_routes);
break;
此时用 route 命令查看,可以看到路由表中多了一条 192.168.10.0 192.168.2.1 255.255.255.0 UG 202 0 0 eth0
:/ # route
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
192.168.2.0 * 255.255.255.0 U 202 0 0 eth0
192.168.3.0 * 255.255.255.0 U 0 0 0 wlan0
192.168.10.0 192.168.2.1 255.255.255.0 UG 202 0 0 eth0
但是实际上此路由表不会起到任何作用。因为在 android6.0 开始使用了策略路由,如下是 wifi 和 ethernet 同时连接情况下的 策略路由信息
:/ # ip rule list
0: from all lookup local
10000: from all fwmark 0xc0000/0xd0000 lookup legacy_system
10500: from all oif wlan0 uidrange 0-0 lookup wlan0
10500: from all oif eth0 uidrange 0-0 lookup eth0
13000: from all fwmark 0x10063/0x1ffff lookup local_network
13000: from all fwmark 0x10065/0x1ffff lookup wlan0
13000: from all fwmark 0x10066/0x1ffff lookup eth0
14000: from all oif wlan0 lookup wlan0
14000: from all oif eth0 lookup eth0
15000: from all fwmark 0x0/0x10000 lookup legacy_system
16000: from all fwmark 0x0/0x10000 lookup legacy_network
17000: from all fwmark 0x0/0x10000 lookup local_network
19000: from all fwmark 0x65/0x1ffff lookup wlan0
19000: from all fwmark 0x66/0x1ffff lookup eth0
22000: from all fwmark 0x0/0xffff lookup wlan0
23000: from all fwmark 0x0/0xffff uidrange 0-0 lookup main
32000: from all unreachable
同时可以看到 route 命令查看的实际上是 main 路由表的路由信息
:/ # ip route list table main
192.168.2.0/24 dev eth0 proto kernel scope link src 192.168.2.247 metric 202
192.168.3.0/24 dev wlan0 proto kernel scope link src 192.168.3.146
192.168.10.0/24 via 192.168.2.1 dev eth0 metric 202
所以从上面的分析可以得出结论,单纯依靠 dhcp 下发静态路由,并不能到达效果。
3、android6.0 策略路由
:/ # ip rule list
0: from all lookup local
10000: from all fwmark 0xc0000/0xd0000 lookup legacy_system
10500: from all oif wlan0 uidrange 0-0 lookup wlan0
10500: from all oif eth0 uidrange 0-0 lookup eth0
13000: from all fwmark 0x10063/0x1ffff lookup local_network
13000: from all fwmark 0x10065/0x1ffff lookup wlan0
13000: from all fwmark 0x10066/0x1ffff lookup eth0
14000: from all oif wlan0 lookup wlan0
14000: from all oif eth0 lookup eth0
15000: from all fwmark 0x0/0x10000 lookup legacy_system
16000: from all fwmark 0x0/0x10000 lookup legacy_network
17000: from all fwmark 0x0/0x10000 lookup local_network
19000: from all fwmark 0x65/0x1ffff lookup wlan0
19000: from all fwmark 0x66/0x1ffff lookup eth0
22000: from all fwmark 0x0/0xffff lookup wlan0
23000: from all fwmark 0x0/0xffff uidrange 0-0 lookup main
32000: from all unreachable
从这个路由规则中可以看到, 路由表 local优先,然后是netid 对应 0x10065 的走 wlan0 路由表,对应 0x10066 走 eth0 路由表。
而通常情况下访问网络时没有设置 netid,默认就使用 22000: from all fwmark 0x0/0xffff lookup wlan0 这个,即 wlan0 路由表。
netid 指定在 android6.0中应用可以通过 bindProcessToNetwork() 来指定使用wlan或者ethernet进行网络访问。
看下各个路由表中的信息:
:/ # ip route list table wlan0
default via 192.168.3.1 dev wlan0 proto static
192.168.3.0/24 dev wlan0 proto static scope link
:/ # ip route list table eth0
default via 192.168.2.1 dev eth0 proto static
192.168.2.0/24 dev eth0 proto static scope link
以上静态路由无法达到目的,策略路由不知道如何通过dhcp配置,而且就算配置也只能对应在 eth0 表中,但起作用的是 wlan0 这个路由表。
所以这条路放弃,换个思路。
4、自由选择要使用的网络
13000: from all fwmark 0x10066/0x1ffff lookup eth0 看这条路由信息,可以想到如果对应 app 在访问指定网络时设置 netid 为 0x10066,是否就可以用 eth0 访问指定网络。
接着 android6.0 的网络相关的新功能, bindProcessToNetwork 接口。
详细使用可以参照原生代码中 CaptivePortalLoginActivity 类。
这个调用的过程可以参考 http://blog.csdn.net/javon_hzw/article/details/46831771