目录

  • 概述
  • 问题分析
  • 总结

概述

在最近开发过程中需要获取当前wifi的SSID,目前网上一般推荐 mWifiManager.getConnectionInfo() 这个方法来进行获取,但是发现在Android12上这个方法已经被标记为过时,本着用最新方法的想法,决定使用推荐的新方法试试。

问题分析

一言不合看源码,既然该方法被标记为过时,那么应该也会有推荐的方法来使用,源码如下:

 /**//path:packages/modules/Wifi/framework/java/android/net/wifi/WifiManager.java* Return dynamic information about the current Wi-Fi connection, if any is active.* <p>** @return the Wi-Fi information, contained in {@link WifiInfo}.** @deprecated Starting with {@link Build.VERSION_CODES#S}, WifiInfo retrieval is moved to* {@link ConnectivityManager} API surface. WifiInfo is attached in* {@link NetworkCapabilities#getTransportInfo()} which is available via callback in* {@link NetworkCallback#onCapabilitiesChanged(Network, NetworkCapabilities)} or on-demand from* {@link ConnectivityManager#getNetworkCapabilities(Network)}.**</p>* Usage example:* <pre>{@code* final NetworkRequest request =*      new NetworkRequest.Builder()*      .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)*      .build();* final ConnectivityManager connectivityManager =*      context.getSystemService(ConnectivityManager.class);* final NetworkCallback networkCallback = new NetworkCallback() {*      ...*      {@literal @}Override*      void onAvailable(Network network) {}**      {@literal @}Override*      void onCapabilitiesChanged(Network network, NetworkCapabilities networkCapabilities) {*          WifiInfo wifiInfo = (WifiInfo) networkCapabilities.getTransportInfo();*      }*      // etc.* };* connectivityManager.requestNetwork(request, networkCallback); // For request* connectivityManager.registerNetworkCallback(request, networkCallback); // For listen* }</pre>* <p>* <b>Compatibility Notes:</b>* <li>Apps can continue using this API, however newer features* such as ability to mask out location sensitive data in WifiInfo will not be supported* via this API. </li>* <li>On devices supporting concurrent connections (indicated via* {@link #isStaConcurrencyForLocalOnlyConnectionsSupported()}, etc) this API will return* the details of the internet providing connection (if any) to all apps, except for the apps* that triggered the creation of the concurrent connection. For such apps, this API will return* the details of the connection they created. e.g. apps using {@link WifiNetworkSpecifier} will* trigger a concurrent connection on supported devices and hence this API will provide* details of their peer to peer connection (not the internet providing connection). This* is to maintain backwards compatibility with behavior on single STA devices.</li>* </p>*/@Deprecatedpublic WifiInfo getConnectionInfo() {try {return mService.getConnectionInfo(mContext.getOpPackageName(),mContext.getAttributionTag());} catch (RemoteException e) {throw e.rethrowFromSystemServer();}}

根据注释里的提示,谷歌推荐使用NetworkCallback监听网络状态的方法来获取wifi 的ssid,照着写一下,如下:

 final NetworkRequest request =new NetworkRequest.Builder().addTransportType(NetworkCapabilities.TRANSPORT_WIFI).build();final ConnectivityManager.NetworkCallback mNetworkCallback = new ConnectivityManager.NetworkCallback() {@Overridepublic void onAvailable(@NonNull Network network) {super.onAvailable(network);}@Overridepublic void onCapabilitiesChanged(@NonNull Network network, @NonNull NetworkCapabilities networkCapabilities) {super.onCapabilitiesChanged(network, networkCapabilities);WifiInfo wifiInfo = (WifiInfo) networkCapabilities.getTransportInfo();if (wifiInfo != null) {String ssid = wifiInfo.getSSID().replace("\"", "").replace("<", "").replace(">", ""));} }};private void requestNetwork() {mConnectivityManager.registerNetworkCallback(mRequest, mNetworkCallback);}private void unrequestNetwork() {mConnectivityManager.unregisterNetworkCallback(mNetworkCallback);}

本以为万事大吉,一切OK,没想到install以后拿到的ssid 一直是 unknow ssid。对于这种情况,第一想法是应用是否缺少权限?查看WifiInfo源码,发现在应用没有"Manifest.permission.ACCESS_FINE_LOCATION"权限时,ssid的确会返回Unknown Ssid。难道这就解决了?看了一下应用的清单文件,发现该有的权限配置都是有的。这~ 给我整不会了!
纠结了好几天,始终没有找到解决问题的办法。
偶然在查看NetworkCallback源码的时候好像发现了新大陆。

