如何在Android中获取可用的WiFi网络并将其显示在列表中

38

朋友们,我想查找所有可用的WiFi网络并将它们显示在一个列表中,我已经尝试了如下代码。但它没有起作用。我编辑了我的代码,现在我得到了结果,但是它包含了所有我不需要的结果。我只需要在我的列表中列出Wi-Fi网络名称。

public class MainActivity extends Activity {

    TextView mainText;
    WifiManager mainWifi;
    WifiReceiver receiverWifi;
    List<ScanResult> wifiList;
    StringBuilder sb = new StringBuilder();

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mainText = (TextView) findViewById(R.id.tv1);
        mainWifi = (WifiManager) getSystemService(Context.WIFI_SERVICE);

        if (mainWifi.isWifiEnabled() == false)
        {  
             // If wifi disabled then enable it
             Toast.makeText(getApplicationContext(), "wifi is disabled..making it enabled",
             Toast.LENGTH_LONG).show();
             mainWifi.setWifiEnabled(true);
         } 

         receiverWifi = new WifiReceiver();
         registerReceiver(receiverWifi, new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
         mainWifi.startScan();
         mainText.setText("Starting Scan...");

     }

     public boolean onCreateOptionsMenu(Menu menu) {
            menu.add(0, 0, 0, "Refresh");
            return super.onCreateOptionsMenu(menu);
     }

     public boolean onMenuItemSelected(int featureId, MenuItem item) {
            mainWifi.startScan();
            mainText.setText("Starting Scan");
            return super.onMenuItemSelected(featureId, item);
     }

     protected void onPause() {
            unregisterReceiver(receiverWifi);
            super.onPause();
     }

     protected void onResume() {
            registerReceiver(receiverWifi, new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
            super.onResume();
     }

        // Broadcast receiver class called its receive method
        // when number of wifi connections changed

      class WifiReceiver extends BroadcastReceiver {

            // This method call when number of wifi connections changed
            public void onReceive(Context c, Intent intent) {

                sb = new StringBuilder();
                wifiList = mainWifi.getScanResults();
                sb.append("\n        Number Of Wifi connections :"+wifiList.size()+"\n\n");

                for(int i = 0; i < wifiList.size(); i++){

                    sb.append(new Integer(i+1).toString() + ". ");
                    sb.append((wifiList.get(i)).toString());
                    sb.append("\n\n");
                }

                mainText.setText(sb); 
            }

       }
}
4个回答

44

您需要创建一个BroadcastReceiver来监听Wifi扫描结果:

private final BroadcastReceiver mWifiScanReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context c, Intent intent) {
        if (intent.getAction().equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) {
            List<ScanResult> mScanResults = mWifiManager.getScanResults();
            // add your logic here
        }
    }
}

onCreate() 方法中,您将会给 mWifiManager 赋值并开始扫描:

mWifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
registerReceiver(mWifiScanReceiver,
        new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
mWifiManager.startScan();

getScanResults() 只有在您拥有适当的权限时才会返回数据。为此,请将以下两行之一添加到您的 AndroidManifest.xml 文件中:

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

请注意,在API 23+中,权限必须在运行时请求。(对于实验室环境,您也可以在设置中手动授予权限,少量代码编写,但不建议用于最终用户应用程序。)

请注意,处理扫描结果的代码会在每次有新的扫描结果可用时运行,更新结果。


请查看我的更新代码...现在我已经得到了所有可用网络的列表,但它们带有BSSID、信号强度等详细信息...所以我只需要那个WiFi网络的名称...你能帮我解决这个问题吗? - jigar
请查看ScanResult的SDK文档。有一个名为getSSID()(或类似)的方法。SSID是网络的“显示”名称。 - user149408
1
抱歉,我的 Nexus 5 出现了一个 bug,只有在打开 GPS 的情况下才会显示 WiFi 列表。你的代码有效。 - Bala Vishnu
2
@BalaVishnu 看起来 GPS 设置可以启用/禁用所有位置服务,包括 WiFi 扫描,因此无法从附近的 WiFi 推断出任何位置信息。 - user149408
1
android.permission.ACCESS_WIFI_STATE也是必需的。文档中没有找到任何信息,但RuntimeException告诉我这一点。这是一个新的东西吗?为什么没有人在这里提到呢? - stoefln
显示剩余2条评论

14

Android 6.0及以上版本

如果你的Android操作系统版本为6.0或更高版本,则你的应用程序必须在运行时请求以下权限(两者之一)。

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

如何在运行时请求权限

只需将以下代码添加到您的Activity的onResume方法中即可:

@Override
public void onResume()
{
    super.onResume();

    if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
    {
        if(checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED)
        {
            requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, 87);
        }
    }
}

