Android--获取已连接的Wifi、蓝牙的名字

今天有个需求,需要在快捷面板上面的蓝牙和Wifi上面显示已连接的蓝牙和Wifi的名字。

从网上找了一些资料,发现并没有说明到底怎么处理,我这边研究了下,目前,Wifi是可以正常显示的,但是,蓝牙的,需要使用到隐藏API,当然,这个对于我处理的系统应用是没有问题的,但是三方应用呢?貌似是不可以的。

现在总结下,后续找到更好的方案了,再来处理。以下内容基于Android 7.1.

Wifi名字的显示

Wifi开关的时候,会发送如下广播

WifiManager.WIFI_STATE_CHANGED_ACTION

看下API里面的说明

import android.net.wifi.WifiManager;

       * Broadcast intent action indicating that Wi-Fi has been enabled, disabled,
       * enabling, disabling, or unknown. One extra provides this state   as an int.
       * Another extra provides the previous state, if available.
       *
       * @see #EXTRA_WIFI_STATE
       * @see #EXTRA_PREVIOUS_WIFI_STATE
       
      @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
      public static final String WIFI_STATE_CHANGED_ACTION =
        "android.net.wifi.WIFI_STATE_CHANGED";

从API上面的说明可以看出,此广播是在Wifi的状态enabled(已打开)、disabled(已关闭)、enabling(正在打开)、disabling(正在关闭)、unknow(未知)之间发送变化的时候发送,发送的时候会附带两个信息–EXTRA_WIFI_STATE和EXTRA_PREVIOUS_WIFI_STATE

  • EXTRA_WIFI_STATE–发生变化后的状态
         * The lookup key for an int that indicates whether Wi-Fi is enabled,
         * disabled, enabling, disabling, or unknown.  Retrieve it with
         * {@link android.content.Intent#getIntExtra(String,int)}.
         *
         * @see #WIFI_STATE_DISABLED
         * @see #WIFI_STATE_DISABLING
         * @see #WIFI_STATE_ENABLED
         * @see #WIFI_STATE_ENABLING
         * @see #WIFI_STATE_UNKNOWN
     
         public static final String EXTRA_WIFI_STATE = "wifi_state";
  • EXTRA_PREVIOUS_WIFI_STATE–变化之前的状态
        * The previous Wi-Fi state.
        *
        * @see #EXTRA_WIFI_STATE
  
        public static final String EXTRA_PREVIOUS_WIFI_STATE = "previous_wifi_state";

所以,我们监听了这个广播消息,就可以获取当前Wifi的一些状态信息。

具体使用如下:

  1. 注册广播
        IntentFilter filter = new IntentFilter();
        filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
        mContext.registerReceiver(mReceiver, filter);
  1. 接收到广播处理
      if (WifiManager.WIFI_STATE_CHANGED_ACTION.equals(action)) {//wifi

             int extra = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
                     WifiManager.WIFI_STATE_DISABLED);
            
             Log.d("nida", "WIFI_STATE_CHANGED_ACTION get extra:" + extra);
             if (extra == WifiManager.WIFI_STATE_ENABLED) {
                    //do something 
             } else if (extra == WifiManager.WIFI_STATE_DISABLED) {
                    //do other things.
             }
             
       } 

但是,以上并没有办法获取到已连接的Wifi的名字,那么,如果我想要获取名字,该怎么处理呢?

  1. 初始化的时候的获取
        private final WifiManager mWifiManager;
        //init
        mWifiManager = (WifiManager) mContext.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
        
           
        WifiInfo info = mWifiManager.getConnectionInfo();
        if(info != null) {
            Log.d("nida", "ssid=" + info.getSSID());
        }

使用mWifiManager.getConnectionInfo()就可以获取当前已连接wifi的名字,如果当前没有连接,那么就会显示字符串

D/nida: ssid=

那么,当Wifi的名字动态变化的时候呢?也就是,比如,我手动来点击打开Wifi,此时Wifi会自动连接到已连接过的有密码的AP,这个时候,我们是如何在其连接成功之后马上获取到对应的名字呢?

这就需要另外的一个监听

WifiManager.NETWORK_STATE_CHANGED_ACTION

我们看下其API的解释

        /**
     * Broadcast intent action indicating that the state of Wi-Fi connectivity
     * has changed. One extra provides the new state
     * in the form of a {@link android.net.NetworkInfo} object. If the new
     * state is CONNECTED, additional extras may provide the BSSID and WifiInfo of
     * the access point.
     * as a {@code String}.
     * @see #EXTRA_NETWORK_INFO
     * @see #EXTRA_BSSID
     * @see #EXTRA_WIFI_INFO
     */
    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    public static final String NETWORK_STATE_CHANGED_ACTION = "android.net.wifi.STATE_CHANGE";

