Android API 28及以上连接WiFi时如何获取SSID、频段等AP详细信息
Android 获取WiFi AP详情最优实现方案
原有代码核心问题
- 用到的
NetworkInfo、ConnectivityManager.TYPE_WIFI、WifiManager.NETWORK_STATE_CHANGED_ACTION均已在安卓高版本中废弃,官方推荐使用ConnectivityManager.NetworkCallback替代实现网络状态监听 - SSID为空主要是权限适配不到位、缺少动态权限申请、高版本安卓权限规则变更导致
最优实现方案
步骤1:适配全版本Manifest权限配置
<!-- 基础WiFi、网络状态权限 --> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <!-- 安卓12及以下,获取SSID需要位置权限 --> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" android:maxSdkVersion="32" /> <!-- 安卓13及以上,获取WiFi相关信息用Nearby Devices权限,无需位置权限 --> <uses-permission android:name="android.permission.NEARBY_WIFI_DEVICES" android:usesPermissionFlags="neverForLocation" tools:targetApi="33" />
步骤2:动态申请危险权限
安卓系统中位置权限、Nearby WiFi设备权限属于危险权限,仅在Manifest中声明无效,必须动态申请用户同意后才能正常获取WiFi信息。
步骤3:使用NetworkCallback实现WiFi状态监听
private val TAG = "[MainActivity]" private lateinit var connectivityManager: ConnectivityManager // WiFi网络状态回调 private val wifiNetworkCallback = object : ConnectivityManager.NetworkCallback() { // WiFi连接成功时回调 override fun onAvailable(network: Network) { super.onAvailable(network) val wifiManager = applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager val wifiInfo = wifiManager.connectionInfo // trim去掉SSID前后自带的双引号 Log.d(TAG, "WiFi详情:SSID=${wifiInfo.ssid.trim('"')}, BSSID=${wifiInfo.bssid}, 信号强度=${wifiInfo.rssi}dBm") } // WiFi断开时回调 override fun onLost(network: Network) { super.onLost(network) Log.d(TAG, "WiFi已断开连接") } } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) connectivityManager = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager if (hasRequiredPermissions()) { registerWifiCallback() } else { requestRequiredPermissions() } } // 检查所需权限是否已授权 private fun hasRequiredPermissions(): Boolean { return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { ContextCompat.checkSelfPermission(this, Manifest.permission.NEARBY_WIFI_DEVICES) == PackageManager.PERMISSION_GRANTED } else { ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED } } // 申请所需权限 private fun requestRequiredPermissions() { val permissions = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { arrayOf(Manifest.permission.NEARBY_WIFI_DEVICES) } else { arrayOf(Manifest.permission.ACCESS_FINE_LOCATION) } ActivityCompat.requestPermissions(this, permissions, 1001) } // 注册WiFi状态监听 private fun registerWifiCallback() { val request = NetworkRequest.Builder() .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) .build() connectivityManager.registerNetworkCallback(request, wifiNetworkCallback) } // 权限申请结果回调 override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) { super.onRequestPermissionsResult(requestCode, permissions, grantResults) if (requestCode == 1001 && grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) { registerWifiCallback() } else { Toast.makeText(this, "权限被拒绝,无法获取WiFi信息", Toast.LENGTH_SHORT).show() } } override fun onDestroy() { super.onDestroy() // 注销回调避免内存泄漏 if (::connectivityManager.isInitialized) { connectivityManager.unregisterNetworkCallback(wifiNetworkCallback) } }
补充注意事项
- 安卓12及以下设备,除位置权限外还需要开启设备定位服务,否则即使授权也无法获取到真实SSID
- 如果需要获取扫描到的所有周边WiFi AP信息而非仅当前连接的WiFi,还需要添加
CHANGE_WIFI_STATE权限,调用wifiManager.startScan()方法获取扫描列表 - 部分定制ROM可能存在额外权限限制,若仍无法获取SSID可检查应用的位置、WiFi相关权限是否被系统限制
内容的提问来源于stack exchange,提问作者chelsea
相关产品推荐
相关产品推荐

