三、Android 網(wǎng)絡(luò)評(píng)分機(jī)制

在前兩節(jié)簡(jiǎn)單介紹了連接管理的大致框架,數(shù)據(jù)鏈接的準(zhǔn)備工作,包括APN的初始化與默認(rèn)APN使能,DcTracker的構(gòu)造,包括各種事件的注冊(cè)等工作。但是數(shù)據(jù)鏈接的打開不止是只有用戶主動(dòng)去打開,Android可以提供數(shù)據(jù)業(yè)務(wù)的對(duì)象主要有,移動(dòng)數(shù)據(jù)網(wǎng)絡(luò)、WIFI、藍(lán)牙、網(wǎng)線等,這些連接本身都可以獨(dú)立使用,但是對(duì)于用戶來(lái)說(shuō),每一時(shí)刻又最多只能使用一種方式接入網(wǎng)絡(luò),那么當(dāng)這些功能同時(shí)打開時(shí),比如即使用戶打開了移動(dòng)數(shù)據(jù)連接,但是又打開了wifi,那么只要wifi暢通,移動(dòng)數(shù)據(jù)鏈接是不會(huì)用于上網(wǎng)的,那究竟如何選擇最佳的接入環(huán)境呢?這就需要提供一個(gè)能夠動(dòng)態(tài)管理他們的打開與斷開的功能,Android專門設(shè)計(jì)了一套管理方法來(lái)實(shí)現(xiàn)上面的這種機(jī)制,包括ConnectivityManager、ConnectivityService、NetworkAgent等對(duì)象之間的關(guān)系以及消息流走向,本節(jié)在這些知識(shí)的基礎(chǔ)上介紹連接管理的核心機(jī)制,即連接管理中的評(píng)分機(jī)制,其中ConnectivityService是管理員身份,沒種網(wǎng)絡(luò)都會(huì)去向它注冊(cè),網(wǎng)絡(luò)的使用權(quán)全靠它來(lái)分配。

連接管理通過一個(gè)評(píng)分機(jī)制來(lái)實(shí)現(xiàn)不同接入方式的選擇。具體來(lái)說(shuō)就是,每一種上網(wǎng)方式在初始化時(shí),都向ConnectivityService標(biāo)明自己網(wǎng)絡(luò)的分值(比如數(shù)據(jù)連接50,WIFI60,藍(lán)牙69,網(wǎng)線70),當(dāng)有更高分?jǐn)?shù)的網(wǎng)絡(luò)就緒時(shí),就將當(dāng)前分值低的連接斷開。而當(dāng)當(dāng)前網(wǎng)絡(luò)被斷開時(shí),就尋找當(dāng)前就緒的其他網(wǎng)絡(luò)連接,選取分值高的進(jìn)行接入。并且,每一個(gè)網(wǎng)絡(luò)接入時(shí),都會(huì)進(jìn)行有效性檢測(cè),如果檢測(cè)不通過,將會(huì)被扣掉一定分?jǐn)?shù),此時(shí)該網(wǎng)絡(luò)的優(yōu)先級(jí)也會(huì)相應(yīng)的下降。下面我們利用三個(gè)部分來(lái)分析評(píng)分機(jī)制的原理:
1、NetworkFactory
2、NetworkAgent
3、NetworkMonitor
其中NetworkFactory是每一種網(wǎng)絡(luò)持有一個(gè),比如WIFI和Telephony會(huì)分別注冊(cè)一個(gè),但是NetworkAgent和NetworkMonitor是一種數(shù)據(jù)類型就會(huì)有一個(gè),比如數(shù)據(jù)連接總的APN TYPE有8種,其中任意一種鏈接上之后都會(huì)各注冊(cè)一個(gè)。

1、NetworkFactory

NetworkFactory直譯就是網(wǎng)絡(luò)工廠,開機(jī)之后每種網(wǎng)絡(luò)都必須注冊(cè)自己的NetworkFactory,NetworkFactory的作用是用來(lái)創(chuàng)建NetworkAgent,同時(shí)作為ConnectivityService與網(wǎng)絡(luò)之間的通訊樞紐

private DctController(PhoneProxy[] phones) {
    for (int i = 0; i < mPhoneNum; ++i) {
        // Register for radio state change
        PhoneBase phoneBase = (PhoneBase)mPhones[i].getActivePhone();
        updatePhoneBaseForIndex(i, phoneBase);
    }
}    

