新聞中心

        Android WIFI 詳解

        作者: 時間:2016-10-08 來源:網(wǎng)絡(luò) 收藏

        public class WifiEnabler implementsPreference.OnPreferenceChangeListener {

        ……

        public boolean onPreferenceChange(Preference preference,Object value) {

        booleanenable = (Boolean) value;

        ……

        if (mWifiManager.setWifiEnabled(enable)) {

        mCheckBox.setEnabled(false);

        ……

        }

        ……

        }

        我們都知道Wifimanager只是個服務(wù)代理,所以它會調(diào)用WifiService的setWifiEnabled()函數(shù),而這個函數(shù)會調(diào)用 sendEnableMessage()函數(shù),了解android消息處理機制的都知道,這個函數(shù)最終會給自己發(fā)送一個 MESSAGE_ENABLE_WIFI的消息,被WifiService里面定義的handlermessage()函數(shù)處理,會調(diào)用 setWifiEnabledBlocking()函數(shù)。下面是調(diào)用流程:

        mWifiEnabler.onpreferencechange()=>mWifiManage.setWifienabled()=>mWifiService.setWifiEnabled()=>mWifiService.sendEnableMessage()=>mWifiService.handleMessage()=>mWifiService.setWifiEnabledBlocking().

        在setWifiEnabledBlocking()函數(shù)中主要做如下工作:加載Wifi驅(qū)動,啟動wpa_supplicant,注冊廣播接收器,啟動WifiThread監(jiān)聽線程。代碼如下:

        ……

        if (enable) {

        if (!mWifiStateTracker.loadDriver()) {

        Slog.e(TAG, Failed toload Wi-Fi driver.);

        setWifiEnabledState(WIFI_STATE_UNKNOWN, uid);

        return false;

        }

        if (!mWifiStateTracker.startSupplicant()) {

        mWifiStateTracker.unloadDriver();

        Slog.e(TAG, Failed tostart supplicant daemon.);

        setWifiEnabledState(WIFI_STATE_UNKNOWN, uid);

        return false;

        }

        registerForBroadcasts();

        mWifiStateTracker.startEventLoop();

        ……

        至此,Wifi使能結(jié)束,自動進(jìn)入掃描階段。

        (2) 掃描AP

        當(dāng)驅(qū)動加載成功后,如果配置文件的AP_SCAN = 1,掃描會自動開始,WifiMonitor將會從supplicant收到一個消息EVENT_DRIVER_STATE_CHANGED,調(diào)用 handleDriverEvent(),然后調(diào)用mWifiStateTracker.notifyDriverStarted(),該函數(shù)向消息隊列 添加EVENT_DRIVER_STATE_CHANGED,handlermessage()函數(shù)處理消息時調(diào)用scan()函數(shù),并通過 WifiNative將掃描命令發(fā)送到wpa_supplicant。

        Frameworks/base/wifi/java/android/net/wifi/WifiMonitor.java

        private void handleDriverEvent(Stringstate) {

        if (state == null) {

        return;

        }

        if (state.equals(STOPPED)) {

        mWifiStateTracker.notifyDriverStopped();

        } else if (state.equals(STARTED)) {

        mWifiStateTracker.notifyDriverStarted();

        } else if (state.equals(HANGED)) {

        mWifiStateTracker.notifyDriverHung();

        }

        }

        Frameworks/base/wifi/java/android/net/wifi/WifiStateTracker.java

        case EVENT_DRIVER_STATE_CHANGED:

        switch(msg.arg1) {

        case DRIVER_STARTED:

        /**

        *Set the number of allowed radio channels according

        *to the system setting, since it gets reset by the

        *driver upon changing to the STARTED state.

        */

        setNumAllowedChannels();

        synchronized (this) {

        if (mRunState == RUN_STATE_STARTING) {

        mRunState = RUN_STATE_RUNNING;

        if (!mIsScanOnly) {

        reconnectCommand();

        } else {

        // In somesituations, supplicant needs to be kickstarted to

        // start thebackground scanning

        scan(true);

        }

        }

        }

        break;

        上面是啟動Wifi時,自動進(jìn)行的AP的掃描,用戶當(dāng)然也可以手動掃描AP,這部分實現(xiàn)在WifiService里面,WifiService通過startScan()接口函數(shù)發(fā)送掃描命令到supplicant。

        Frameworks/base/wifi/java/android/net/wifi/WifiStateTracker.java

        public boolean startScan(booleanforceActive) {

        enforceChangePermission();

        switch (mWifiStateTracker.getSupplicantState()) {

        case DISCONNECTED:

        case INACTIVE:

        case SCANNING:

        case DORMANT:

        break;

        default:

        mWifiStateTracker.setScanResultHandling(

        WifiStateTracker.SUPPL_SCAN_HANDLING_LIST_ONLY);

        break;

        }

        return mWifiStateTracker.scan(forceActive);

        }

        然后下面的流程同上面的自動掃描,我們來分析一下手動掃描從哪里開始的。我們應(yīng)該知道手動掃描是通過菜單鍵的掃描鍵來響應(yīng)的,而響應(yīng)該動作的應(yīng)該是 WifiSettings類中Scanner類的handlerMessage()函數(shù),它調(diào)用WifiManager的 startScanActive(),這才調(diào)用WifiService的startScan()。

        packages/apps/Settings/src/com/android/settings/wifiwifisettings.java

        public boolean onCreateOptionsMenu(Menu menu) {

        menu.add(Menu.NONE, MENU_ID_SCAN, 0, R.string.wifi_menu_scan)

        .setIcon(R.drawable.ic_menu_scan_network);

        menu.add(Menu.NONE, MENU_ID_ADVANCED, 0, R.string.wifi_menu_advanced)

        .setIcon(android.R.drawable.ic_menu_manage);

        return super.onCreateOptionsMenu(menu);

        }

        當(dāng)按下菜單鍵時,WifiSettings就會調(diào)用這個函數(shù)繪制菜單。如果選擇掃描按鈕,WifiSettings會調(diào)用onOptionsItemSelected()。

        packages/apps/Settings/src/com/android/settings/wifiwifisettings.java



        關(guān)鍵詞:

        評論


        相關(guān)推薦

        技術(shù)專區(qū)

        關(guān)閉
        主站蜘蛛池模板: 东平县| 芦山县| 怀仁县| 浪卡子县| 苍山县| 阿合奇县| 三门峡市| 仁寿县| 县级市| 沁源县| 冀州市| 大宁县| 桓仁| 综艺| 榕江县| 毕节市| 常熟市| 霍林郭勒市| 浏阳市| 安平县| 泾阳县| 衡山县| 柏乡县| 常德市| 西藏| 比如县| 新野县| 琼中| 庄河市| 石首市| 南充市| 临夏县| 呼伦贝尔市| 舟曲县| 赣榆县| 锡林郭勒盟| 尉氏县| 永兴县| 郓城县| 福州市| 綦江县|