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雖然撰寫方法已有改變,但並未解決此一狀況,可能基於某些原因故意為之?
此版本已將權限驗證抽離為專門處理之模組,其判斷機制如下:
完整專案範例(連結)