private void updatePhoneBaseForIndex(int index, PhoneBase phoneBase) {
    phoneBase.getServiceStateTracker().registerForDataConnectionAttached(mRspHandler,
               EVENT_DATA_ATTACHED + index, null);
    phoneBase.getServiceStateTracker().registerForDataConnectionDetached(mRspHandler,
               EVENT_DATA_DETACHED + index, null);

    mNetworkFilter[index] = new NetworkCapabilities();
    mNetworkFilter[index].addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
    mNetworkFilter[index].addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
    mNetworkFilter[index].addCapability(NetworkCapabilities.NET_CAPABILITY_SUPL);
    mNetworkFilter[index].addCapability(NetworkCapabilities.NET_CAPABILITY_DUN);
    mNetworkFilter[index].addCapability(NetworkCapabilities.NET_CAPABILITY_FOTA);
    mNetworkFilter[index].addCapability(NetworkCapabilities.NET_CAPABILITY_IMS);
    mNetworkFilter[index].addCapability(NetworkCapabilities.NET_CAPABILITY_CBS);
    mNetworkFilter[index].addCapability(NetworkCapabilities.NET_CAPABILITY_IA);
    mNetworkFilter[index].addCapability(NetworkCapabilities.NET_CAPABILITY_RCS);
    mNetworkFilter[index].addCapability(NetworkCapabilities.NET_CAPABILITY_XCAP);
    mNetworkFilter[index].addCapability(NetworkCapabilities.NET_CAPABILITY_EIMS);
    mNetworkFilter[index].addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
    mNetworkFilter[index].addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);

    mNetworkFactory[index] = new TelephonyNetworkFactory(this.getLooper(),
            mPhones[index].getContext(), "TelephonyNetworkFactory", phoneBase,
            mNetworkFilter[index]);
    mNetworkFactory[index].setScoreFilter(50);
    mNetworkFactoryMessenger[index] = new Messenger(mNetworkFactory[index]);
    cm.registerNetworkFactory(mNetworkFactoryMessenger[index], "Telephony");
}

可以看出來(lái)一個(gè)NetworkFactory 支持多種網(wǎng)絡(luò)類型(NetworkCapabilities),網(wǎng)絡(luò)類型與APN的TYPE相對(duì)應(yīng)。
以移動(dòng)數(shù)據(jù)網(wǎng)絡(luò)為例,TelephonyNetworkFactory 將會(huì)繼承NetworkFactory ,并重寫其中兩個(gè)重要的方法,needNetworkFor和releaseNetworkFor,這兩個(gè)方法就是ConnectivityService與移動(dòng)網(wǎng)絡(luò)之間橋梁,分別負(fù)責(zé)請(qǐng)求當(dāng)前網(wǎng)絡(luò)和斷開當(dāng)前網(wǎng)絡(luò)。

private class TelephonyNetworkFactory extends NetworkFactory {
    protected void needNetworkFor(NetworkRequest networkRequest, int score) {
        // figure out the apn type and enable it
        if (!SubscriptionManager.isUsableSubIdValue(mPhone.getSubId())) {
            mPendingReq.put(networkRequest.requestId, networkRequest);
            return;
        }
        if (getRequestPhoneId(networkRequest) == mPhone.getPhoneId()) { 
            DcTrackerBase dcTracker =((PhoneBase)mPhone).mDcTracker;
            String apn = apnForNetworkRequest(networkRequest);
            if (dcTracker.isApnSupported(apn)) {
                requestNetwork(networkRequest, dcTracker.getApnPriority(apn));
            }
        } else {
            mPendingReq.put(networkRequest.requestId, networkRequest);
        }
    }  
    protected void releaseNetworkFor(NetworkRequest networkRequest) {
        if (!SubscriptionManager.isUsableSubIdValue(mPhone.getSubId())) {
            mPendingReq.remove(networkRequest.requestId);
            return;
        }
        if (getRequestPhoneId(networkRequest) == mPhone.getPhoneId()) { 
            DcTrackerBase dcTracker =((PhoneBase)mPhone).mDcTracker;
            String apn = apnForNetworkRequest(networkRequest);
            if (dcTracker.isApnSupported(apn)) {
                releaseNetwork(networkRequest);
            }
        }
    }     

再看NetworkFactory 的注冊(cè)cm.registerNetworkFactory(mNetworkFactoryMessenger[index], "Telephony");其中mNetworkFactoryMessenger是一個(gè)包裝了mNetworkFactory的Messenger對(duì)象,這個(gè)主要是建立AsyncChannel通道時(shí)用。

@ConnectivityService.java
public void registerNetworkFactory(Messenger messenger, String name) {
    enforceConnectivityInternalPermission();
    NetworkFactoryInfo nfi = new NetworkFactoryInfo(name, messenger, new AsyncChannel());
    mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_FACTORY, nfi));
}