这个广播就是Wifi连接状态改变的时候发出的。附带有一个信息android.net.NetworkInfo,也就是当前的网络状态对象。如果连接成功,那么就会有另外的两个信息被附带EXTRA_BSSID和EXTRA_WIFI_INFO .而我们需要的就是这个WifiInfo,里面就包含了当前已连接的Wifi的名字。

  1. EXTRA_NETWORK_INFO
       * The lookup key for a {@link android.net.NetworkInfo} object associated with the
       * Wi-Fi network. Retrieve with
       * {@link android.content.Intent#getParcelableExtra(String)}.
   
       public static final String EXTRA_NETWORK_INFO = "networkInfo";
  1. EXTRA_BSSID
        * The lookup key for a String giving the BSSID of the access point to which
        * we are connected. Only present when the new state is CONNECTED.
        * Retrieve with
        * {@link android.content.Intent#getStringExtra(String)}.
     
        public static final String EXTRA_BSSID = "bssid";
  1. EXTRA_WIFI_INFO
        * The lookup key for a {@link android.net.wifi.WifiInfo} object giving the
        * information about the access point to which we are connected. Only present
        * when the new state is CONNECTED.  Retrieve with
        * {@link android.content.Intent#getParcelableExtra(String)}.
    
        public static final String EXTRA_WIFI_INFO = "wifiInfo";

处理过程如下,注册广播的步骤省略

       if(WifiManager.NETWORK_STATE_CHANGED_ACTION.equals(action)) {
                 Log.d("nida", "NETWORK_STATE_CHANGED_ACTION");

                WifiInfo info =  intent.getParcelableExtra(WifiManager.EXTRA_WIFI_INFO);
                if(info != null) {
                    String name = info.getSSID();
                    Log.d("nida", "name=" + name);
                }
       }

至此,Wifi相关的就处理完毕。

获取已连接的蓝牙名字

  1. 初始化的时候获取已连接的蓝牙的名字

    并没有找到比较好的方法,目前使用的是隐藏API,此仅仅可以在系统应用里面使用

            private final BluetoothAdapter mBluetoothAdapter;
            private String mBtName;
            //init
            mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
            
            private String getBluetoothName () {
               //获取已绑定的设备列表
               Set<BluetoothDevice> deviceList = mBluetoothAdapter.getBondedDevices();
               for(BluetoothDevice device : deviceList) {
                  Log.d("nida", "device.isConnected()=" + device.isConnected() + ", name=" + device.getName());
                  if(device.isConnected()) {
                     mBtName = device.getName();
                  else {
                     mBtName = "BT";
                  }
              }
              return mBtName;
           }

BluetoothDevice的isConnected()方法是隐藏API,无法访问的

framework\base\core\java\android\bluetooth\BluetoothDevice.java

      /**
     * Returns whether there is an open connection to this device.
     * 

Requires {@link android.Manifest.permission#BLUETOOTH}. * * @return True if there is at least one open connection to this device. * @hide */ @SystemApi public boolean isConnected() { if (sService == null) { // BT is not enabled, we cannot be connected. return false; } try { return sService.getConnectionState(this) != CONNECTION_STATE_DISCONNECTED; } catch (RemoteException e) { Log.e(TAG, "", e); return false; } }

2.蓝牙动态开关的时候获取已配对蓝牙的名字

同Wifi一样,当我们手动去开关蓝牙的时候,其名字是怎么获取的呢?

同样,监听广播

BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED

     /**
     * Intent used to broadcast the change in connection state of the local
     * Bluetooth adapter to a profile of the remote device. When the adapter is
     * not connected to any profiles of any remote devices and it attempts a
     * connection to a profile this intent will sent. Once connected, this intent
     * will not be sent for any more connection attempts to any profiles of any
     * remote device. When the adapter disconnects from the last profile its
     * connected to of any remote device, this intent will be sent.
     *
     * 

This intent is useful for applications that are only concerned about * whether the local adapter is connected to any profile of any device and * are not really concerned about which profile. For example, an application * which displays an icon to display whether Bluetooth is connected or not * can use this intent. * *

This intent will have 3 extras: * {@link #EXTRA_CONNECTION_STATE} - The current connection state. * {@link #EXTRA_PREVIOUS_CONNECTION_STATE}- The previous connection state. * {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. * * {@link #EXTRA_CONNECTION_STATE} or {@link #EXTRA_PREVIOUS_CONNECTION_STATE} * can be any of {@link #STATE_DISCONNECTED}, {@link #STATE_CONNECTING}, * {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTING}. * *

Requires {@link android.Manifest.permission#BLUETOOTH} to receive. */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.adapter.action.CONNECTION_STATE_CHANGED";

也就是说,当蓝牙的连接状态发送改变的时候就会发送这个广播,并且会带三个额外信息,我们需要的就是BluetoothDevice这个额外信息。

处理过程如下

            if(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED.equals(action)) {
               int state = intent.getIntExtra(BluetoothAdapter.EXTRA_CONNECTION_STATE, BluetoothAdapter.STATE_DISCONNECTING);
               if(state == BluetoothAdapter.STATE_CONNECTED) {
                   BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                   if(device != null) {
                       Log.d("nida", "ACTION_CONNECTION_STATE_CHANGED name=" + device.getName());
                   }
               }
            }

至此,蓝牙名字的获取也已经完成。唯一的就是蓝牙初始化的名字的获取使用了隐藏API。

参考

Android如何获取Wifi名称即SSID

Android 如何获取已连接的蓝牙地址

你可能感兴趣的:(android,java)