Android12 (S) method to obtain wifi name (SSID)

Table of contents

overview

In the recent development process, it is necessary to obtain the current wifi SSID. At present, the mWifiManager.getConnectionInfo() method is generally recommended on the Internet to obtain it, but it is found that this method has been marked as obsolete on Android 12. In line with the idea of ​​​​using the latest method, I decided to use the recommendation new method to try.

problem analysis

Look at the source code. Since this method is marked as obsolete, there should be a recommended method to use. The source code is as follows:

 /**
    //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>
     */
    @Deprecated
    public WifiInfo getConnectionInfo() {
    
    
        try {
    
    
            return mService.getConnectionInfo(mContext.getOpPackageName(),
                    mContext.getAttributionTag());
        } catch (RemoteException e) {
    
    
            throw e.rethrowFromSystemServer();
        }
    }

According to the tips in the comments, Google recommends using NetworkCallback to monitor the network status to obtain the wifi ssid, and write it as follows:

 final NetworkRequest request =
           new NetworkRequest.Builder()
           .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
           .build();

 final ConnectivityManager.NetworkCallback mNetworkCallback = new ConnectivityManager.NetworkCallback() {
    
    
        @Override
        public void onAvailable(@NonNull Network network) {
    
    
            super.onAvailable(network);
        }

        @Override
        public 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);
    }

I thought everything would be fine and everything was OK, but I didn't expect that the ssid I got after the install was always an unknown ssid. For this case, the first thought is is the app missing permissions? Check the WifiInfo source code and find that when the application does not have the "Manifest.permission.ACCESS_FINE_LOCATION" permission, the ssid will indeed return Unknown Ssid. Is this solved? After looking at the manifest file of the application, I found that all the permission configurations should be available. This~ I can't fix it!
I struggled with it for several days, but still haven't found a solution to the problem.
It seems that I discovered a new world when I checked the source code of NetworkCallback by accident.

//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;
        }
        ...

It is found that parameters can be passed in the construction method of NetworkCallback, and according to the comments, we can know that the flag FLAG_INCLUDE_LOCATION_INFO is to control the NetworkCapabilities#getTransportInfo() when onCapabilitiesChanged can pass some sensitive location information, and obtaining the ssid in WifiInfo does require location information. seem? This is the correct answer? Hurry up and try it.

final ConnectivityManager.NetworkCallback mNetworkCallback = new ConnectivityManager.NetworkCallback(ConnectivityManager.NetworkCallback.FLAG_INCLUDE_LOCATION_INFO) {
    
    
        @Override
        public void onAvailable(@NonNull Network network) {
    
    
            super.onAvailable(network);
        }

        @Override
        public 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(">", ""));
            } 
        }
    };

The same method is to pass in FLAG_INCLUDE_LOCATION_INFO when creating NetworkCallback.
Compile, install, open the application, and the ssid is perfectly presented.
So far the problem is solved, this is the correct solution.

Summarize

Read the source code if you are indecisive, and read the source code if you are puzzled.

Guess you like

Origin blog.csdn.net/weixin_40774418/article/details/127718218