handleRegisterNetworkFactory處理EVENT_REGISTER_NETWORK_FACTORY消息

private void handleRegisterNetworkFactory(NetworkFactoryInfo nfi) {
    mNetworkFactoryInfos.put(nfi.messenger, nfi);
    nfi.asyncChannel.connect(mContext, mTrackerHandler, nfi.messenger);
}

在這里,ConnectivityService做了兩個(gè)事情:
1、將新注冊(cè)的NetworkFactoryInfo 保存到mNetworkFactoryInfos中;
2、利用剛才創(chuàng)建的AsyncChannel向NetworkAgent發(fā)起單向連接請(qǐng)求;
nfi.asyncChannel.connect(mContext, mTrackerHandler, nfi.messenger);即利用傳入的Messenger對(duì)象建立起ConnectivityService與NetworkFactory的通訊通道,ConnectivityService后續(xù)的消息都將通過這個(gè)asyncChannel傳入到數(shù)據(jù)網(wǎng)絡(luò)中的NetworkFactory。
當(dāng)asyncChannel通道建立成功后ConnectivityService會(huì)收到CMD_CHANNEL_HALF_CONNECTED消息。

@Override
public void handleMessage(Message msg) {
    NetworkInfo info;
    switch (msg.what) {
        case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: {
            handleAsyncChannelHalfConnect(msg);
            break;
        }
}
private void handleAsyncChannelHalfConnect(Message msg) {
    AsyncChannel ac = (AsyncChannel) msg.obj;
    if (mNetworkFactoryInfos.containsKey(msg.replyTo)) {  //此時(shí)是鏈接的是NetworkFactory,走這個(gè)path
        if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
            // A network factory has connected.  Send it all current NetworkRequests.
            for (NetworkRequestInfo nri : mNetworkRequests.values()) {
                if (nri.isRequest == false) continue;
                NetworkAgentInfo nai = mNetworkForRequestId.get(nri.request.requestId);
                ac.sendMessage(android.net.NetworkFactory.CMD_REQUEST_NETWORK,(nai != null ? nai.getCurrentScore() : 0), 0, nri.request);
            }
        } else {
            mNetworkFactoryInfos.remove(msg.obj);
        }
    } else if (mNetworkAgentInfos.containsKey(msg.replyTo)) {

    }
}

此時(shí)是鏈接的是NetworkFactory,走這個(gè)path,mNetworkFactoryInfos是在handleRegisterNetworkFactory時(shí)保存的。
在這里,ConnectivityService通過AsyncChannel通道向當(dāng)前的NetworkFactory發(fā)起CMD_REQUEST_NETWORK的請(qǐng)求,需要注意的是,該請(qǐng)求所附帶的第二個(gè)參數(shù)選擇,由于當(dāng)前處于初始化階段,因此當(dāng)前的mNetworkForRequestId中為空,也就是說(shuō)此時(shí)傳遞的第二個(gè)參數(shù)必然為0。
我們接下來(lái)看NetworkFactory收到該請(qǐng)求時(shí)的處理:

@NetworkFactory.java
public void handleMessage(Message msg) {
    switch (msg.what) {
        case CMD_REQUEST_NETWORK: {
            handleAddRequest((NetworkRequest)msg.obj, msg.arg1);
            break;
        }
    }
}
private void handleAddRequest(NetworkRequest request, int score) {
    NetworkRequestInfo n = mNetworkRequests.get(request.requestId);
    if (n == null) {
        if (DBG) log("got request " + request + " with score " + score);
        n = new NetworkRequestInfo(request, score);
        mNetworkRequests.put(n.request.requestId, n);
    } else {
        n.score = score;
    }
    evalRequest(n);
}

接下來(lái)評(píng)估網(wǎng)絡(luò)評(píng)分,是需要鏈接網(wǎng)絡(luò)還是斷開網(wǎng)路

private void evalRequest(NetworkRequestInfo n) {
    if (n.requested == false && n.score < mScore &&
            n.request.networkCapabilities.satisfiedByNetworkCapabilities(
            mCapabilityFilter) && acceptRequest(n.request, n.score)) {
        needNetworkFor(n.request, n.score);
        n.requested = true;
    } else if (n.requested == true &&
            (n.score > mScore || n.request.networkCapabilities.satisfiedByNetworkCapabilities(
            mCapabilityFilter) == false || acceptRequest(n.request, n.score) == false)) {
        releaseNetworkFor(n.request);
        n.requested = false;
    } 
}

