Android network — 进程指定网络发包
0. 前言
在android 中,一个app使用网络,需要在manifest 申请一下
<uses-permission android:name="android.permission.INTERNET"/>
这种方式将使用default网络,比如WIFI 和 数据网络,android 同一个时间点,只能有一个default网络,default网络由Android 网络评分机制选择。
那有没有一种方式可以不使用默认网络呢,比如某一个App只想使用WiFi或者别的某一个网络,而不受默认网络变化的影响,答案是有的
1. 进程绑定网络
1.1 App进程绑定网络
对于App进程,ConnectivityService中提供了bindProcessToNetwork 接口进行绑定,使用说明如下
- 通过 requestNetwork 申请一个网络
- 在NetworkCallback中的onAvailable的方法去调用bindProcessToNetwork 去bind这个网络
- 上两步后APP的网络流量将会走这个network,或者说走这个network 指定的 网卡
补充说明一下 :NetworkRequest 在CS对应一个NetworkRequestInfo ,一般情况下一个NetworkRequestInfo对应了一个client进程
使用示例:
NetworkRequest request = new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
.build();
mNetworkCallback = new ConnectivityManager.NetworkCallback() {
@Override
public void onAvailable(final Network network) {
runOnUiThread(new Runnable() {
@Override
public void run() {
// requires android.permission.INTERNET
if (!mConnectivityManager.bindProcessToNetwork(network)) {
} else {
Log.d(TAG, "Network available");
}
}
});
1.2 Native进程绑定网络
对于Native进程,我们可以模仿Framework的底层实现,具体可参考后面2. 原理实现部分
#include “NetdClient.h”
此文件,此文件在netd的源码中,并 动态链接libnetd_client.so
,注意一定是动态链接- 调用 setNetworkForProcess() 传入需要绑定网络的 netid
- 强调一下,一定是动态链接,具体原因在后面原理分析中进行解释
补充说明一下 :同一网络,如某一个wifi或以太网,在断开重连后,netid是变化的,因此,实际使用中,要考虑到异常断开场景后,netid如何固定下来
使用示例:
// Android.bp
cc_binary {
name: "netd_client_example",
srcs: ["main.cpp"],
vendor: true,
sdk_version: "current",
defaults: ["netd_defaults"],
shared_libs: [
......
"libnetd_client"
],
......
}
// main.cpp
#include <NetdClient.h>
......
result = setNetworkForProcess(netId);
......
2. 源码原理分析
2.1 申请网络requestNetwork
//frameworks/base/core/java/android/net/ConnectivityManager.java
public void requestNetwork(NetworkRequest request, NetworkCallback networkCallback) {
}
- NetworkRequest 可以设置 TransportType 比如 TRANSPORT_CELLULAR或者 TRANSPORT_WIFI
- NetworkRequest 可以设置NetworkCapabilities比如NET_CAPABILITY_INTERNET或者其他类型
这个方法可能导致一个新的Network的出现,对应ConnectivityService中就是一个NetworkAgentInfo,这里可以简单的认为一个NetworkAgent