当WIFI连接成功时获取SSID

86

当我的安卓设备连接到WIFI时,我想获得WIFI网络的SSID。

我已经注册了一个BroadcastReceiver监听android.net.wifi.supplicant.CONNECTION_CHANGE事件。当WIFI被断开或重新连接时,我会收到通知。但是,我无法获取网络的SSID。

我正在使用以下代码查找SSID:

WifiManager wifiManager = (WifiManager) context.getSystemService(context.WIFI_SERVICE);
WifiInfo wifiInfo = wifiManager.getConnectionInfo();
String ssid = wifiInfo.getSSID();

我得到了字符串<未知SSID>而不是SSID。

这些是清单中的权限(我添加了ACCESS_NETWORK_STATE只是为了检查,实际上我不需要它)。

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
为什么会发生这种情况?我如何获取实际的SSID?是广播提前触发了,还是在连接建立之前?是否有其他广播可以侦听?我只对WIFI连接感兴趣,不关心3G连接。
更新:我刚刚检查过,wifiInfo.getBSSID()返回null。

有趣的是,文档中指出如果连接不可用,应该从getSSID()接收到null,因此我认为这不是连接问题。只是想知道,您测试的网络的SSID是什么? - Ben Siver
详细状态和请求者状态是什么? - Eric Woodruff
1
@Ben S,检查我在问题中提供的链接,<unknown ssid>是Android 4.2的行为,可能也适用于更新版本。这是一个Android的bug。 - zmbq
谢谢澄清。 - Ben Siver
试试这个 Stack Overflow 的答案。https://dev59.com/iVUL5IYBdhLWcg3wqpo7#51518480 - Yaswant Narayan
11个回答

115

我在广播接收器中监听WifiManager.NETWORK_STATE_CHANGED_ACTION事件。

if (WifiManager.NETWORK_STATE_CHANGED_ACTION.equals(action)) {
    NetworkInfo netInfo = intent.getParcelableExtra (WifiManager.EXTRA_NETWORK_INFO);
    if (ConnectivityManager.TYPE_WIFI == netInfo.getType ()) {
        ...
    }
}
我检查了netInfo.isConnected()。然后我就可以使用。
WifiManager wifiManager = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
WifiInfo info = wifiManager.getConnectionInfo();
String ssid  = info.getSSID();

更新

从Android 8.0开始,除非启用位置服务且您的应用程序有权限访问它,否则我们将无法获得连接网络的SSID。


@Eric:您能否分享包含广播接收器的完整代码? - Rakesh Gondaliya
我在第一个代码块中分享了它。“action”来自广播接收器接收的意图。 - Eric Woodruff
12
你应该将WifiManager wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);改为WifiManager wifiManager = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);,因为WiFiManager必须使用应用程序上下文而非活动上下文,否则可能会发生内存泄漏。 - Pavlos Panteliadis
你确定这个在 Android 8 上即使开启 GPS 也能正常工作吗?NETWORK_STATE_CHANGED 不在 隐式广播例外列表 中,所以我认为系统不会再调用你的 BroadcastReceiver。 - Michael Krause
3
那个更新很重要!即使你拥有所有正确的权限,直到GPS实际开启之前,你仍然会收到一个未知的SSID!(仅在安卓9上进行了测试) - Kedar Paranjape
显示剩余3条评论

60

自 Android 8.1 (API 27) 起,应用必须被授予 ACCESS_COARSE_LOCATION(或 ACCESS_FINE_LOCATION)权限,才能从 WifiInfo.getSSID()WifiInfo.getBSSID() 中获得结果。针对 API 29 或更高版本(Android 10)的应用必须被授予 ACCESS_FINE_LOCATION

虽然不清楚是否新要求,但获取 WifiManager.getConnectionInfo()WifiManager.getScanResults() 的结果也需要此权限。

来源: “BSSID / SSID 可用于推断位置,因此要求使用 WifiManager.getConnectionInfo() 请求这些 WifiInfo 字段时需要与 WifiManager.getScanResults() 相同的位置权限。”


是我自己的问题还是Android P DP2即使你的目标SDK很低也会强制执行这个规定? - behelit
2
似乎8.1+设备需要这个,而不管目标sdk是什么。 - behelit
同样适用于Android P测试版。 - Jay Ryu
  • 为了说明为什么需要位置权限。
- Hayk Nahapetyan

44

如果您不想创建广播接收器,那么简单尝试一下

WifiManager wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
WifiInfo wifiInfo;

wifiInfo = wifiManager.getConnectionInfo();
if (wifiInfo.getSupplicantState() == SupplicantState.COMPLETED) {
    ssid = wifiInfo.getSSID();
}

每当用户断开连接,连接到新的SSID或任何wifi状态更改时,您需要初始化WifiInfo,即wifiInfo = wifiManager.getConnectionInfo();


2
这比被接受的答案好多了。为什么要监听网络状态的变化,当我们需要检查此信息(已连接网络的SSID)的特定运行时可能实际上没有任何变化呢?我假设,由于getConnectionInfo的文档,WifiInfo可能为空,因此在我看来应该进行保护检查。 - leRobot
1
应该是 WifiManager 而不是 WiFiManager。 - behelit
3
可以工作,只需要设置权限:INTERNET、ACCESS_WIFI_STATE以及位置权限:ACCESS_COARSE_LOCATION或ACCESS_FINE_LOCATION。 - android developer

16

我发现一种有趣的解决方法,可以获取当前连接Wifi AP的SSID。 你只需使用迭代WifiManager.getConfiguredNetworks()并查找具有特定WifiInfo.getNetworkId()的配置即可。

我的例子

在具有操作WifiManager.NETWORK_STATE_CHANGED_ACTION的广播接收器中, 我从意图中获取当前连接状态。

