1.概述
最近在做Android盒子开发的时候,在对wifi和热点的开发需求也是比较多的,在项目开发中需要对热点进行开关和对状态的判断,经过查询相关资料找到解决方案WifiManager.java源码,通过WifiManager中的api来获取相关状态,而在其中的getWifiApState() 就是获取热点开关的状态
2.1获取热点状态的两种方法
@SystemService(Context.WIFI_SERVICE)
public class WifiManager {
IWifiManager mService;
/**
* Gets the Wi-Fi enabled state.
* @return One of {@link #WIFI_AP_STATE_DISABLED},
* {@link #WIFI_AP_STATE_DISABLING}, {@link #WIFI_AP_STATE_ENABLED},
* {@link #WIFI_AP_STATE_ENABLING}, {@link #WIFI_AP_STATE_FAILED}
* @see #isWifiApEnabled()
*
* @hide Dont open yet
*/
public int getWifiApState() {
try {
return mService.getWifiApEnabledState();
} catch (RemoteException e) {
return WIFI_AP_STATE_FAILED;
}
}
从getWifiApState()的相关方法可以看出,最终是调用WifiManagerService.java中的getWifiApEnabledState()来获取热点的状态
如果getWifiApState()被隐藏,就得调用反射来获取
public static boolean isWifiApOpen(Context context) {
try {
WifiManager manager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
//通过放射获取 getWifiApState()方法
Method method = manager.getClass().getDeclaredMethod("getWifiApState");
//调用getWifiApState() ,获取返回值
int state = (int) method.invoke(manager);
//通过放射获取 WIFI_AP的开启状态属性
Field field = manager.getClass().getDeclaredField("WIFI_AP_STATE_ENABLED");
//获取属性值
int value = (int) field.get(manager);
//判断是否开启
if (state == value) {
return true;
} else {
return false;
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
return false;
}
通过 getWifiApState() 方法返回值的注释,可以找到如下几种状态,拿到当前状态值之后,只需要对比各种状态的值,就知道热点的开启状态了
@return One of
{@link #WIFI_STATE_DISABLED},
{@link #WIFI_STATE_DISABLING},
{@link #WIFI_STATE_ENABLED},
{@link #WIFI_STATE_ENABLING},
{@link #WIFI_STATE_UNKNOWN}
public static final int WIFI_MODE_FULL_HIGH_PERF = 3;
/** Anything worse than or equal to this will show 0 bars. */
private static final int MIN_RSSI = -100;
/** Anything better than or equal to this will show the max bars. */
private static final int MAX_RSSI = -55;
/**
* Number of RSSI levels used in the framework to initiate
* {@link #RSSI_CHANGED_ACTION} broadcast
* @hide
*/
public static final int RSSI_LEVELS = 5;
/**
* Auto settings in the driver. The driver could choose to operate on both
* 2.4 GHz and 5 GHz or make a dynamic decision on selecting the band.
* @hide
*/
public static final int WIFI_FREQUENCY_BAND_AUTO = 0;
/**
* Operation on 5 GHz alone
* @hide
*/
public static final int WIFI_FREQUENCY_BAND_5GHZ = 1;
/**
* Operation on 2.4 GHz alone
* @hide
*/
public static final int WIFI_FREQUENCY_BAND_2GHZ = 2;
/* LocalOnlyHotspot callback message types */
/** @hide */
public static final int HOTSPOT_STARTED = 0;
/** @hide */
public static final int HOTSPOT_STOPPED = 1;
/** @hide */
public static final int HOTSPOT_FAILED = 2;
/** @hide */
public static final int HOTSPOT_OBSERVER_REGISTERED = 3;
通过上述WifiManager.java的常量来表示当前wifi和hotspot热点状态
2.2通过反射获取到热点的SSID
首先来看下WifiManager.java中获取热点的相关api
/**
* Return whether Wi-Fi AP is enabled or disabled.
* @return {@code true} if Wi-Fi AP is enabled
* @see #getWifiApState()
*
* @hide
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE)
public boolean isWifiApEnabled() {
return getWifiApState() == WIFI_AP_STATE_ENABLED;
}
/**
* Gets the Wi-Fi AP Configuration.
* @return AP details in WifiConfiguration
*
* @hide
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE)
public WifiConfiguration getWifiApConfiguration() {
try {
return mService.getWifiApConfiguration();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Sets the Wi-Fi AP Configuration. The AP configuration must either be open or
* WPA2 PSK networks.
* @return {@code true} if the operation succeeded, {@code false} otherwise
*
* @hide
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.CHANGE_WIFI_STATE)
public boolean setWifiApConfiguration(WifiConfiguration wifiConfig) {
try {
return mService.setWifiApConfiguration(wifiConfig, mContext.getOpPackageName());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
在WifiManager中可以通过getWifiApConfiguration() 来获取WifiConfiguration对象从而通过
调用WifiConfiguration 的SSID来获取当前连接热点的ssid,获取方法如下:
private void getApSSID(){
try {
WifiManager manager = (WifiManager) this.getSystemService(Context.WIFI_SERVICE);
//调用getWifiApConfiguration()方法,获取到 热点的WifiConfiguration
WifiConfiguration configuration = (WifiConfiguration) manager.getWifiApConfiguration();
String ssid = configuration.SSID;
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
在普通app中是获取不到getWifiApConfiguration()所以需要通过反射的方法来获取WifiConfiguration
然后通过WifiConfiguration来获取当前热点的ssid,具体实现方法如下:
private void getApSSID(){
try {
WifiManager manager = (WifiManager) this.getSystemService(Context.WIFI_SERVICE);
//拿到getWifiApConfiguration()方法
Method method = manager.getClass().getDeclaredMethod("getWifiApConfiguration");
//调用getWifiApConfiguration()方法,获取到 热点的WifiConfiguration
WifiConfiguration configuration = (WifiConfiguration) method.invoke(manager);
String ssid = configuration.SSID;
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
3.关于WifiManager的相关方法的分析
在wifiManager的相关api中,WifiInfo 是专门用来表示连接的对象,这个对象可以通过 WifiManager.getConnectionInfo() 来获取。
WifiInfo中包含了当前连接中的相关信息。
getBSSID() 获取wifi的BSSID属性
getDetailedStateOf() 获取客户端的连通性
getHiddenSSID() 获取wifi的SSID 是否被隐藏
getIpAddress() 获取wifi的IP 地址
getLinkSpeed() 获取wifi连接的速度
getMacAddress() 获取wifi的Mac 地址
getRssi() 获取wifi网络的信号
getSSID() 获取wifi的SSID
getSupplicanState() 获取具体客户端状态的信息