//path:packages/modules/Connectivity/framework/src/android/net/ConnectivityManager.java/*** Base class for {@code NetworkRequest} callbacks. Used for notifications about network* changes. Should be extended by applications wanting notifications.** A {@code NetworkCallback} is registered by calling* {@link #requestNetwork(NetworkRequest, NetworkCallback)},* {@link #registerNetworkCallback(NetworkRequest, NetworkCallback)},* or {@link #registerDefaultNetworkCallback(NetworkCallback)}. A {@code NetworkCallback} is* unregistered by calling {@link #unregisterNetworkCallback(NetworkCallback)}.* A {@code NetworkCallback} should be registered at most once at any time.* A {@code NetworkCallback} that has been unregistered can be registered again.*/public static class NetworkCallback {/*** No flags associated with this callback.* @hide*/public static final int FLAG_NONE = 0;/*** Use this flag to include any location sensitive data in {@link NetworkCapabilities} sent* via {@link #onCapabilitiesChanged(Network, NetworkCapabilities)}.* <p>* These include:* <li> Some transport info instances (retrieved via* {@link NetworkCapabilities#getTransportInfo()}) like {@link android.net.wifi.WifiInfo}* contain location sensitive information.* <li> OwnerUid (retrieved via {@link NetworkCapabilities#getOwnerUid()} is location* sensitive for wifi suggestor apps (i.e using {@link WifiNetworkSuggestion}).</li>* </p>* <p>* Note:* <li> Retrieving this location sensitive information (subject to app's location* permissions) will be noted by system. </li>* <li> Without this flag any {@link NetworkCapabilities} provided via the callback does* not include location sensitive info.* </p>*/// Note: Some existing fields which are location sensitive may still be included without// this flag if the app targets SDK < S (to maintain backwards compatibility).public static final int FLAG_INCLUDE_LOCATION_INFO = 1 << 0;/** @hide */@Retention(RetentionPolicy.SOURCE)@IntDef(flag = true, prefix = "FLAG_", value = {FLAG_NONE,FLAG_INCLUDE_LOCATION_INFO})public @interface Flag { }/*** All the valid flags for error checking.*/private static final int VALID_FLAGS = FLAG_INCLUDE_LOCATION_INFO;public NetworkCallback() {this(FLAG_NONE);}public NetworkCallback(@Flag int flags) {if ((flags & VALID_FLAGS) != flags) {throw new IllegalArgumentException("Invalid flags");}mFlags = flags;}...

发现NetworkCallback的构造方法中是可以传参数的,并且根据注释可知 FLAG_INCLUDE_LOCATION_INFO 这个flag就是控制onCapabilitiesChanged时 NetworkCapabilities#getTransportInfo() 可以传递一些敏感的位置信息,而获取WifiInfo中的ssid的确需要位置信息。似乎?这就是正解?赶紧加进去试试。

final ConnectivityManager.NetworkCallback mNetworkCallback = new ConnectivityManager.NetworkCallback(ConnectivityManager.NetworkCallback.FLAG_INCLUDE_LOCATION_INFO) {@Overridepublic void onAvailable(@NonNull Network network) {super.onAvailable(network);}@Overridepublic void onCapabilitiesChanged(@NonNull Network network, @NonNull NetworkCapabilities networkCapabilities) {super.onCapabilitiesChanged(network, networkCapabilities);WifiInfo wifiInfo = (WifiInfo) networkCapabilities.getTransportInfo();if (wifiInfo != null) {String ssid = wifiInfo.getSSID().replace("\"", "").replace("<", "").replace(">", ""));} }};

方法相同就是在创建NetworkCallback 时传入FLAG_INCLUDE_LOCATION_INFO。
编译,install,打开应用,ssid完美呈现。
至此问题解决,这就是正解。

总结

遇事不决阅读源码,百思不解可读源码。