該邏輯就是整個(gè)網(wǎng)絡(luò)評(píng)價(jià)系統(tǒng)最關(guān)鍵的地方,如果NetworkRequestInfo沒有被requested過,并且其分值(n.score)小于當(dāng)前NetworkFactory自己的分值(mScore),那么就說(shuō)明,當(dāng)前NetworkFactory所處的網(wǎng)絡(luò)優(yōu)先級(jí)高于其他網(wǎng)絡(luò)的優(yōu)先級(jí),就會(huì)觸發(fā)當(dāng)前NetworkFactory所在網(wǎng)絡(luò)的needNetworkFor()流程,也就是連接建立流程,并將標(biāo)記NetworkRequestInfo.requested=true。
當(dāng)NetworkRequestInfo被requested過(也就是當(dāng)前網(wǎng)絡(luò)被needNetworkFor過),此時(shí)如果再次收到請(qǐng)求,并且攜帶的新score大于當(dāng)前NetworkFactory所處網(wǎng)絡(luò)的mScore,那么就說(shuō)明當(dāng)前NetworkFactory所在網(wǎng)絡(luò)優(yōu)先級(jí)已經(jīng)不是最高,需要將其releaseNetworkFor掉,并標(biāo)記NetworkRequestInfo.requested=false。

evalRequest中調(diào)用TelephonyNetworkFactory 重寫的needNetworkFor或者releaseNetworkFor,分別是鏈接網(wǎng)絡(luò)和斷開網(wǎng)絡(luò),后續(xù)的流程如下圖(請(qǐng)求網(wǎng)絡(luò)的情況)


這里寫圖片描述

在此數(shù)據(jù)鏈接的NetworkFactory算是創(chuàng)建完畢,并將自己注冊(cè)到ConnectivityService中。

2、NetworkAgent

前面提到NetworkFactory是在系統(tǒng)初始化時(shí)就被創(chuàng)建,而NetworkAgent是在真正接入網(wǎng)絡(luò)時(shí)才會(huì)創(chuàng)建,NetworkAgent的創(chuàng)建在DataConnection狀態(tài)機(jī)里的DcActiveState狀態(tài)時(shí)。

private class DcActiveState extends State {
    @Override public void enter() {
        // If we were retrying there maybe more than one, otherwise they'll only be one.
        notifyAllOfConnected(Phone.REASON_CONNECTED);

        mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED,
                mNetworkInfo.getReason(), null);
        mNetworkInfo.setExtraInfo(mApnSetting.apn);
        updateTcpBufferSizes(mRilRat);

        final NetworkMisc misc = new NetworkMisc();
        misc.subscriberId = mPhone.getSubscriberId();
        mNetworkAgent = new DcNetworkAgent(getHandler().getLooper(), mPhone.getContext(),
                "DcNetworkAgent", mNetworkInfo, makeNetworkCapabilities(), mLinkProperties,
                50, misc);
    }
}
public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni,
        NetworkCapabilities nc, LinkProperties lp, int score, NetworkMisc misc) {
    super(looper);

    mContext = context;
    ConnectivityManager cm = (ConnectivityManager)mContext.getSystemService(
            Context.CONNECTIVITY_SERVICE);
    cm.registerNetworkAgent(new Messenger(this), new NetworkInfo(ni),
            new LinkProperties(lp), new NetworkCapabilities(nc), score, misc);
}  

當(dāng)網(wǎng)絡(luò)鏈接完成之后,就會(huì)新建一個(gè)DcNetworkAgent,接著分析NetworkAgent的構(gòu)造,和NetworkFactory類似,也是將自己注冊(cè)到ConnectivityService中去,繼續(xù)看registerNetworkAgent

public void registerNetworkAgent(Messenger messenger, NetworkInfo networkInfo,
        LinkProperties linkProperties, NetworkCapabilities networkCapabilities,
        int currentScore, NetworkMisc networkMisc) {

    NetworkAgentInfo nai = new NetworkAgentInfo(messenger, new AsyncChannel(),
        new NetworkInfo(networkInfo), new LinkProperties(linkProperties),
        new NetworkCapabilities(networkCapabilities), currentScore, mContext, mTrackerHandler,
        new NetworkMisc(networkMisc), mDefaultRequest);
    synchronized (this) {
        nai.networkMonitor.systemReady = mSystemReady;
    }
    mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_AGENT, nai));
}