NetworkInfo nwInfo = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
nwInfo.getState()

如果NetworkInfo.getState等于NetworkInfo.State.CONNECTED,那么我可以获取当前的WifiInfo对象。

WifiManager wifiManager = (WifiManager) getSystemService (Context.WIFI_SERVICE);
WifiInfo info = wifiManager.getConnectionInfo ();

之后

public String findSSIDForWifiInfo(WifiManager manager, WifiInfo wifiInfo) {

    List<WifiConfiguration> listOfConfigurations = manager.getConfiguredNetworks();

    for (int index = 0; index < listOfConfigurations.size(); index++) {
        WifiConfiguration configuration = listOfConfigurations.get(index);
        if (configuration.networkId == wifiInfo.getNetworkId()) {
            return configuration.SSID;
        }
    }

    return null;
}

非常重要的一点是,这种方法不需要位置或位置权限。

在API29中,谷歌重新设计了Wifi API,因此该解决方案已过时适用于Android 10。


运行得很好;在接收到wifiInfo之前我跳过了所有您的描述/说明(仍然拥有这个+管理器)。想知道这是否会因为安卓9而改变。 - Kaspatoo
2
不客气。我已在“Pie”中测试了这个解决方案,仍然可用。 - TomMannson
这段程序相关的内容翻译成中文如下:如果没有位置权限,这个在Android Q上无法工作,getConfiguredNetworks返回空列表,getNetworkId返回-1。只有在获得位置权限后才能正常工作。 - Nithin
2
WifiConfiguration在API 29(即Android 10)中已被弃用。 - Werner Schäffer
你说得对,但出于向后兼容的目的,它可能很有用。感谢您的反馈。 - TomMannson

5
这是对 @EricWoodruff 给出答案的跟进。
您可以使用 netInfogetExtraInfo() 方法来获取 WiFi 的 SSID。
if (WifiManager.NETWORK_STATE_CHANGED_ACTION.equals (action)) {
    NetworkInfo netInfo = intent.getParcelableExtra (WifiManager.EXTRA_NETWORK_INFO);
    if (ConnectivityManager.TYPE_WIFI == netInfo.getType ()) {
        String ssid = info.getExtraInfo()
        Log.d(TAG, "WiFi SSID: " + ssid)
    }
}

如果您没有使用BroadcastReceiver,请查看这个答案来使用Context获取SSID。此方法在Android Oreo 8.1.0上已测试通过。

2
这在我的9.0上不起作用,getExtraInfo()返回null。 - szx

5
在Android 8.1中,必须打开位置信息才能获取SSID,否则可以获取连接状态但无法获取SSID。
WifiManager wifiManager = (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
WifiInfo wifiInfo = null;
if (wifiManager != null) 
wifiInfo = wifiManager.getConnectionInfo();
 String ssid = null;
if (wifiInfo != null) 
ssid = wifiInfo.getSSID(); /*you will get SSID <unknown ssid> if location turned off*/

3

使用Kotlin回答

授权许可

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<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_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />



 private fun getCurrentNetworkDetail() {
    val connManager =
        context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
    val networkInfo = connManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI)
    if (networkInfo.isConnected) {
        val wifiManager =
            context.getApplicationContext().getSystemService(Context.WIFI_SERVICE) as WifiManager
        val connectionInfo = wifiManager.connectionInfo
        if (connectionInfo != null && !TextUtils.isEmpty(connectionInfo.ssid)) {
            Log.e("ssid", connectionInfo.ssid)
        }
    }
    else{
        Log.e("ssid", "No Connection")
    }

}

3

对于我而言,只有在手机上设置了权限后(设置 -> 应用程序权限 -> 始终启用位置),才能正常工作。


0
根据官方文件的解释,在Android 10+(API 29及更高版本)中,仅声明ACCESS_COARSE_LOCATION或ACCESS_FINE_LOCATION权限是不够的。
1. 对于前台定位:
您还需要在您的Service中声明一个foregroundServiceType为location的foregroundServiceType来使用前台定位。
<service
    android:name="MyNavigationService"
    android:foregroundServiceType="location" ... >
    <!-- Any inner elements would go here. -->
</service>

或者如果您的代码在Activity中运行,则该Activity应对用户可见。

2. 对于后台位置:

您应该在应用程序清单中声明ACCESS_BACKGROUND_LOCATION权限,以便在运行时请求后台位置访问。

注意:Google Play商店有关设备位置的位置政策,限制仅允许核心功能需要并符合相关政策要求的应用程序进行后台位置访问。

官方文件:

https://developer.android.com/training/location/permissions https://developer.android.com/guide/topics/connectivity/wifi-scan#wifi-scan-permissions


0
返回当前802.11网络的服务集标识符(SSID)。 如果SSID可以解码为UTF-8,则将其用双引号括起来返回。否则,将其作为十六进制数字字符串返回。如果没有网络连接或调用者没有足够的权限访问SSID,则SSID可能是WifiManager.UNKNOWN_SSID。 在Build.VERSION_CODES.JELLY_BEAN_MR1之前,该方法始终返回没有引号的SSID。 返回: SSID。
public String getSSID() {
    if (mWifiSsid != null) {
        String unicode = mWifiSsid.toString();
        if (!TextUtils.isEmpty(unicode)) {
            return "\"" + unicode + "\"";
        } else {
            String hex = mWifiSsid.getHexString();
            return (hex != null) ? hex : WifiManager.UNKNOWN_SSID;
        }
    }
    return WifiManager.UNKNOWN_SSID;
}

应该是“权限不足”。 以下是我的演示权限,在Android 9上测试,一切正常。您可以添加所有权限来判断原因:

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