Android 搜尋Wifi 須開啟相關權限:

<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

由於每次依照不同權限請求使用者同意是非常麻煩且無趣的工作,自動化開啟權限之相關程式碼可參考(連結)。

 

可以先確認裝置是否有開啟wifi服務,若無可以請使用者開啟。

wifiManager提供wifi相關的管理方法,包含裝置的支援程度以及目前連線狀態等相關資訊,詳細可參考開發者網站。

private void IsEnable(){
    //首先取得Wi-Fi服務控制Manager
    wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
    String msgStatus = null;
    if(wifiManager.isWifiEnabled()){
        msgStatus = "Wifi is Enable";
    }else {
        msgStatus = "Wifi is disable";
        //wifiManager.setWifiEnabled(true);
    }

    txtStatus.setText(msgStatus);
}

 

透過startScan方法可以成功掃描裝置,註冊receiver是由於掃描裝置為非同步進行,因此在掃描完畢後能夠呼叫此函數。

此寫法的優勢在於可以一直部段更新掃描結果,若不需要持續更新掃描狀況,可以不用註冊接收器(receiver),直接透過getScanResults()取得掃描結果即可。

private void scan() {
    // Register the Receiver in some part os fragment...
    registerReceiver(new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            wifiScanReceive();
        }
    }, new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));

    wifiManager.startScan();

    // Inside the receiver:
}

 

在成功掃描完畢後可以透過getScanResults()取得掃描結果,以下以下拉選單呈現為範例。

private void wifiScanReceive(){
    // the result.size() is 0 after update to Android v6.0, same code working in older devices.
    List<ScanResult> scanResultList =  wifiManager.getScanResults();

    int size = scanResultList.size();
    final List<String> dataList = new ArrayList<String>(size);
    Toast.makeText(context,"scan result :" + size,Toast.LENGTH_SHORT).show();

     for(int i = 0 ; i <size  ; i++ )
    {
        //手機目前周圍的Wi-Fi環境
        String SSID  = scanResultList.get(i).SSID ;
        int LEVEL = scanResultList.get(i).level;
        String item = String.format("%s-%d",SSID,LEVEL);
        Log.d("wifi",item);
        dataList.add(item);
    }


    runOnUiThread(new Runnable() {
        @Override
        public void run() {
            ArrayAdapter adapter = new ArrayAdapter(context,android.R.layout.simple_spinner_item,dataList);
            adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
            spinnerWifis.setAdapter(adapter);
        }
    });
}

 


而在Android 6.0 + 版本會出現搜尋裝置恆為0的窘境。以下將針對其緣由進行說明以及提出解決方案。

在 API 23 SDK's source code 中 WifiServiceImpl.java Line964。有以下一段奇怪且詭異的程式碼:

{YOUR_PATH}/Sdk/sources/android-26/com/android/server/wifi

if (!canReadPeerMacAddresses && !isActiveNetworkScorer && !isLocationEnabled()) {
    return new ArrayList<ScanResult>();
} 

它驗證當有上述任一條件未通過時回傳一個空的List,然而這即是這一問題的主因。

由於該段程式碼判別isLocationEnabled 因此使用者開啟GPS服務後,即可以正常偵測到預期的結果。

 

 

然而分析android-26版本API雖然撰寫方法已有改變,但並未解決此一狀況,可能基於某些原因故意為之?

此版本已將權限驗證抽離為專門處理之模組,其判斷機制如下:

 


完整專案範例(連結

arrow
arrow
    文章標籤
    Android
    全站熱搜

    Lung-Yu,Tsai 發表在 痞客邦 留言(1) 人氣()