如果在运行时没有上述权限会发生什么?

Wifi.getScanResults() 将返回0个结果。

许多人,包括我自己,在Nexus 5手机上遇到了这个问题,并将其称为“漏洞”。

如何扫描并读取WiFi网络?(深入理解)

扫描可以通过以下方式请求:

wifiManager.startScan();

boolean startScan()会立刻返回true或false,取决于扫描是否成功开始。
不过它会启动一个异步事件,当扫描完成时发送一个意图(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)。由于扫描结果(异步事件结果)不会立即可用,因此您需要使用BroadcastReceiver在活动中进行注册。

以下是使用BroadcastReceiver读取这些结果(异步方式)的代码片段。

public class WifiScanReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {

        if(intent.getAction().equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION))
        {
            List<ScanResult> scanResults = wifimanager.getScanResults();
            // Write your logic to show in the list
        }

    }
}

您可以在BroadcastReceiver上查看此演示

相关链接

在Android 6.0中扫描结果返回空列表


如果我没记错的话,"android.permission.ACCESS_FINE_LOCATION" 可能也包含了 "android.permission.ACCESS_COARSE_LOCATION"。 - hyena
确实如此。您可以选择其中任何一个提到的权限。它会很好地工作。@hyena - Rohit Singh

6
  class WifiReceiver extends BroadcastReceiver {

       public void onReceive(Context c, Intent intent) {

          sb = new StringBuilder();
          wifiList = mainWifi.getScanResults();

            for (int i = 0; i < wifiList.size(); i++){
                sb.append(new Integer(i+1).toString() + ".");
                sb.append((wifiList.get(i)).SSID);
                sb.append("\n");
            }

          mainText.setText(sb);

        }

  }

0
Android 10(API 级别29)及更高版本:
成功调用WifiManager.startScan()需要满足以下所有条件:
If your app is targeting Android 10 (API level 29) SDK or higher, your app has the ACCESS_FINE_LOCATION permission.
If your app is targeting SDK lower than Android 10 (API level 29), your app has the ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION permission.
Your app has the CHANGE_WIFI_STATE permission.
Location services are enabled on the device (under Settings > Location).

要成功调用WifiManager.getScanResults(),请确保满足以下所有条件:
If your app is targeting Android 10 (API level 29) SDK or higher, your app has the ACCESS_FINE_LOCATION permission.
If your app is targeting SDK lower than Android 10 (API level 29), your app has the ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION permission.
Your app has the ACCESS_WIFI_STATE permission.
Location services are enabled on the device (under Settings > Location).

如果调用应用程序不满足所有这些要求,调用将失败并出现SecurityException异常。
以下是您可以尝试的代码:
BtWifiscan.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 1);
            }
        }
    });




 public void onRequestPermissionsResult(int requestCode, String[] permissions,
                                       int[] grantResults) {
    if (requestCode == 1/*PERMISSIONS_REQUEST_CODE_ACCESS_COARSE_LOCATION*/
            && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
        permisio_state[1] = 1;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            requestPermissions(new String[]{Manifest.permission.CHANGE_WIFI_STATE}, 2);
        }
    }
    if (requestCode == 2/*PERMISSIONS_REQUEST_CODE_ACCESS_COARSE_LOCATION*/
            && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
        permisio_state[2] = 2;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, 3);
        }
    }
    if (requestCode == 3/*PERMISSIONS_REQUEST_CODE_ACCESS_COARSE_LOCATION*/
            && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
        permisio_state[3] = 3;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            requestPermissions(new String[]{Manifest.permission.ACCESS_WIFI_STATE}, 4);
        }
    }
    if (requestCode == 4/*PERMISSIONS_REQUEST_CODE_ACCESS_COARSE_LOCATION*/
            && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
        permisio_state[4] = 4;
    }
    if (permisio_state[1] == 1 && permisio_state[2] == 2 && permisio_state[3] == 3 && permisio_state[4] == 4)
        WifiScaning();
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接