Android M 多网络应用

来源:互联网 发布:ubuntu install kde 编辑:程序博客网 时间:2024/05/17 01:19

达到 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