private void handleRegisterNetworkAgent(NetworkAgentInfo na) {
    mNetworkAgentInfos.put(na.messenger, na);
    assignNextNetId(na);
    na.asyncChannel.connect(mContext, mTrackerHandler, na.messenger);
    NetworkInfo networkInfo = na.networkInfo;
    na.networkInfo = null;
    updateNetworkInfo(na, networkInfo);
}

在這里,ConnectivityService做了三個(gè)事情:
1、將新注冊(cè)的NetworkAgentInfo保存到mNetworkAgentInfos中;
2、利用剛才創(chuàng)建的AsyncChannel向NetworkAgent發(fā)起單向連接請(qǐng)求;
3、更新最新的NetworkAgentInfo狀態(tài);

@Override
public void handleMessage(Message msg) {
    NetworkInfo info;
    switch (msg.what) {
        case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: {
            handleAsyncChannelHalfConnect(msg);
            break;
        }
}

以上流程和NetworkFactory注冊(cè)時(shí)幾乎一模一樣的模式

private void handleAsyncChannelHalfConnect(Message msg) {
    AsyncChannel ac = (AsyncChannel) msg.obj;
    if (mNetworkFactoryInfos.containsKey(msg.replyTo)) {  

    }  else if (mNetworkAgentInfos.containsKey(msg.replyTo)) {  //此時(shí)是鏈接的是NetworkAgent,走這個(gè)path
        if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
            // A network agent has requested a connection.  Establish the connection.
            mNetworkAgentInfos.get(msg.replyTo).asyncChannel.
                    sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION);
        } 
    }
}

唯一的區(qū)別是在handleAsyncChannelHalfConnect中這里,當(dāng)ConnectivityService與NetworkAgent之間單向通道建立完成后,又發(fā)起了雙向通道的請(qǐng)求,此時(shí)在NetworkAgent端,將會(huì)收到CMD_CHANNEL_FULL_CONNECTION的消息,建立雙向通道的目的是,有時(shí)候網(wǎng)絡(luò)也需要通過AsyncChannel向ConnectivityService發(fā)送消息。至此,NetworkAgent的初始化完畢。
現(xiàn)在的問題是NetworkAgent如何影響網(wǎng)絡(luò)鏈接的?
NetworkAgent提供了兩種方法更新評(píng)分管理:
1、sendNetworkScore

public void sendNetworkScore(int score) {
    queueOrSendMessage(EVENT_NETWORK_SCORE_CHANGED, new Integer(score));
}

2、sendNetworkInfo

public void sendNetworkInfo(NetworkInfo networkInfo) {
    queueOrSendMessage(EVENT_NETWORK_INFO_CHANGED, new NetworkInfo(networkInfo));
}

先來(lái)分析第二種情況,比如移動(dòng)數(shù)據(jù)網(wǎng)絡(luò)的斷開時(shí)就會(huì)調(diào)用此方法:

@DataConnection.java
private class DcActiveState extends State {
    public void exit() {
        mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.DISCONNECTED,
                mNetworkInfo.getReason(), mNetworkInfo.getExtraInfo());
        mNetworkAgent.sendNetworkInfo(mNetworkInfo);
        mNetworkAgent = null;
    }
}

接著就會(huì)進(jìn)入ConnectivityService

