今天有个需求,需要在快捷面板上面的蓝牙和Wifi上面显示已连接的蓝牙和Wifi的名字。
从网上找了一些资料,发现并没有说明到底怎么处理,我这边研究了下,目前,Wifi是可以正常显示的,但是,蓝牙的,需要使用到隐藏API,当然,这个对于我处理的系统应用是没有问题的,但是三方应用呢?貌似是不可以的。
现在总结下,后续找到更好的方案了,再来处理。以下内容基于Android 7.1.
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
* 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";
* The previous Wi-Fi state.
*
* @see #EXTRA_WIFI_STATE
public static final String EXTRA_PREVIOUS_WIFI_STATE = "previous_wifi_state";
所以,我们监听了这个广播消息,就可以获取当前Wifi的一些状态信息。
具体使用如下:
IntentFilter filter = new IntentFilter();
filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
mContext.registerReceiver(mReceiver, filter);
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的名字,那么,如果我想要获取名字,该怎么处理呢?
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的名字。
* 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";
* 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";
* 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相关的就处理完毕。
初始化的时候获取已连接的蓝牙的名字
并没有找到比较好的方法,目前使用的是隐藏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 如何获取已连接的蓝牙地址