精华内容
下载资源
问答
  • 此模式为数据传输状态,所有输入输出数据(除逃逸字符以外)均进行透明传输处理,模块仅作为串口无线网络之间的数据通路。在此模式下,只有一条虚拟的数据收发通路处于激活状态,即: 当使用tcp连接时,只有一个...
  • WIFI热点释放功能依赖于Java反射机制,逆向解析并调用WIFI Manager类中的方法去实现热点的打开、关闭和状态管理。【2使用Java反射机制逆向分析类方法之间的关系DOI:10.16184/j.cnki.comprg.2016.19.006 分类号:TP...
  • 同时接入多个设备,小伙伴们分享WiFi网络 宿舍兄弟上网账号没流量,出差酒店没WiFi,自习室里只有网线口... 赶紧用小米随身WiFi创建WiFi网络,分享给你的小伙伴们。 插上、连接、上网!创建WiFi就这么简单 插...
  • WiFi探针在商用领域可以大放异彩,不仅是因为它能够提供相关的有效的客流数据同时它可以打开系统之间、数据之间的壁垒,通过解决相应的技术难题,将顾客的MAC地址企业的CRM系统、收银系统进行对接,数据间的配合...

    WiFi探针在商用领域可以大放异彩,不仅是因为它能够提供相关的有效的客流数据,同时它可以打开系统之间、数据之间的壁垒,通过解决相应的技术难题,将顾客的MAC地址与企业的CRM系统、收银系统进行对接,数据间的配合找出顾客的信息,实现真正的线下的精准营销。


    假如客户进店你第一时间就能获取客户信息,这样的系统能给你带来多大的价值呢?

    假如客户路过你的店门口就能收到你们店铺的优惠信息,这样的系统能给你带来多大的价值呢?

    线下商业的运营一直缺少有效的数据支持,尤其是客户数据的支持,众多的商家有大量的消费数据累计,有众多的会员人员。但是如何使这些数据进行相互的联系,数据建立起联系将产生多少的效益?


    此时中科爱讯WiFi探针帮助商业系统的集成商及企业撕开了这个商业难题的口子,让企业内部的数据与探针数据进行匹配,让巨大的数据库能够动起来,发挥数据的力量,用数据来运营商业,数据来激活商业。


    中科爱讯Wi-Fi探针为线下企业精准营销提供了基础数据,将采集到的顾客手机MAC地址数据与顾客的虚拟身份、线上数据、消费数据等相互关联,可建立顾客完整的线下信息。


    业务需求

    线下营销缺乏运营数据的支持,无法完整的获取客户的人群画像、消费喜好等信息,致使无法有效的解决营销难、成本高的难题。


    产品特点

    1、 精准识别:在客户无感知场景下,快速的精准识别客户手机MAC地址;

    2、 匹配第三方数据:MAC地址可作为基础的身份识别,配合第三方数据,如消费信息、线上信息等数据;

    3、 行为分析:可形成热力图、行为轨迹、产品关注度等行为分析,结合行为分析和第三方数据,可形成完整的消费者画像;


    解决方案

    l  将探针模块通过串口/USB嵌入到已有的营销设备中(比如:收银机、POS机、摄像头等),探针通过已有的营销设备将数据上传到服务器后台与其他的营销数据进行打通融合,如CRM系统中的顾客信息、顾客的线上信息等。

    l  前端数据的展现可以植入已有的APP或Web端。可实现消费者画像、消费习惯分析、客流数据统计分析等功能。


    行业架构



    来就推--线下门店精准营销系统

    来就推营销系统由深圳中科爱讯科技有限公司推出,来就推可以精准的将进店的顾客信息实时推送到店员、店长手机,店员可以通过推送的消息,了解到顾客的个人信息、进店信息、消费记录、消费标签、消费历史等数据。通过精准详细的数据协助企业提升顾客体验度及满意度。




    来就推详细功能



    如何实现客户一进店就推送信息?



    来就推怎么和集成商、企业合作使用?



    当然中科爱讯WiFi探针也可以应用到更多的商业推送领域:



    产品选型及帮助

    Wi-Fi探针TZ-1002 嵌入式模块  

    Wi-Fi探针TZ-007 USB口智能探针



    展开全文
  • 打开本手机APP,点击登录,跳出成功连接,然后会自动跳转到控制界面,轻点一下“开关按钮”,灯会被打开同时模块会向手机终端返回“灯亮”,反之...... 硬件连接及注意事项: 1.单片机型号为stc15w408as。其他型号...
  • 本系统通过在系统服务端家电设备之间添加网关设备以连接不同通信方式的家电设备,将设备信息规格化通过 Wifi 通信上传到系统服务端,以此解决硬件上的异构性。在信息整合上采用元编程的方式解决信息上的异构性,...
  • 四、 Android 数据业务APN参数的创建

    千次阅读 2016-12-20 18:18:48
    在前两节简单介绍了连接管理的大致框架,数据链接的准备工作,包括APN的初始化默认APN使能,DcTracker的构造,包括各种事件的注册等工作。但是数据链接的打开不止是...那么当这些功能同时打开时,比如即使用户打开了

    前面在DcTracker初始化过程中注册了大量监听器,其中有两个监听器可以触发APN的创建过程:1、SIM载入完毕;2、APN改变。其中SIM载入完毕的注册是EVENT_RECORDS_LOADED事件,APN改变是注册了一个ApnChangeObserver类来监听。
    当SIM载入完毕时,将会触发onRecordsLoaded()

    private void onRecordsLoaded() {
        logi("onRecordsLoaded: createAllApnList");
        mAutoAttachOnCreationConfig = mPhone.getContext().getResources()
                .getBoolean(com.android.internal.R.bool.config_auto_attach_data_on_creation);
    
        createAllApnList();
        setInitialAttachApn();
        if (mPhone.mCi.getRadioState().isOn()) {
            if (DBG) log("onRecordsLoaded: notifying data availability");
            notifyOffApnsOfAvailability(Phone.REASON_SIM_LOADED);
        }
        setupDataOnConnectableApns(Phone.REASON_SIM_LOADED);
    }

    当APN改变时,用户指定APN,将会触发onApnChanged()

    /**
     * Handles changes to the APN database.
     */
    private void onApnChanged() {
        DctConstants.State overallState = getOverallState();
        boolean isDisconnected = (overallState == DctConstants.State.IDLE ||
                overallState == DctConstants.State.FAILED);
    
        createAllApnList();
        setInitialAttachApn();
        cleanUpConnectionsOnUpdatedApns(!isDisconnected);
    
        // FIXME: See bug 17426028 maybe no conditional is needed.
        if (mPhone.getSubId() == SubscriptionManager.getDefaultDataSubId()) {
            setupDataOnConnectableApns(Phone.REASON_APN_CHANGED);
        }
    }

    两个事件都会调用createAllApnList()和setInitialAttachApn(),分别是初始化当前卡可用的所有APN和设置默认联网用的APN,首先看createAllApnList()

    private void createAllApnList() {
        mAllApnSettings = new ArrayList<ApnSetting>();
        IccRecords r = mIccRecords.get();
        String operator = (r != null) ? r.getOperatorNumeric() : "";
        if (operator != null) {
            String selection = "numeric = '" + operator + "'";
            Cursor cursor = mPhone.getContext().getContentResolver().query(
                    Telephony.Carriers.CONTENT_URI, null, selection, null, null);
            if (cursor != null) {
                if (cursor.getCount() > 0) {
                    mAllApnSettings = createApnList(cursor);
                }
                cursor.close();
            }
        }
    
        addEmergencyApnSetting(); // 添加emergencyApnSettings
        dedupeApnSettings();      // 去除重复的APN
        if (mAllApnSettings.isEmpty()) {
            mPreferredApn = null;
        } else {
            mPreferredApn = getPreferredApn();
            if (mPreferredApn != null && !mPreferredApn.numeric.equals(operator)) {
                mPreferredApn = null;
                setPreferredApn(-1);
            }
        }
        setDataProfilesAsNeeded();
    }

    这里面主要做了三件事
    1、创建一个APN的列表,其中包含:当前SIM对应的APN、紧急APN;
    APN的来源是telephony.db数据库中表carries,数据库的的参数是更新于apns-conf.xml文件
    2、合并相同的APN;
    在apns-conf.xml中的APN有可能又重复的
    3、寻找一个当前Prefer的APN参数;
    用户使用一张卡时,可能手动选择过使用的APN,因此,当用户再次插拔卡后,getPreferredApn用于找出用户之前选择的APN
    这个mPreferredApn会在buildWaitingApns中被检查
    如果mPreferredApn满足用户数据链接的需求,那么buildWaitingApns就直接会返回mPreferredApn用于联网使用的APN
    如果mPreferredApn已经不能满足用户数据链接的需求时,才会从mAllApnSettings(createAllApnList)中去找合适的APN用于联网

    这就是为什么setupData中getNextWaitingApn要去拿list的第0个APN联网,因为当mPreferredApn有效时,只会有一个APN存在apnContext中
    以上就是APN的初始化和设置默认值

    展开全文
  • IPhone条形码数据枪是一个利用摄像头读取各种条码,通过wifi实时的将数据传送到电脑上的,拥有该软件,您就拥有了一把高性能无线条码枪,属于扩展性极强的IPhone应用软件。 本软件可以扫描条形码,一维码,二维码,...
  • Android 网络评分机制

    2020-12-25 14:31:29
    在前两节简单介绍了连接管理的大致框架,数据链接的准备...那么当这些功能同时打开时,比如即使用户打开了移动数据连接,但是又打开了wifi,那么只要wifi畅通,移动数据链接是不会用于上网的,那究竟如何选择最佳的接

    在前两节简单介绍了连接管理的大致框架,数据链接的准备工作,包括APN的初始化与默认APN使能,DcTracker的构造,包括各种事件的注册等工作。但是数据链接的打开不止是只有用户主动去打开,Android可以提供数据业务的对象主要有,移动数据网络、WIFI、蓝牙、网线等,这些连接本身都可以独立使用,但是对于用户来说,每一时刻又最多只能使用一种方式接入网络,那么当这些功能同时打开时,比如即使用户打开了移动数据连接,但是又打开了wifi,那么只要wifi畅通,移动数据链接是不会用于上网的,那究竟如何选择最佳的接入环境呢?这就需要提供一个能够动态管理他们的打开与断开的功能,Android专门设计了一套管理方法来实现上面的这种机制,包括ConnectivityManager、ConnectivityService、NetworkAgent等对象之间的关系以及消息流走向,本节在这些知识的基础上介绍连接管理的核心机制,即连接管理中的评分机制,其中ConnectivityService是管理员身份,没种网络都会去向它注册,网络的使用权全靠它来分配。

    连接管理通过一个评分机制来实现不同接入方式的选择。具体来说就是,每一种上网方式在初始化时,都向ConnectivityService标明自己网络的分值(比如数据连接50,WIFI60,蓝牙69,网线70),当有更高分数的网络就绪时,就将当前分值低的连接断开。而当当前网络被断开时,就寻找当前就绪的其他网络连接,选取分值高的进行接入。并且,每一个网络接入时,都会进行有效性检测,如果检测不通过,将会被扣掉一定分数,此时该网络的优先级也会相应的下降。下面我们利用三个部分来分析评分机制的原理:
    1、NetworkFactory
    2、NetworkAgent
    3、NetworkMonitor
    其中NetworkFactory是每一种网络持有一个,比如WIFI和Telephony会分别注册一个,但是NetworkAgent和NetworkMonitor是一种数据类型就会有一个,比如数据连接总的APN TYPE有8种,其中任意一种链接上之后都会各注册一个。

    1、NetworkFactory

    NetworkFactory直译就是网络工厂,开机之后每种网络都必须注册自己的NetworkFactory,NetworkFactory的作用是用来创建NetworkAgent,同时作为ConnectivityService与网络之间的通讯枢纽

    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");
    }
    
    

    可以看出来一个NetworkFactory 支持多种网络类型(NetworkCapabilities),网络类型与APN的TYPE相对应。
    以移动数据网络为例,TelephonyNetworkFactory 将会继承NetworkFactory ,并重写其中两个重要的方法,needNetworkFor和releaseNetworkFor,这两个方法就是ConnectivityService与移动网络之间桥梁,分别负责请求当前网络和断开当前网络。

    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 的注册cm.registerNetworkFactory(mNetworkFactoryMessenger[index], "Telephony");其中mNetworkFactoryMessenger是一个包装了mNetworkFactory的Messenger对象,这个主要是建立AsyncChannel通道时用。

    @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做了两个事情:
    1、将新注册的NetworkFactoryInfo 保存到mNetworkFactoryInfos中;
    2、利用刚才创建的AsyncChannel向NetworkAgent发起单向连接请求;
    nfi.asyncChannel.connect(mContext, mTrackerHandler, nfi.messenger);即利用传入的Messenger对象建立起ConnectivityService与NetworkFactory的通讯通道,ConnectivityService后续的消息都将通过这个asyncChannel传入到数据网络中的NetworkFactory。
    当asyncChannel通道建立成功后ConnectivityService会收到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)) {  //此时是链接的是NetworkFactory,走这个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)) {
    
        }
    }
    

    此时是链接的是NetworkFactory,走这个path,mNetworkFactoryInfos是在handleRegisterNetworkFactory时保存的。
    在这里,ConnectivityService通过AsyncChannel通道向当前的NetworkFactory发起CMD_REQUEST_NETWORK的请求,需要注意的是,该请求所附带的第二个参数选择,由于当前处于初始化阶段,因此当前的mNetworkForRequestId中为空,也就是说此时传递的第二个参数必然为0。
    我们接下来看NetworkFactory收到该请求时的处理:

    @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);
    }
    

    接下来评估网络评分,是需要链接网络还是断开网路

    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;
        } 
    }
    

    该逻辑就是整个网络评价系统最关键的地方,如果NetworkRequestInfo没有被requested过,并且其分值(n.score)小于当前NetworkFactory自己的分值(mScore),那么就说明,当前NetworkFactory所处的网络优先级高于其他网络的优先级,就会触发当前NetworkFactory所在网络的needNetworkFor()流程,也就是连接建立流程,并将标记NetworkRequestInfo.requested=true。
    当NetworkRequestInfo被requested过(也就是当前网络被needNetworkFor过),此时如果再次收到请求,并且携带的新score大于当前NetworkFactory所处网络的mScore,那么就说明当前NetworkFactory所在网络优先级已经不是最高,需要将其releaseNetworkFor掉,并标记NetworkRequestInfo.requested=false。

    evalRequest中调用TelephonyNetworkFactory 重写的needNetworkFor或者releaseNetworkFor,分别是链接网络和断开网络,后续的流程如下图(请求网络的情况)

     

    这里写图片描述

     

    在此数据链接的NetworkFactory算是创建完毕,并将自己注册到ConnectivityService中。

    2、NetworkAgent

    前面提到NetworkFactory是在系统初始化时就被创建,而NetworkAgent是在真正接入网络时才会创建,NetworkAgent的创建在DataConnection状态机里的DcActiveState状态时。

    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);
    }  
    

    当网络链接完成之后,就会新建一个DcNetworkAgent,接着分析NetworkAgent的构造,和NetworkFactory类似,也是将自己注册到ConnectivityService中去,继续看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做了三个事情:
    1、将新注册的NetworkAgentInfo保存到mNetworkAgentInfos中;
    2、利用刚才创建的AsyncChannel向NetworkAgent发起单向连接请求;
    3、更新最新的NetworkAgentInfo状态;

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

    以上流程和NetworkFactory注册时几乎一模一样的模式

    private void handleAsyncChannelHalfConnect(Message msg) {
        AsyncChannel ac = (AsyncChannel) msg.obj;
        if (mNetworkFactoryInfos.containsKey(msg.replyTo)) {  
    
        }  else if (mNetworkAgentInfos.containsKey(msg.replyTo)) {  //此时是链接的是NetworkAgent,走这个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);
            } 
        }
    }
    

    唯一的区别是在handleAsyncChannelHalfConnect中这里,当ConnectivityService与NetworkAgent之间单向通道建立完成后,又发起了双向通道的请求,此时在NetworkAgent端,将会收到CMD_CHANNEL_FULL_CONNECTION的消息,建立双向通道的目的是,有时候网络也需要通过AsyncChannel向ConnectivityService发送消息。至此,NetworkAgent的初始化完毕。
    现在的问题是NetworkAgent如何影响网络链接的?
    NetworkAgent提供了两种方法更新评分管理:
    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));
    }
    

    先来分析第二种情况,比如移动数据网络的断开时就会调用此方法:

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

    接着就会进入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();        
        }   
    

    由于是断开数据网络,因此这里是断开AsyncChannel,从而进入

    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) {  
            //删掉当前NetworkAgent对象  
            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分更新到各个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);
        }
    }
    

    在这里,由于当前连接是断开状态,因此其分值必然为0,这样就把他的0分值通知到各个NetworkFactory中,由NetworkFactory判断是否需要开启自己的网络,通知方法同样是CMD_REQUEST_NETWORK,也就是说,无论是直接更新NetworkAgent中的分数,还是更新NetworkAgent的状态,最终都会触发NetworkFactory中的评分机制。

    3、NetworkMonitor

    NetworkMonitor的构造是在注册NetworkAgent,构造NetworkAgentInfo是创建的,其实质ping网络是在updateNetworkInfo中,细节不分析,但是NetworkMonitor对网络可用性的评分是有影响的,即当网络链接上之后,会去ping当前网络是否可用,如果不可用则会影响getCurrentScore获取的分数值,getCurrentScore是每次网络评分获取的分数的必经之路:

    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;
    }
    

    当一个网络连接建立时,系统将用该连接Ping一个Google的网站来判断该连接是否真的可以上网,如果不可以,那么就会扣掉该网络40分,从而可能导致该网络的评分低于其他网络评分
    如果是用户指定了网络那么分数直接等于EXPLICITLY_SELECTED_NETWORK_SCORE(100分)
    至此网络评分就分析完毕

    链接:https://www.jianshu.com/p/541a21bf82d6

    展开全文
  • 5.12 自制打开或关闭wifi 210 5.13 还原手机桌面背景 214 5.14 设置手机桌面背景 216 5.15 轻松获取手机桌面背景 217 5.16 轻松查看手机的相关信息 219 5.17 查看sim卡的信详细息 223 5.18 按键移动图片...
  • 三、Android 网络评分机制

    千次阅读 2016-12-20 18:15:03
    在前两节简单介绍了连接管理的大致框架,数据链接的准备工作,包括APN的初始化默认APN使能,DcTracker的构造,包括各种事件的注册等工作。但是数据链接的打开不止是...那么当这些功能同时打开时,比如即使用户打开了

    在前两节简单介绍了连接管理的大致框架,数据链接的准备工作,包括APN的初始化与默认APN使能,DcTracker的构造,包括各种事件的注册等工作。但是数据链接的打开不止是只有用户主动去打开,Android可以提供数据业务的对象主要有,移动数据网络、WIFI、蓝牙、网线等,这些连接本身都可以独立使用,但是对于用户来说,每一时刻又最多只能使用一种方式接入网络,那么当这些功能同时打开时,比如即使用户打开了移动数据连接,但是又打开了wifi,那么只要wifi畅通,移动数据链接是不会用于上网的,那究竟如何选择最佳的接入环境呢?这就需要提供一个能够动态管理他们的打开与断开的功能,Android专门设计了一套管理方法来实现上面的这种机制,包括ConnectivityManager、ConnectivityService、NetworkAgent等对象之间的关系以及消息流走向,本节在这些知识的基础上介绍连接管理的核心机制,即连接管理中的评分机制,其中ConnectivityService是管理员身份,没种网络都会去向它注册,网络的使用权全靠它来分配。

    连接管理通过一个评分机制来实现不同接入方式的选择。具体来说就是,每一种上网方式在初始化时,都向ConnectivityService标明自己网络的分值(比如数据连接50,WIFI60,蓝牙69,网线70),当有更高分数的网络就绪时,就将当前分值低的连接断开。而当当前网络被断开时,就寻找当前就绪的其他网络连接,选取分值高的进行接入。并且,每一个网络接入时,都会进行有效性检测,如果检测不通过,将会被扣掉一定分数,此时该网络的优先级也会相应的下降。下面我们利用三个部分来分析评分机制的原理:
    1、NetworkFactory
    2、NetworkAgent
    3、NetworkMonitor
    其中NetworkFactory是每一种网络持有一个,比如WIFI和Telephony会分别注册一个,但是NetworkAgent和NetworkMonitor是一种数据类型就会有一个,比如数据连接总的APN TYPE有8种,其中任意一种链接上之后都会各注册一个。

    1、NetworkFactory

    NetworkFactory直译就是网络工厂,开机之后每种网络都必须注册自己的NetworkFactory,NetworkFactory的作用是用来创建NetworkAgent,同时作为ConnectivityService与网络之间的通讯枢纽

    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");
    }
    

    可以看出来一个NetworkFactory 支持多种网络类型(NetworkCapabilities),网络类型与APN的TYPE相对应。
    以移动数据网络为例,TelephonyNetworkFactory 将会继承NetworkFactory ,并重写其中两个重要的方法,needNetworkFor和releaseNetworkFor,这两个方法就是ConnectivityService与移动网络之间桥梁,分别负责请求当前网络和断开当前网络。

    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 的注册cm.registerNetworkFactory(mNetworkFactoryMessenger[index], “Telephony”);其中mNetworkFactoryMessenger是一个包装了mNetworkFactory的Messenger对象,这个主要是建立AsyncChannel通道时用。

    @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做了两个事情:
    1、将新注册的NetworkFactoryInfo 保存到mNetworkFactoryInfos中;
    2、利用刚才创建的AsyncChannel向NetworkAgent发起单向连接请求;
    nfi.asyncChannel.connect(mContext, mTrackerHandler, nfi.messenger);即利用传入的Messenger对象建立起ConnectivityService与NetworkFactory的通讯通道,ConnectivityService后续的消息都将通过这个asyncChannel传入到数据网络中的NetworkFactory。
    当asyncChannel通道建立成功后ConnectivityService会收到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)) {  //此时是链接的是NetworkFactory,走这个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)) {
    
        }
    }

    此时是链接的是NetworkFactory,走这个path,mNetworkFactoryInfos是在handleRegisterNetworkFactory时保存的。
    在这里,ConnectivityService通过AsyncChannel通道向当前的NetworkFactory发起CMD_REQUEST_NETWORK的请求,需要注意的是,该请求所附带的第二个参数选择,由于当前处于初始化阶段,因此当前的mNetworkForRequestId中为空,也就是说此时传递的第二个参数必然为0。
    我们接下来看NetworkFactory收到该请求时的处理:

    @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);
    }

    接下来评估网络评分,是需要链接网络还是断开网路

    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;
        } 
    }

    该逻辑就是整个网络评价系统最关键的地方,如果NetworkRequestInfo没有被requested过,并且其分值(n.score)小于当前NetworkFactory自己的分值(mScore),那么就说明,当前NetworkFactory所处的网络优先级高于其他网络的优先级,就会触发当前NetworkFactory所在网络的needNetworkFor()流程,也就是连接建立流程,并将标记NetworkRequestInfo.requested=true。
    当NetworkRequestInfo被requested过(也就是当前网络被needNetworkFor过),此时如果再次收到请求,并且携带的新score大于当前NetworkFactory所处网络的mScore,那么就说明当前NetworkFactory所在网络优先级已经不是最高,需要将其releaseNetworkFor掉,并标记NetworkRequestInfo.requested=false。

    evalRequest中调用TelephonyNetworkFactory 重写的needNetworkFor或者releaseNetworkFor,分别是链接网络和断开网络,后续的流程如下图(请求网络的情况)
    这里写图片描述
    在此数据链接的NetworkFactory算是创建完毕,并将自己注册到ConnectivityService中。

    2、NetworkAgent

    前面提到NetworkFactory是在系统初始化时就被创建,而NetworkAgent是在真正接入网络时才会创建,NetworkAgent的创建在DataConnection状态机里的DcActiveState状态时。

    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);
    }  

    当网络链接完成之后,就会新建一个DcNetworkAgent,接着分析NetworkAgent的构造,和NetworkFactory类似,也是将自己注册到ConnectivityService中去,继续看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做了三个事情:
    1、将新注册的NetworkAgentInfo保存到mNetworkAgentInfos中;
    2、利用刚才创建的AsyncChannel向NetworkAgent发起单向连接请求;
    3、更新最新的NetworkAgentInfo状态;

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

    以上流程和NetworkFactory注册时几乎一模一样的模式

    private void handleAsyncChannelHalfConnect(Message msg) {
        AsyncChannel ac = (AsyncChannel) msg.obj;
        if (mNetworkFactoryInfos.containsKey(msg.replyTo)) {  
    
        }  else if (mNetworkAgentInfos.containsKey(msg.replyTo)) {  //此时是链接的是NetworkAgent,走这个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);
            } 
        }
    }

    唯一的区别是在handleAsyncChannelHalfConnect中这里,当ConnectivityService与NetworkAgent之间单向通道建立完成后,又发起了双向通道的请求,此时在NetworkAgent端,将会收到CMD_CHANNEL_FULL_CONNECTION的消息,建立双向通道的目的是,有时候网络也需要通过AsyncChannel向ConnectivityService发送消息。至此,NetworkAgent的初始化完毕。
    现在的问题是NetworkAgent如何影响网络链接的?
    NetworkAgent提供了两种方法更新评分管理:
    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));
    }

    先来分析第二种情况,比如移动数据网络的断开时就会调用此方法:

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

    接着就会进入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();        
        }   

    由于是断开数据网络,因此这里是断开AsyncChannel,从而进入

    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) {  
            //删掉当前NetworkAgent对象  
            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分更新到各个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);
        }
    }

    在这里,由于当前连接是断开状态,因此其分值必然为0,这样就把他的0分值通知到各个NetworkFactory中,由NetworkFactory判断是否需要开启自己的网络,通知方法同样是CMD_REQUEST_NETWORK,也就是说,无论是直接更新NetworkAgent中的分数,还是更新NetworkAgent的状态,最终都会触发NetworkFactory中的评分机制。

    3、NetworkMonitor

    NetworkMonitor的构造是在注册NetworkAgent,构造NetworkAgentInfo是创建的,其实质ping网络是在updateNetworkInfo中,细节不分析,但是NetworkMonitor对网络可用性的评分是有影响的,即当网络链接上之后,会去ping当前网络是否可用,如果不可用则会影响getCurrentScore获取的分数值,getCurrentScore是每次网络评分获取的分数的必经之路:

    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;
    }

    当一个网络连接建立时,系统将用该连接Ping一个Google的网站来判断该连接是否真的可以上网,如果不可以,那么就会扣掉该网络40分,从而可能导致该网络的评分低于其他网络评分
    如果是用户指定了网络那么分数直接等于EXPLICITLY_SELECTED_NETWORK_SCORE(100分)
    至此网络评分就分析完毕

    展开全文
  • 程序+论文+PPT+资料.rar

    2019-06-24 00:56:23
    作品上电后,初始化装置各个模块,DHT11数据脚连接单片机一脚处于推挽输出;让烟雾浓度MQ-2输出模拟电压的引脚连接到... 同时通过WiFi模块onenet中移物联网平台连接,把数据上传到互联网平台,实现远程监控控制。
  • 要求手机能同时接收到多块esp发送来的数据(esp每秒发送一次自己的运行时间数据),显示在手机app里面。手机app能区分数据是来自哪一块esp的,同时能分别控制它们是否暂停和继续发送数据,或者控制设备重启。app要求...
  • PC上位机正确接受数据,进行心电波形的显示,同时对心电数据进行保存,分析。 双层板子:正面—电源模块和前置放大部分 反面—STM32单片机 面积(4cm*5cm) 附件内容包括: 整个心电采集系统硬件电路设计原理图和PCB...
  • 点击蓝字关注我哦以下是本期干货视频视频后还附有文字版本哦▼《名企高频考点之-Linux 什么命令能够进行文本列级别切分》▼ps:请在WiFi环境下打开,如果有钱任性请随意0.概述AWK是一种样式扫描处理的工具,其功能...
  • 截屏工具_PocketSnapshot

    2011-06-17 16:35:47
    !!! 使用步骤: 1,下载附件,解压到电脑!!将手机与电脑用数据线相连! ...在手机上会提示你安装软件!... 3,安装好后在开始菜单--》程序--》... 5,这样以后,你就可以通过wifi与电脑相连,无需数据线了!!
  • 同时用户还可以利用华为HiSuite备份手机数据,防止重要资料的丢失。 华为HiSuite手机管家支持的设备包括华为U8500, U8501,U8650等大多数华为安卓智能手机和平板电脑。 华为手机助手(HiSuite)特色功能 应用程序...
  • 开发板通过网线和电脑直连,ping通的网络设置

    千次阅读 多人点赞 2020-06-06 21:33:19
    为实现开发板和虚拟机下的linux、PClinux之间能互传数据。所处环境限制,离路由器太远,开发板不能直接连路由器。所以利用开发板的网口直连笔记本的网口,笔记本连接wifi的形式来学习调试开发板。 网线连接桥接...
  • 同时在设备管理器卸载英伟达显卡驱动(有概率只卸载向日葵并且选在删除数据也能好) 重启就好了 选择程序功能 找到向日葵卸载(记得选择删除配置文件) 选择设备管理器 找到显示适配器打开 右击...
  • 您可以浏览设备的内部,如果您是高级用户并且设备已植根,则可以更改系统数据 - 备份文件,删除不需要的应用程序等。 如果您是标准用户,您可以选择隐藏内部存储器,并确保不要弄乱系统。 您可以在设备上轻松查看大...
  • 您可以浏览设备的内部结构,如果您是高级用户并且已扎根设备,则可以更改系统数据-备份文件,删除不需要的应用程序等。 如果您是标准用户,则可以选择从视图中隐藏内部存储器,并确保不要系统混淆。 您可以...
  • 如果双方都安装超信,就能通过手机网络(WiFi、3G、GPRS)您通讯录中的联系人发送(需消耗少量网络流量)信息、图片、语音和位置等多媒体文件 超信官方介绍 超信是上海聊聊网络科技有限公司研发的一款为安全而...
  • 无线传书,使你的手机通过wifi网络电脑相连,让你能够在电脑上管理你手机中的文件,向手机传送文件,或从手机中获取文件。 无线传书,是一条隐形的,虚拟的数据线。 无线传书,界面简洁直接,操作简单,能够让你...
  • 1。iOS 6 Programming Cookbook_第0章_前言 内容提要: 期待已久的iOS 6 ... 当用户打开程序时,程序会检测用户通行证数据咖啡店相关的通行证,然后就可以使用 相关的通行证了。 Pass Kit 代表着苹果的一种数字 ...
  • • 应用程序框架 支持组件的重用替换 • Dalvik Dalvik Dalvik Dalvik 虚拟机 专为移动设备优化 • 集成的浏览器 基于开源的 WebKit 引擎 • 优化的图形库 包括定制的2D 图形库,3D 图形库基于 OpenGL ES 1.0 ...
  • 教你如何破解

    2012-05-20 01:55:50
    7、如果出现下图的结果,那么说明你的网卡驱动不支持此程序,同时会自动打开浏览器让你选择合适的驱动。 8、在安装好合适的驱动后会出现下图: 9、当统计的数据包比较多的时候,就可以自动分析出无线网络对应的...
  • 5.26 判断手持设备的WiFi与GPS状态 5.27 手机安全设置管理器 5.28 Shell Script运行Cmmand 5.29 模拟文件下载Notification进度变化与关闭 5.30 取得已安装应用程序列表与安装日期信息 5.31 造假的Toast画面 5.32 ...
  • 5.26 判断手持设备的WiFi与GPS状态 5.27 手机安全设置管理器 5.28 Shell Script运行Cmmand 5.29 模拟文件下载Notification进度变化与关闭 5.30 取得已安装应用程序列表与安装日期信息 5.31 造假的Toast画面 5.32 ...

空空如也

空空如也

1 2 3
收藏数 53
精华内容 21
关键字:

wifi与数据同时打开