@Override
public void handleMessage(Message msg) {
    NetworkInfo info;
        case NetworkAgent.EVENT_NETWORK_INFO_CHANGED: {
            NetworkAgentInfo nai = mNetworkAgentInfos.get(msg.replyTo);
            info = (NetworkInfo) msg.obj;
            updateNetworkInfo(nai, info);
            break;
        }
}
private void updateNetworkInfo(NetworkAgentInfo networkAgent, NetworkInfo newInfo) {
    if (state == NetworkInfo.State.CONNECTED && !networkAgent.created) {

    } else if (state == NetworkInfo.State.DISCONNECTED || state == NetworkInfo.State.SUSPENDED) {
        networkAgent.asyncChannel.disconnect();        
    }   

由于是斷開數(shù)據(jù)網(wǎng)絡(luò),因此這里是斷開AsyncChannel,從而進(jìn)入

AsyncChannel.CMD_CHANNEL_DISCONNECTED
        @Override
        public void handleMessage(Message msg) {
            NetworkInfo info;
            switch (msg.what) {
                case AsyncChannel.CMD_CHANNEL_DISCONNECTED: {
                    handleAsyncChannelDisconnected(msg);
                    break;
                }
        }
private void handleAsyncChannelDisconnected(Message msg) {  
    NetworkAgentInfo nai = mNetworkAgentInfos.get(msg.replyTo);  
    if (nai != null) {  
        //刪掉當(dāng)前NetworkAgent對(duì)象  
        mNetworkAgentInfos.remove(msg.replyTo);  
        final ArrayList<NetworkAgentInfo> toActivate = new ArrayList<NetworkAgentInfo>();  
        for (int i = 0; i < nai.networkRequests.size(); i++) {  
            NetworkRequest request = nai.networkRequests.valueAt(i);  
            NetworkAgentInfo currentNetwork = mNetworkForRequestId.get(request.requestId);  
            if (currentNetwork != null && currentNetwork.network.netId == nai.network.netId) {  
                mNetworkForRequestId.remove(request.requestId);  
                //將0分更新到各個(gè)NetworkFactory中  
                sendUpdatedScoreToFactories(request, 0);  
            }  
        }  
    }  
}  
private void sendUpdatedScoreToFactories(NetworkRequest networkRequest, int score) {
    for (NetworkFactoryInfo nfi : mNetworkFactoryInfos.values()) {
        nfi.asyncChannel.sendMessage(android.net.NetworkFactory.CMD_REQUEST_NETWORK, score, 0,networkRequest);
    }
}

在這里,由于當(dāng)前連接是斷開狀態(tài),因此其分值必然為0,這樣就把他的0分值通知到各個(gè)NetworkFactory中,由NetworkFactory判斷是否需要開啟自己的網(wǎng)絡(luò),通知方法同樣是CMD_REQUEST_NETWORK,也就是說(shuō),無(wú)論是直接更新NetworkAgent中的分?jǐn)?shù),還是更新NetworkAgent的狀態(tài),最終都會(huì)觸發(fā)NetworkFactory中的評(píng)分機(jī)制。

3、NetworkMonitor

NetworkMonitor的構(gòu)造是在注冊(cè)NetworkAgent,構(gòu)造NetworkAgentInfo是創(chuàng)建的,其實(shí)質(zhì)ping網(wǎng)絡(luò)是在updateNetworkInfo中,細(xì)節(jié)不分析,但是NetworkMonitor對(duì)網(wǎng)絡(luò)可用性的評(píng)分是有影響的,即當(dāng)網(wǎng)絡(luò)鏈接上之后,會(huì)去ping當(dāng)前網(wǎng)絡(luò)是否可用,如果不可用則會(huì)影響getCurrentScore獲取的分?jǐn)?shù)值,getCurrentScore是每次網(wǎng)絡(luò)評(píng)分獲取的分?jǐn)?shù)的必經(jīng)之路:

private int getCurrentScore(boolean pretendValidated) {
    int score = currentScore;

    if (!everValidated && !pretendValidated) score -= UNVALIDATED_SCORE_PENALTY;
    if (score < 0) score = 0;

    if (networkMisc.explicitlySelected) score = EXPLICITLY_SELECTED_NETWORK_SCORE;

    return score;
}

當(dāng)一個(gè)網(wǎng)絡(luò)連接建立時(shí),系統(tǒng)將用該連接Ping一個(gè)Google的網(wǎng)站來(lái)判斷該連接是否真的可以上網(wǎng),如果不可以,那么就會(huì)扣掉該網(wǎng)絡(luò)40分,從而可能導(dǎo)致該網(wǎng)絡(luò)的評(píng)分低于其他網(wǎng)絡(luò)評(píng)分
如果是用戶指定了網(wǎng)絡(luò)那么分?jǐn)?shù)直接等于EXPLICITLY_SELECTED_NETWORK_SCORE(100分)
至此網(wǎng)絡(luò)評(píng)分就分析完畢

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • 國(guó)家電網(wǎng)公司企業(yè)標(biāo)準(zhǔn)(Q/GDW)- 面向?qū)ο蟮挠秒娦畔?shù)據(jù)交換協(xié)議 - 報(bào)批稿:20170802 前言: 排版 ...
    庭說(shuō)閱讀 11,166評(píng)論 6 13
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 134,948評(píng)論 18 139
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 173,372評(píng)論 25 708
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫(kù)、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,245評(píng)論 4 61
  • 1.read命令 1.等待輸入的值,賦值給read后面的變量printf "請(qǐng)輸入一個(gè)數(shù): "read nump...
    抬頭向前看閱讀 118評(píng)論 0 0