引言
- Android每个版本的API都是有点差异的,就拿Android7.0 8.0和9.0来说,设置热点开启与关闭的API都不是很相同,尤其Android7.0 到 8.0。设置调用的API还是发生了较大改变,一般情况热点的关闭和打开我们都会通过判断API版本,来判断调用不同的代码。
一、Hotspot的关闭
/**
* 关闭热点
*/
@SuppressLint("ObsoleteSdkInt")
public void closeWifiAp() {
Method method ;
if (isWifiApEnabled()) {
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
method = mWifiManager.getClass().getDeclaredMethod("stopSoftAp");
method.invoke(mWifiManager);
} else {
method = mWifiManager.getClass().getMethod("getWifiApConfiguration");
method.setAccessible(true);
WifiConfiguration config = (WifiConfiguration) method.invoke(mWifiManager);
Method method2 = mWifiManager.getClass().getMethod("setWifiApEnabled", WifiConfiguration.class, boolean.class);
method2.invoke(mWifiManager, config, false);
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
- 关闭热点代码入上所示,其中if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)代码是对Android 版本进行判断,Build.VERSION_CODES.O是26对应的是Android8.0,因此if中跑的是Android8.0和Android9.0关闭热点的代码,else中跑的是Android7.0关闭热点的代码。
二、Hotspot的打开
/**
* 打开热点
*/
public void openWifiAp() {
Method method;
if (mWifiManager.isWifiEnabled()) {
mWifiManager.setWifiEnabled(false);
}
if (!isWifiApEnabled()) {
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
mWifiConfiguration = getWifiApInfo();
Method configMethod = mWifiManager.getClass().getMethod("setWifiApConfiguration", WifiConfiguration.class);
configMethod.invoke(mWifiManager, mWifiConfiguration);
method = mWifiManager.getClass().getMethod("startSoftAp", WifiConfiguration.class);
//返回热点打开状态
method.invoke(mWifiManager, mWifiConfiguration);
} else {
method = mWifiManager.getClass().getMethod("getWifiApConfiguration");
method.setAccessible(true);
WifiConfiguration config = (WifiConfiguration) method.invoke(mWifiManager);
Method method2 = mWifiManager.getClass().getMethod("setWifiApEnabled", WifiConfiguration.class, boolean.class);
method2.invoke(mWifiManager, config, true);
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
- 打开热点代码如上所示,其中if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)代码是对Android 版本进行判断,Build.VERSION_CODES.O是26对应的是Android8.0,因此if中跑的是Android8.0和Android9.0打开热点的代码,else中跑的是Android7.0打开热点的代码
三、Hotspot的创建
/**
* 创建热点
*
* @param ssid 热点名称
* @param passwd 热点密码
* @param type 热点类型
*/
public void startWifiAp(String ssid, String passwd, int type) {
Method method;
if (mWifiManager.isWifiEnabled()) {
mWifiManager.setWifiEnabled(false);
}
try {
WifiConfiguration netConfig = new WifiConfiguration();
netConfig.SSID = ssid;
netConfig.preSharedKey = passwd;
netConfig.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
switch (type) {
case WIFI_NONE_TYPE:
netConfig.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
netConfig.preSharedKey = null;
break;
case WIFI_WEP_TYPE:
netConfig.allowedKeyManagement.set(4);
break;
case WIFI_WPA_TYPE:
netConfig.allowedKeyManagement.set(4);
break;
case WIFI_PSK_TYPE:
netConfig.allowedKeyManagement.set(4);
break;
default:
break;
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
Method configMethod = mWifiManager.getClass().getMethod("setWifiApConfiguration", WifiConfiguration.class);
configMethod.invoke(mWifiManager, netConfig);
} else {
method = mWifiManager.getClass().getMethod("setWifiApEnabled",
WifiConfiguration.class, boolean.class);
method.invoke(mWifiManager, netConfig, true);
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
- 创建热点代码如上所示,其中if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)代码是对Android 版本进行判断,Build.VERSION_CODES.O是26对应的是Android8.0,因此if中跑的是Android8.0和Android9.0创建热点的代码,else中跑的是Android7.0创建热点的代码
四、获取连接Hotspot的设备列表
/**
* 开热点手机获得其他连接手机IP的方法
*
* @return 其他手机IP 数组列表
*/
public ArrayList getConnectedIP() {
ArrayList connectedIp = new ArrayList();
BufferedReader br = null;
FileReader fileReader = null;
boolean flags = true;
try {
String line;
fileReader = new FileReader("/proc/net/arp");
br = new BufferedReader(fileReader);
mWifiManager.getDhcpInfo().toString();
while ((line = br.readLine()) != null) {
if (!flags) {
final String[] splitted = line.split(" + ");
if (splitted != null && splitted.length >= 6) {
if (splitted[2].equals(AP_CONNECTED) && splitted[5].equals(AP_DEVICE_TYPE)) {
connectedIp.add(splitted[0] + " " + splitted[3]);
}
}
}
flags = false;
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (null != fileReader) {
fileReader.close();
}
if (null != br) {
br.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return connectedIp;
}
五、WifiApManage类的所有代码
package com.dvb.net.hotspot;
import android.annotation.SuppressLint;
import android.content.Context;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager;
import android.os.Build;
import com.tulip.common.util.LogU;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import static android.content.Context.WIFI_SERVICE;
/**
* @author weijinsong
* @date 9/16/19
*/
public class WifiApManage {
private static final String AP_CONNECTED = "0x2";
private static final String AP_DEVICE_TYPE = "wlan0";
private static final int WIFI_NONE_TYPE = 0;
private static final int WIFI_WEP_TYPE = 1;
private static final int WIFI_WPA_TYPE = 2;
private static final int WIFI_PSK_TYPE = 3;
private static WifiApManage mWifiApManage;
private WifiManager mWifiManager;
private WifiConfiguration mWifiConfiguration;
public static WifiApManage newInstance(Context context) {
if (null == mWifiApManage) {
mWifiApManage = new WifiApManage(context);
}
return mWifiApManage;
}
public WifiApManage(Context context) {
mWifiManager = (WifiManager) context.getSystemService(WIFI_SERVICE);
}
/**
* 创建热点
*
* @param ssid 热点名称
* @param passwd 热点密码
* @param type 热点类型
*/
public void startWifiAp(String ssid, String passwd, int type) {
Method method;
if (mWifiManager.isWifiEnabled()) {
mWifiManager.setWifiEnabled(false);
}
try {
WifiConfiguration netConfig = new WifiConfiguration();
netConfig.SSID = ssid;
netConfig.preSharedKey = passwd;
netConfig.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
switch (type) {
case WIFI_NONE_TYPE:
netConfig.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
netConfig.preSharedKey = null;
break;
case WIFI_WEP_TYPE:
netConfig.allowedKeyManagement.set(4);
break;
case WIFI_WPA_TYPE:
netConfig.allowedKeyManagement.set(4);
break;
case WIFI_PSK_TYPE:
netConfig.allowedKeyManagement.set(4);
break;
default:
break;
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
Method configMethod = mWifiManager.getClass().getMethod("setWifiApConfiguration", WifiConfiguration.class);
configMethod.invoke(mWifiManager, netConfig);
} else {
method = mWifiManager.getClass().getMethod("setWifiApEnabled",
WifiConfiguration.class, boolean.class);
method.invoke(mWifiManager, netConfig, true);
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 检查是否开启Wifi热点
*
* @return
*/
public boolean isWifiApEnabled() {
try {
Method method = mWifiManager.getClass().getMethod("isWifiApEnabled");
method.setAccessible(true);
return (boolean) method.invoke(mWifiManager);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return false;
}
/**
* 关闭热点
*/
@SuppressLint("ObsoleteSdkInt")
public void closeWifiAp() {
Method method ;
if (isWifiApEnabled()) {
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
method = mWifiManager.getClass().getDeclaredMethod("stopSoftAp");
method.invoke(mWifiManager);
} else {
method = mWifiManager.getClass().getMethod("getWifiApConfiguration");
method.setAccessible(true);
WifiConfiguration config = (WifiConfiguration) method.invoke(mWifiManager);
Method method2 = mWifiManager.getClass().getMethod("setWifiApEnabled", WifiConfiguration.class, boolean.class);
method2.invoke(mWifiManager, config, false);
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
/**
* 关闭热点
*/
public void openWifiAp() {
Method method;
if (mWifiManager.isWifiEnabled()) {
mWifiManager.setWifiEnabled(false);
}
if (!isWifiApEnabled()) {
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
mWifiConfiguration = getWifiApInfo();
Method configMethod = mWifiManager.getClass().getMethod("setWifiApConfiguration", WifiConfiguration.class);
configMethod.invoke(mWifiManager, mWifiConfiguration);
method = mWifiManager.getClass().getMethod("startSoftAp", WifiConfiguration.class);
//返回热点打开状态
method.invoke(mWifiManager, mWifiConfiguration);
} else {
method = mWifiManager.getClass().getMethod("getWifiApConfiguration");
method.setAccessible(true);
WifiConfiguration config = (WifiConfiguration) method.invoke(mWifiManager);
Method method2 = mWifiManager.getClass().getMethod("setWifiApEnabled", WifiConfiguration.class, boolean.class);
method2.invoke(mWifiManager, config, true);
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
public WifiConfiguration getWifiApInfo() {
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
Method method = mWifiManager.getClass().getMethod("getWifiApConfiguration");
method.setAccessible(true);
mWifiConfiguration = (WifiConfiguration) method.invoke(mWifiManager);
LogU.e("enter ssid : " + mWifiConfiguration.SSID + " pwd : " + mWifiConfiguration.preSharedKey);
} else {
Method method = mWifiManager.getClass().getMethod("getWifiApConfiguration");
method.setAccessible(true);
mWifiConfiguration = (WifiConfiguration) method.invoke(mWifiManager);
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return mWifiConfiguration;
}
/**
* 开热点手机获得其他连接手机IP的方法
*
* @return 其他手机IP 数组列表
*/
public ArrayList getConnectedIP() {
ArrayList connectedIp = new ArrayList();
BufferedReader br = null;
FileReader fileReader = null;
boolean flags = true;
try {
String line;
fileReader = new FileReader("/proc/net/arp");
br = new BufferedReader(fileReader);
mWifiManager.getDhcpInfo().toString();
while ((line = br.readLine()) != null) {
if (!flags) {
final String[] splitted = line.split(" + ");
if (splitted != null && splitted.length >= 6) {
if (splitted[2].equals(AP_CONNECTED) && splitted[5].equals(AP_DEVICE_TYPE)) {
connectedIp.add(splitted[0] + " " + splitted[3]);
}
}
}
flags = false;
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (null != fileReader) {
fileReader.close();
}
if (null != br) {
br.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return connectedIp;
}
public String getClientDeviceName() {
BufferedReader br = null;
FileReader fileReader = null;
try {
fileReader = new FileReader("/data/misc/dhcp/dnsmasq.leases");
br = new BufferedReader(fileReader);
String line = "";
while ((line = br.readLine()) != null) {
LogU.e("enter device name : " + line);
if (line.indexOf("") != 1) {
String[] fields = line.split(" ");
//校验数据是不是破损
if (fields.length > 4) {
//返回第4个栏位
return fields[3];
}
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (null != fileReader) {
fileReader.close();
}
if (null != br) {
br.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
}
六、总结
- 上述代码容易踩坑的地方是当你想创建热点通过调用startWifiAp(String ssid, String passwd, int type)进行创建热点时,需要判断当前Android版本如果是Android7.0的话,需要先关闭热点才能对热点进行修改或者称为创建
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {mWifiApManage.closeWifiAp();}
- 如果需要获取连接当前的设备列表可通过getConnectedIP()进行获取,但是此方法只能获取到设备的IP和MAC等信息,如果想获取到当前设备的名称的话,需要调用另一个方法 getClientDeviceName,此方法中通过读取/data/misc/dhcp/dnsmasq.leases文件可获取到当前连接热点的设备的名字,可通过getConnectedIP()获取的的设备IP来进行关联从中获取对应IP的设备名称。/data/misc/dhcp/dnsmasq.leases文件的读取需要比较高级的权限,我只看过文件中的数据,在代码中实现读取里面的数据是没有成功过,因为权限不允许,这只是给大家一个获取连接设备名称的参考思路