浅谈Android的ConnectivityService网络连接服务
目次
1、概述
2、原理
3、网络工厂
4、网络类型注册
5、网络链接哀求
6、网络评分机制
总结
8、附表
表1:代码路径
表2:网络能力
表3:网络透传能力
9、扩展:怎样举行第二路拨号并访问网络
9.1 拨号
9.2 访问
1、概述
ConnectivityService在 Android 系统中是一个核心的服务,它主要负责管理和监控网络连接的状态。这个服务是 Android 框架的一部分,为应用程序和系统服务提供了关于网络连接(如 wifi、mobile network、ethernet、bt-pan)的详细信息。
ConnectivityService作为管理员身份,每种网络都会去向它注册,网络的利用权全靠它来分配。并实现了网络评分机制确保了系统能够最出作优的网络连接,从而为用户提供更好的网络体验。
2、原理
https://img-blog.csdnimg.cn/direct/563b0759295f4008aad124ef9d60ce7c.png
相干类的功能说明如下:
[*]ConnectivityService是个服务,用来管理网络链接。
[*]ConnectivityManager是ConnectivityService的署理,署理意思是调用者不要关心具体接口的实现,只管调用,以是才设计此模式。以是ConnectivityManager作用是对外提供ConnectivityService的相干接口。
[*]TelephonyNetworkFatory是个移动的网络工厂,父类是NetworkFactory,用于SIM卡业务的数据链接。
[*]WifiNetworkFatory是个Wifi的网络工厂,父类是NetworkFactory,用于WIFI模块的数据链接。
[*]EthernetNetworkFatory是个以太网的网络工厂,父类是NetworkFactory,用于以太网业务的数据链接。
ConnectivityService链接服务从箭头来看分为2个流程,分别为注册和网络选择。
[*]注册:见红色箭头,在设备开机时,相干的网络工厂会向ConnectivityService举行注册register,ConnectivityManager是个署理,ConnectivityService对外提供的接口都由ConnectivityManager提供,末了在register函数里通过调用registerNetworkProvider,ConnectivityService就拿到了各种类型的网络工厂,比如移动,Wifi,以太网等。
[*]网络选择:见绿色箭头,假如存在多种网络的情况下,ConnectivityService根据evalRequest逻辑举行评分,分数高的网络工厂会优先利用,这叫做网络评分机制。从流程图可以看出,当应用调用哀求网络requestNetwork时(此函数是发起一个网络链接哀求),最终根据evalRequest函数找到分数最高的网络工厂然后调用它的needNetworkFor来完成网络链接哀求。
3、网络工厂
NetworkFactory网络工厂其实是通过工厂模式天生各自特有功能的网络类型。
https://img-blog.csdnimg.cn/direct/ac84771c81504c52a61ce95cd5e84f70.png
上图的圆圈是网络工厂的相干类图,TelephonyNetworkFatory、WifiNetworkFatory、EthernetNetworkFatory网络类型继承NetworkFatory,NetworkFatory的重点override接口如下:
[*]needNetworkFor:哀求网络链接接口
[*]releaseNetworkFor:释放网络链接接口
[*]setScoreFilter(int score): 设置分数,除了初始评分外,各个网络的评分还会根据实时状态举行调解。
比方,以太网会根据网卡的up和down状态,把分值设置为70(当网卡up时)或0(当网卡down时)。Wi-Fi的分值还跟信号状态、当前数据速率等一系列因素有关,在WifiStateMachine.java的calculateWifiScore函数中举行盘算,初始盘算的基础分值为56,然后根据wifi网络的状态举行小的加减,末了假如分值大于60,就把分值设置为60。
[*]register(): 向ConnectivityService注册,这样ConnectivityService就能拿到各类型的网络。用于后面选择评分高的网络举行链接。
NetworkProvider直译是网络提供者,和对应的网络工厂绑定,用于告知ConnectivityService,方便异步调用网络提供者。
4、网络类型注册
https://img-blog.csdnimg.cn/direct/1819ab47514d4620af0f5fb89b4f8cd3.png
在开机时,各网络类型通过调用register向ConnectivityService举行注册,函数代码如下:
1. public void register() {
2. if (mProvider != null) {
3. throw new IllegalStateException("A NetworkFactory must only be registered once");
4. }
5. if (DBG) log("Registering NetworkFactory");
6.
7. mProvider = new NetworkProvider(mContext, NetworkFactory.this.getLooper(), LOG_TAG) {
8. @Override
9. public void onNetworkRequested(@NonNull NetworkRequest request, int score,
10. int servingProviderId) {
11. handleAddRequest(request, score, servingProviderId);
12. }
13.
14. @Override
15. public void onNetworkRequestWithdrawn(@NonNull NetworkRequest request) {
16. handleRemoveRequest(request);
17. }
18. };
19.
20. ((ConnectivityManager) mContext.getSystemService(
21. Context.CONNECTIVITY_SERVICE)).registerNetworkProvider(mProvider);
22. }
从如上代码可以看出,先创建一个NetworkProvider的对象mProvider,此对象之前说过,方便ConnectivityService举行异步调用,也就是NetworkProvider有相干的Messenger实现。
末了调用ConnectivityService的registerNetworkProvider函数完成注册,把NetworkProvider放到mNetworkProviderInfos这个成员数组里。其实ConnectivityService最终拿到的是NetworkFactory的NetworkProvider相干接口。
5、网络链接哀求
https://img-blog.csdnimg.cn/direct/37f959897db24c82a15d6b310c00b458.png
应用层怎样发起网络链接哀求,本文以TelephonyNetworkFatory为例说明。
ConnectivityManager对外提供了一个requestNetwork接口,以是应用层调用此接口即可。
1. NetworkRequest.Builder networkRequestBuilder = new NetworkRequest.Builder();
2. networkRequestBuilder.addCapability(NetworkCapabilities.NET_CAPABILITY_SUPL);
3. networkRequestBuilder.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
4. // During an emergency call, and when we have cached the Active Sub Id, we set the
5. // Network Specifier so that the network request goes to the correct Sub Id
6. if (mNiHandler.getInEmergency() && mActiveSubId >= 0) {
7. if (DEBUG) Log.d(TAG, "Adding Network Specifier: " + Integer.toString(mActiveSubId));
8. networkRequestBuilder.setNetworkSpecifier(Integer.toString(mActiveSubId));
9. }
10. NetworkRequest networkRequest = networkRequestBuilder.build();
11. mConnMgr.requestNetwork(
12. networkRequest,
13. mSuplConnectivityCallback,
14. mHandler,
15. SUPL_NETWORK_REQUEST_TIMEOUT_MILLIS);
requestNetwork函数有2个重要的参数:
[*]NetworkRequest:网络哀求封装,如通过什么能力及什么方式透传。
addCapability:通过此函数设置网络能力,见表2。它用于向网络哀求添加特定的网络能力,具体来说,addCapability用于指定一个网络哀求所需或支持的网络特性,跟APN有关。本示例的网络能力是安全用户平面定位(SUPL),用于GPS辅助定位服务。
addTransportType:函数用于指定网络连接所利用的传输类型,见表3。传输类型决定了网络哀求所利用的底层传输技能,比方Wi-Fi、蜂窝数据等。本示例的传输类型是移动网络。
[*]NetworkCallback:网络哀求的回调,具体是ConnectivityManager.NetworkCallback,回调的接口有onAvailable,onLost,onUnavailable。
关于requestNetwork接下来怎样调用,请参考时序图,这里不再讲解。
6、网络评分机制
触发网络评分机制有很多多少种方法,如修改分数,下发网络哀求等。这些最终都会触发evalRequest函数的调用,代码如下:
1. private void evalRequest(NetworkRequestInfo n) {
2. if (VDBG) {
3. log("evalRequest");
4. log(" n.requests = " + n.requested);
5. log(" n.score = " + n.score);
6. log(" mScore = " + mScore);
7. log(" request.providerId = " + n.providerId);
8. log(" mProvider.id = " + mProvider.getProviderId());
9. }
10. if (shouldNeedNetworkFor(n)) {
11. if (VDBG) log("needNetworkFor");
12. needNetworkFor(n.request, n.score);
13. n.requested = true;
14. } else if (shouldReleaseNetworkFor(n)) {
15. if (VDBG) log("releaseNetworkFor");
16. releaseNetworkFor(n.request);
17. n.requested = false;
18. } else {
19. if (VDBG) log("done");
20. }21. }
shouldNeedNetworkFor函数用于确认是否举行网络链接哀求,shouldReleaseNetworkFor函数用于释放网络链接哀求。
shouldNeedNetworkFor的函数代码如下,具体逻辑是:假如NetworkRequestInfo没有被requested过,而且其分值(n.score)小于当前NetworkFactory自己的分值(mScore),那么就说明,当前NetworkFactory所处的网络优先级高于其他网络的优先级,就会触发当前NetworkFactory所在网络的needNetworkFor()流程,也就是连接创建流程,并将标志NetworkRequestInfo.requested=true。当NetworkRequestInfo被requested过(也就是当前网络被needNetworkFor过),此时假如再次收到哀求,而且携带的新score大于当前NetworkFactory所处网络的mScore,那么就说明当前NetworkFactory所在网络优先级已经不是最高,需要将其releaseNetworkFor掉,并标志NetworkRequestInfo.requested=false。
1. private boolean shouldNeedNetworkFor(NetworkRequestInfo n) {
2. // If this request is already tracked, it doesn't qualify for need
3. return !n.requested
4. // If the score of this request is higher or equal to that of this factory and some
5. // other factory is responsible for it, then this factory should not track the request
6. // because it has no hope of satisfying it.
7. && (n.score < mScore || n.providerId == mProvider.getProviderId())
8. // If this factory can't satisfy the capability needs of this request, then it
9. // should not be tracked.
10. && n.request.canBeSatisfiedBy(mCapabilityFilter)
11. // Finally if the concrete implementation of the factory rejects the request, then
12. // don't track it.
13. && acceptRequest(n.request, n.score);
14. }
总结
本文大概讲了ConnectivityService框架及接口利用说明,涉及的还不是很深。后面有问题再具体总结分析这块的内容。
8、附表
表1:代码路径
路径
frameworks\opt\telephony\src\java\com\android\internal\telephony\dataconnection\TelephonyNetworkFactory.java
frameworks\libs\net\common\src_servicescommon\android\net\NetworkFactory.java
frameworks\base\core\java\android\net\NetworkCapabilities.java
frameworks\base\core\java\android\net\NetworkRequest.java
frameworks\base\core\java\android\net\ConnectivityManager.java
frameworks\base\core\java\android\net\ Network.java
frameworks\base\core\java\android\net\ NetworkProvider.java
frameworks\base\services\core\java\com\android\server\ConnectivityService.java
frameworks\opt\net\ethernet\java\com\android\server\ethernet\ EthernetNetworkFactory.java
表2:网络能力
NetworkCapabilities
ApnSetting
能力说明
NET_CAPABILITY_MMS
TYPE_MMS
多媒体消息服务(MMS),用于发送和接收彩信。
NET_CAPABILITY_SUPL
TYPE_SUPL
安全用户平面定位(SUPL),用于GPS辅助定位服务。
NET_CAPABILITY_DUN
TYPE_DUN
拨号上网(DUN),允许设备通过移动网络为其他设备提供网络连接。
NET_CAPABILITY_FOTA
TYPE_FOTA
固件空中升级(FOTA),允许设备通过移动网络接收固件更新。
NET_CAPABILITY_IMS
TYPE_IMS
IP多媒体子系统(IMS),用于支持VoIP等多媒体通信服务。
NET_CAPABILITY_CBS
TYPE_CBS
小区广播服务(CBS),用于向手机用户发送小区内的短消息。
NET_CAPABILITY_IA
TYPE_IA
这个名称不太常见,大概表示某种特定类型的网络访问或功能。
NET_CAPABILITY_EIMS
TYPE_EMERGENCY
紧急IMS,大概用于紧急情况下的多媒体通信。
NET_CAPABILITY_INTERNET
TYPE_DEFAULT
表示网络可以访问互联网。
NET_CAPABILITY_WIFI_P2P
Wi-Fi直连(P2P),允许设备之间直接通过Wi-Fi举行通信,无需接入点。
NET_CAPABILITY_RCS
丰富的呼唤服务(RCS),用于增强语音呼唤的功能,如视频通话、即时消息等。
NET_CAPABILITY_XCAP
XML设置访问协议(XCAP),一种用于存储和检索XML文档的协议。
NET_CAPABILITY_NOT_METERED
表示网络流量不计费。
NET_CAPABILITY_NOT_RESTRICTED
表示网络没有访问限制。
NET_CAPABILITY_TRUSTED
表示网络是可信的。
表3:网络透传能力
TransportType
能力名称
能力说明
TRANSPORT_CELLULAR:
蜂窝数据网络
如2G、3G、4G(LTE)、5G等移动网络。
TRANSPORT_WIFI
Wi-Fi网络
通过无线局域网连接到互联网。
TRANSPORT_BLUETOOTH
蓝牙网络
固然蓝牙通常不消于互联网连接,但在某些特定场景下(如蓝牙PAN)大概用作数据传输。
TRANSPORT_ETHERNET
以太网网络
这通常指的是有线网络连接,但在Android设备上较为稀有,因为移动设备主要利用无线连接。
TRANSPORT_VPN
捏造私人网络(VPN)
这是一种通过公共网络(如互联网)创建加密通道的技能,用于在远程服务器上安全地发送和接收数据。
9、扩展:怎样举行第二路拨号并访问网络
9.1 拨号
在利用移动网络举行第二跑拨号时,要注意不能与当前的apn雷同,比如当前是default的apn,那么第二路只能利用其他apn类型拨号了,否则会报如下错误。
ConnectivityService: NetReassign
利用APN为mms的拨号示例代码如下:
1. import android.net.ConnectivityManager;
2. import android.net.Network;
3. import android.net.NetworkCapabilities;
4. import android.net.NetworkInfo;
5. import android.net.NetworkRequest;
6.
7. private ConnectivityManager.NetworkCallback createConnectivityCallback(){
8. return new ConnectivityManager.NetworkCallback() {
9. @Override
10. public void onAvailable(Network network) {
11. // Specific to a change to a SUPL enabled network becoming ready
12. Log.d(LOG_TAG, "test network connection available.");
13. }
14.
15. @Override
16. public void onLost(Network network) {
17. Log.d(LOG_TAG, "test network connection lost.");
18. }
19.
20. @Override
21. public void onUnavailable() {
22. Log.d(LOG_TAG, "test network connection request timed out.");
23. // Could not setup the connection to the network in the specified time duration.
24.
25. }
26. };
27. }
28. //发起移动网络拨号
29. private void startSecDataCall()
30. {
31. ConnectivityManager mTConnMgr;
32. ConnectivityManager.NetworkCallback mConnectivityCallback = createConnectivityCallback();
33. mTConnMgr = (ConnectivityManager) getActivity().getSystemService(Context.CONNECTIVITY_SERVICE);
34.
35. NetworkRequest.Builder networkRequestBuilder = new NetworkRequest.Builder();
36. networkRequestBuilder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
37. networkRequestBuilder.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
38.
39. NetworkRequest networkRequest = networkRequestBuilder.build();
40. mTConnMgr.requestNetwork(
41. networkRequest,
42. mConnectivityCallback,
43. 20 * 1000);
44. }
拨号成功后,可利用ifconfig指令查询网卡有没有辨认出来。
https://img-blog.csdnimg.cn/direct/faf7c7fec9104fd69354acaff4d4e2e4.png
9.2 访问
利用第二路访问网络代码:
1. import java.net.URL;
2. import java.net.MalformedURLException;
3. import java.io.IOException;
4. import java.net.URLConnection;
5. import java.io.ByteArrayOutputStream;
6.
7. private String getTest(URLConnection urlConnection) throws IOException {
8. //URL url = new URL(pacUri.toString());
9. //URLConnection urlConnection = url.openConnection(java.net.Proxy.NO_PROXY);
10. long MAX_PAC_SIZE = 20 * 1000 * 1000;
11. long contentLength = -1;
12. try {
13. contentLength = Long.parseLong(urlConnection.getHeaderField("Content-Length"));
14. } catch (NumberFormatException e) {
15. // Ignore
16. }
17. if (contentLength > MAX_PAC_SIZE) {
18. throw new IOException("PAC too big: " + contentLength + " bytes");
19. }
20. ByteArrayOutputStream bytes = new ByteArrayOutputStream();
21. byte[] buffer = new byte;
22. int count;
23. while ((count = urlConnection.getInputStream().read(buffer)) != -1) {
24. bytes.write(buffer, 0, count);
25. if (bytes.size() > MAX_PAC_SIZE) {
26. throw new IOException("PAC too big");
27. }
28. }
29. Log.d(LOG_TAG, "bytes.size() = " + bytes.size());
30. return bytes.toString();
31. }
32.
33. private ConnectivityManager.NetworkCallback createConnectivityCallback(){
34. return new ConnectivityManager.NetworkCallback() {
35. @Override
36. public void onAvailable(Network network) {
37. // Specific to a change to a SUPL enabled network becoming ready
38. Log.d(LOG_TAG, "test network connection available");
39. URL mUrl;
40.
41. try {
42. mUrl = new URL("https://www.baidu.com/");
43. //Log.d(LOG_TAG, "test network mUrl = ", mUrl);
44. getTest(network.openConnection(mUrl));
45. } catch (IOException e) {
46. //throw new MalformedURLException("open()", e, ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
47. Log.d(LOG_TAG, "test network 11");
48. }
49. }
50.
51. @Override
52. public void onLost(Network network) {
53. Log.d(LOG_TAG, "test network connection lost.");
54. }
55.
56. @Override
57. public void onUnavailable() {
58. Log.d(LOG_TAG, "test network connection request timed out.");
59. // Could not setup the connection to the network in the specified time duration.
60.
61. }
62. };
63. }
可通过检察对应网卡的RX TX属性,确认是否从该网卡收发,见如下图。
https://img-blog.csdnimg.cn/direct/d32dde8339a94ec0bd60e206f81745dd.png
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页:
[1]