Android13 实现有线网络和wifi共存
文章目录
- [Android13 实现有线网络和wifi共存](#Android13 实现有线网络和wifi共存)
-
- 一、前言
- 二、修改代码:
-
- 1、ConnectivityService.java
- 2、NetworkFactoryImpl.java
- [3、Android11 和Android13 修改代码目录对比:](#3、Android11 和Android13 修改代码目录对比:)
- 4、如果只修改部分代码的后果
-
-
- [只修改 ConnectivityService.java,不修改 NetworkFactoryImpl.java 的情况](#只修改 ConnectivityService.java,不修改 NetworkFactoryImpl.java 的情况)
- [只修改 NetworkFactoryImpl.java,不修改 ConnectivityService.java 的情况](#只修改 NetworkFactoryImpl.java,不修改 ConnectivityService.java 的情况)
-
- 三、网络共存验证
-
- 1、窗口命令查看
-
- (1)ifconfig
- [(2)ping -I 节点名称 ip/url](#(2)ping -I 节点名称 ip/url)
- [(3)dumpsys connectivity](#(3)dumpsys connectivity)
- 2、代码查看
一、前言
Android一些的定制设备,比如商显大屏或者Android盒子,一般是wifi或者有线网络。
Android 系统Framework进行一定适配后,可以实现wifi和有线网络端口都打开的,
进而在App端即可实现通过代码控制选择使用wifi或者有线网络进行网络请求。
Android11 上Wifi和有线网共存,已经有介绍:
https://blog.csdn.net/wenzhi20102321/article/details/133913924
Android13 上代码有较大差别,这里也进行记录和介绍。
二、修改代码:
Android13下面两个代码都要修改,不然会有点bug!
1、ConnectivityService.java
packages\modules\Connectivity\service\src\com\android\server\ConnectivityService.java
private void teardownUnneededNetwork(NetworkAgentInfo nai) {
if (nai.numRequestNetworkRequests() != 0) {
for (int i = 0; i < nai.numNetworkRequests(); i++) {
NetworkRequest nr = nai.requestAt(i);
// Ignore listening and track default requests.
if (!nr.isRequest()) continue;
loge("Dead network still had at least " + nr);
break;
}
}
loge("no to disconnect! ");//mychange
//nai.disconnect();
}
ConnectivityService.java 里面还有一个地方,有调用 nai.disconnect(),最后也注释掉。
2、NetworkFactoryImpl.java
frameworks\libs\net\common\device\android\net\NetworkFactoryImpl.java
private void handleRemoveRequest(NetworkRequest request) {
NetworkRequestInfo n = mNetworkRequests.get(request);
mParent.log(" handleRemoveRequest no do !"); //mychange
if (n != null) {
//mNetworkRequests.remove(request);
//if (n.requested) mParent.releaseNetworkFor(n.request);
}
}
最好是添加一个prop属性,记忆是否释放网络,方便手动修改和调试,类似下面的代码:
import android.os.SystemProperties;
boolean isReleaseNetwork = SystemProperties.getBoolean("persist.demo.release_network", false);
Log.e(TAG, "disconnect isReleaseNetwork = " + isReleaseNetwork);
if (!isReleaseNetwork) {
return;
}
两个地方都加上属性判断
3、Android11 和Android13 修改代码目录对比:
文件修改目录:
//Android11
frameworks\base\services\core\java\com\android\server\ConnectivityService.java
frameworks\libs\net\common\src_servicescommon\android\net\NetworkFactory.java
//Android13
packages\modules\Connectivity\service\src\com\android\server\ConnectivityService.java
frameworks\libs\net\common\device\android\net\NetworkFactoryImpl.java
可以看到里面的代码目录完全不一样的;
并且里面的代码实现也是有非常大的差异!有兴趣的可以自己研究看看。
4、如果只修改部分代码的后果
这里只说Android13 是上的,Android11 的比较久没动了,记不清了!
只修改 ConnectivityService.java,不修改 NetworkFactoryImpl.java 的情况
刚开始是可以同时连接上的,但是你发现断开后,无法再连接上wifi!
因为相关请求已经被移除了,低优先级的网络无法再重新连接!
具体为啥无法再连接,没有进一步具体分析,有兴趣的可以去看看。
只修改 NetworkFactoryImpl.java,不修改 ConnectivityService.java 的情况
Wifi和有线网是可以同时连接的,但是Wifi会每过几秒就会断开重连!
从日志看有 ConnectivityService 和 NetworkAgent 的相关日志
10-18 15:18:49.999 636 802 D ConnectivityService: handleLingerComplete for [143 WIFI]
10-18 15:18:50.000 636 794 D WifiNetworkAgent: NetworkAgent: NetworkAgent channel lost //网络断开的关键
10-18 15:18:50.000 636 802 D ConnectivityService: [143 WIFI] disconnected, was satisfying 10
每几秒重复一次上面的日志
如果你在 ConnectivityService.teardownUnneededNetwork 方法添加日志,发现会执行到 nai.disconnect();
所以循环断开是系统流程里面导致的。具体哪里开始的,可以基于日志分析,这里不展开介绍。
三、网络共存验证
1、窗口命令查看
(1)ifconfig
图片:
内容:
console:/ #
console:/ # ifconfig
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope: Host
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:33 errors:0 dropped:0 overruns:0 frame:0
TX packets:33 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:2898 TX bytes:2898
eth0 Link encap:Ethernet HWaddr 42:6b:39:d7:49:75 Driver rk_gmac-dwmac
inet addr:192.168.31.174 Bcast:192.168.31.255 Mask:255.255.255.0
inet6 addr: fe80::42ff:4f65:13fe:20fa/64 Scope: Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:558 errors:0 dropped:0 overruns:0 frame:0
TX packets:135 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:40961 TX bytes:20403
Interrupt:78
wlan0 Link encap:Ethernet HWaddr 0c:cf:89:a6:44:2a Driver usb
inet addr:192.5.1.34 Bcast:192.5.1.255 Mask:255.255.255.0
inet6 addr: fe80::2e43:706c:c30b:f9c8/64 Scope: Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:812 errors:0 dropped:0 overruns:0 frame:0
TX packets:95 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:3000
RX bytes:142061 TX bytes:17362
console:/ #
可以看到 wlan0 和 eth0 都是存在ip地址的。
(2)ping -I 节点名称 ip/url
测试通过节点对应的网络访问某个ip
130|console:/ #
130|console:/ # ping wwwbaidu.com
PING wwwbaidu.com (45.194.224.35) 56(84) bytes of data.
64 bytes from 45.194.224.35: icmp_seq=1 ttl=43 time=13.6 ms
64 bytes from 45.194.224.35: icmp_seq=2 ttl=43 time=13.4 ms
64 bytes from 45.194.224.35: icmp_seq=3 ttl=43 time=38.7 ms
64 bytes from 45.194.224.35: icmp_seq=4 ttl=43 time=13.5 ms
^C
--- wwwbaidu.com ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3004ms
rtt min/avg/max/mdev = 13.452/19.851/38.744/10.908 ms
console:/ #
console:/ #
console:/ # ping -I eth0 www.baidu.com
PING www.a.shifen.com (157.148.69.80) from 192.168.31.174 eth0: 56(84) bytes of data.
64 bytes from 157.148.69.80: icmp_seq=1 ttl=46 time=15.0 ms
64 bytes from 157.148.69.80: icmp_seq=2 ttl=46 time=14.5 ms
64 bytes from 157.148.69.80: icmp_seq=3 ttl=46 time=15.2 ms
64 bytes from 157.148.69.80: icmp_seq=4 ttl=46 time=14.6 ms
^C
--- www.a.shifen.com ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3004ms
rtt min/avg/max/mdev = 14.580/14.877/15.257/0.294 ms
console:/ #
console:/ # ping -I wlan0 www.baidu.com
PING www.a.shifen.com (157.148.69.80) from 192.5.1.34 wlan0: 56(84) bytes of data.
64 bytes from 157.148.69.80: icmp_seq=1 ttl=41 time=478 ms
64 bytes from 157.148.69.80: icmp_seq=2 ttl=41 time=99.9 ms
64 bytes from 157.148.69.80: icmp_seq=3 ttl=41 time=89.0 ms
64 bytes from 157.148.69.80: icmp_seq=4 ttl=41 time=96.1 ms
^C
--- www.a.shifen.com ping statistics ---
5 packets transmitted, 4 received, 20% packet loss, time 4005ms
rtt min/avg/max/mdev = 89.084/191.015/478.886/166.248 ms
console:/ #
这里可以看到有线网和wifi都是对外正常进行通讯的。
(3)dumpsys connectivity
这里会有比较多的连接信息,主要信息如下:
console:/ #
console:/ #
console:/ # dumpsys connectivity
Current Networks:
//wifi 相关信息
NetworkAgentInfo{network{100} handle{432902426637} ni{WIFI CONNECTED extra: } Score(60 ; KeepConnected : 0 ; Policies : TRANSPORT_PRIMARY&EVER_VALIDATED_NOT_AVOIDED_WHEN_BAD&IS_UNMETERED&IS_VALIDATED) created everValidated lastValidated lp{{InterfaceName: wlan0 LinkAddresses: [ fe80::2e43:706c:c30b:f9c8/64,192.5.1.34/24 ] DnsAddresses: [ /192.5.1.1 ] Domains: null MTU: 0 ServerAddress: /192.5.1.1 TcpBufferSizes: 524288,1048576,2097152,262144,524288,1048576 Routes: [ fe80::/64 -> :: wlan0 mtu 0,192.5.1.0/24 -> 0.0.0.0 wlan0 mtu 0,0.0.0.0/0 -> 192.5.1.1 wlan0 mtu 0 ]}} nc{[ Transports: WIFI Capabilities: NOT_METERED&INTERNET&NOT_RESTRICTED&TRUSTED&NOT_VPN&VALIDATED&NOT_ROAMING&FOREGROUND&NOT_CONGESTED&NOT_SUSPENDED&NOT_VCN_MANAGED LinkUpBandwidth>=12000Kbps LinkDnBandwidth>=30000Kbps Specifier: <WifiNetworkAgentSpecifier [WifiConfiguration=, SSID="VPN", BSSID=34:f7:16:92:87:6c, band=1, mMatchLocalOnlySpecifiers=false]> TransportInfo: <SSID: "VPN", BSSID: 34:f7:16:92:87:6c, MAC: 0c:cf:89:a6:44:2a, IP: /192.5.1.34, Security type: 2, Supplicant state: COMPLETED, Wi-Fi standard: 4, RSSI: -51, Link speed: 270Mbps, Tx Link speed: 270Mbps, Max Supported Tx Link speed: 300Mbps, Rx Link speed: -1Mbps, Max Supported Rx Link speed: 300Mbps, Frequency: 2442MHz, Net ID: 0, Metered hint: false, score: 60, isUsable: true, CarrierMerged: false, SubscriptionId: -1, IsPrimary: 1, Trusted: true, Restricted: false, Ephemeral: false, OEM paid: false, OEM private: false, OSU AP: false, FQDN: <none>, Provider friendly name: <none>, Requesting package name: <none>"VPN"wpa2-pskMLO Information: , AP MLD Address: <none>, AP MLO Link Id: <none>, AP MLO Affiliated links: <none>> SignalStrength: -51 OwnerUid: 1000 AdminUids: [1000] SSID: "VPN" UnderlyingNetworks: Null]} factorySerialNumber=6}
Requests: REQUEST:0 LISTEN:9 BACKGROUND_REQUEST:0 total:9
NetworkRequest [ LISTEN id=5, [ Capabilities: FOREGROUND RequestorUid: 1000 RequestorPkg: android UnderlyingNetworks: Null] ]
Inactivity Timers:
Nat464Xlat:
<not start>
//有线网相关信息
NetworkAgentInfo{network{101} handle{437197393933} ni{Ethernet CONNECTED extra: 42:6b:39:d7:49:75} Score(-2147483648 ; KeepConnected : 0 ; Policies : EVER_VALIDATED_NOT_AVOIDED_WHEN_BAD&IS_UNMETERED&IS_VALIDATED) created everValidated lastValidated lp{{InterfaceName: eth0 LinkAddresses: [ fe80::42ff:4f65:13fe:20fa/64,192.168.31.174/24 ] DnsAddresses: [ /192.168.31.1 ] Domains: null MTU: 0 ServerAddress: /192.168.31.1 TcpBufferSizes: 524288,1048576,3145728,524288,1048576,2097152 Routes: [ fe80::/64 -> :: eth0 mtu 0,192.168.31.0/24 -> 0.0.0.0 eth0 mtu 0,0.0.0.0/0 -> 192.168.31.1 eth0 mtu 0 ]}} nc{[ Transports: ETHERNET Capabilities: NOT_METERED&INTERNET&NOT_RESTRICTED&TRUSTED&NOT_VPN&VALIDATED&NOT_ROAMING&FOREGROUND&NOT_CONGESTED&NOT_SUSPENDED&NOT_VCN_MANAGED LinkUpBandwidth>=100000Kbps LinkDnBandwidth>=100000Kbps Specifier: <EthernetNetworkSpecifier (eth0)> UnderlyingNetworks: Null]} factorySerialNumber=1}
Requests: REQUEST:10 LISTEN:7 BACKGROUND_REQUEST:0 total:17
NetworkRequest [ REQUEST id=1, [ Capabilities: INTERNET&NOT_RESTRICTED&TRUSTED&NOT_VPN&NOT_VCN_MANAGED RequestorUid: 1000 RequestorPkg: android UnderlyingNetworks: Null] ]
NetworkRequest [ LISTEN id=5, [ Capabilities: FOREGROUND RequestorUid: 1000 RequestorPkg: android UnderlyingNetworks: Null] ]
Inactivity Timers:
Nat464Xlat:
<not start>
这里可以看到 Wifi 和有线网都要相关信息和不同的ip;
这里和Android11 有个非常不同的是:Android 有线网没有 Score 值?
这里值显示的是int 的最小值。但是还是有线网优先的!
Android11 上是可以看到 Score 的值为 70,代码上明显定义的,Android13 上未定义;
所以如果Android13 上要设置优先级估计就比较麻烦了。
如果确实要做优先级,可以看 NetworkAgentInfo 对象里面的Score 值的定义线索进行分析。
2、代码查看
可以通过代码查看Wifi 和有线网的 Ip地址
//getIpAddress,第二个参数是决定是获取的wifi的ip地址还是有线网的ip地址
public static String getIpAddress(Context context, boolean isGetWifiIp) {
Network network = null;
if (isGetWifiIp) {
network = getWlanNet(context);
} else {
network = getFirstEthernet(context);
}
if (network == null) {
return "";
}
ConnectivityManager mConnectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
final LinkProperties linkProperties = mConnectivityManager.getLinkProperties(network);
if (linkProperties != null) {
for (LinkAddress linkAddress : linkProperties.getLinkAddresses()) {
InetAddress inetAddress = linkAddress.getAddress();
if (inetAddress instanceof Inet4Address) {
return inetAddress.getHostAddress();
}
}
}
return "";
}
//getFirstEthernet
private static Network getFirstEthernet(Context context) {
ConnectivityManager mConnectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
final Network[] networks = mConnectivityManager.getAllNetworks();
for (final Network network : networks) {
NetworkInfo networkInfo = mConnectivityManager.getNetworkInfo(network);
if (networkInfo != null && networkInfo.getType() == ConnectivityManager.TYPE_ETHERNET) {
return network;
}
}
return null;
}
//getFirstWlan
private static Network getWlanNet(Context context) {
ConnectivityManager mConnectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
final Network[] networks = mConnectivityManager.getAllNetworks();
for (final Network network : networks) {
NetworkInfo networkInfo = mConnectivityManager.getNetworkInfo(network);
if (networkInfo != null && networkInfo.getType() == ConnectivityManager.TYPE_WIFI) {
return network;
}
}
return null;
}
通过上面的代码 getIpAddress 方法,是可以分别获取到Wifi 和有线网的 Ip的!
另外,Java代码情况网络是可以指定特定网络通讯的,这里不展开介绍。
有兴趣的可以看看:
https://blog.csdn.net/wenzhi20102321/article/details/133950336