Android12 (S) 获取wifi名称(SSID)的方法相关推荐

  1. 关于Android 8.0/9.0 之后获取wifi名称为空的解决方法

    今天连接硬件设备的时候,需要用到wifi名和密码来进行绑定配对.在获取wifi名的时候,意外发现为空.于是就开始找寻解决方案. 后来找到这么一篇文章: Android获取WIFI 的ssid 方法适配 ...

  2. Android获取WiFi名称/路由器AP地址总结

    前言 谷歌有一点点的蛋疼,没想到定位也需要加上版本的判断了,再此总结下定位权限以及WiFi AP SSID的获取. 安卓9.0定位权限 安卓系统在9.0之后如果不开启手机的GPS服务功能,应用即使已经 ...

  3. iOS开发:获取WiFi名称(解决iOS12.0以上系统不能正常获取WiFi名称的方法)

    前段时间在开发过程中遇到一个问题,就是之前设置的获取手机连接WiFi名称的方法不起作用了,后来经查发现是因为新系统需要申请开启相对应的权限才能获取到手机连接的WiFi名称等信息,本章就来讲一下iOS1 ...

  4. 【unknow ssid】两种办法获取WIFI名称99%可解决

    复工第一天,今天早上客户反映某品牌手机Android10以上无法获取wifi名称,我寻思不就定位权限嘛,一看权限都有的,就是获取不到wifi名称. 原因: 不知道 解决方案:写了两个方法,如果方法1无 ...

  5. iOS 升级到iOS13 无法获取WiFi名称(SSID)的问题

    在升级到iOS13以后忽然发现无法获取WiFi名称(SSID),在iOS13以下我们可以通过下面的方法获取当前所连WiFi的名称等信息 //引入系统提供的官方库 #import <SystemC ...

  6. flutter 获取wifi名称以及Android10获取不到wifi名称<unknown ssid>

    插件 我使用的是wifi_iot这个插件,版本是0.2.2,flutter版本是1.20.0. dependencies:flutter:sdk: flutterwifi_iot: ^0.2.2 获取 ...

  7. iOS中获取WiFi的SSID(CNCopySupportedInterfaces())

    获取当前设备连接WiFi: ios5之前可以通过读取配置文件获取,ios5以后苹果修改wifi列表文件位置,只有root权限才可以读取. ios4:/System/Library/SystemConf ...

  8. Android Studio WiFi 之 获取 WiFi 名称、IP、Mac

    Android 获取连接的WIFI 的一些数据(后期封装成aar 包给Unity 调用) 封装成AAR包,获取 Android 7.0 以上的 手机 mac 地址 一.Android 代码 impor ...

  9. Android 监听网络连接状态,判断网络连接方式,9.0网络连接,获取已连接WiFi名称SSID和MAC

    获取已连接的WiFi名称 <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/> ...

最新文章

  1. C内存2:程序是如何运行的
  2. 用算法改造过的植物肉,有兴趣试试么?
  3. 【剑指offer-Java版】39二叉树的深度
  4. CSS揭秘之《背景图案》
  5. Windows 技术篇 - 无需确认快速删除包含大量文件的目录,cmd删除文件的rmdir、del、erase和rd四种命令使用方法
  6. Python基础——PyCharm版本——第八章、文件I/O(核心3、csv和excel解析)
  7. ElasticSearch之高亮显示
  8. 11选5下期算法_五指大山|新手入门,快速玩转11选5
  9. PyTorch1.2.0版本来啦!居然还有全套视频!让你快速熟练掌握深度学习框架!
  10. C++_limits头文件
  11. Win7 计算机中丢失api-ms-win-core-path-|1-1-0.dll
  12. 机器学习数学基础二:泰勒公式与拉格朗日
  13. Layui文件下载(VIP典藏版)
  14. dos批处理脚本自动添加网络IP打印机-简单亲测可用
  15. uni-app 中英文切换
  16. 程序员来聊一聊信用卡(一)——年轻人该不该办理一张信用卡
  17. OSPF特殊区域(stub、stub no-summary、nssa)
  18. java阶段七容器集合之Map------练习2
  19. 103个后台PSD源文件、素材网站
  20. 使用springboot每日推送早安问候语到用户微信【部署篇】

热门文章

  1. [1191]电脑耳机孔插上耳机没反应
  2. pandas 根据筛选条件对指定excel列进行筛选
  3. linux查找与替换练习
  4. 一个程序员的十年程序人生感悟
  5. 那些选择网络工程的女生们,后来都怎么样了?
  6. 利用YAKE进行文档关键词提取
  7. Robot Framework自定义测试库
  8. iview upload 上传时携带额外参数
  9. 有些人的恨是没有原因的,他们平庸、没有天分、碌碌无为,于是你的优秀、你的天赋、你的善良和幸福都是原罪。
  10. Unity 常见英文单词