主题:在手机开启热点网络的情况下,想要获取是哪个设备已经连接上了当前开启的热点。
实现思路:Android通过读取
/proc/net/arp
文件可以得到连接当前热点的设备信息,包括Mac地址、IP地址等信息。
一. 方法逻辑:
/*** 获取连接到手机热点上的设备信息* @return*/public List<HashMap> getConnectedApInfo() {List<HashMap> connectedApInfo = new ArrayList<>();try {BufferedReader br = new BufferedReader(new FileReader("/proc/net/arp"));String line;while ((line = br.readLine()) != null) {/*** 获取到的数组结果,示例:[192.168.227.138, 0x1, 0x2, 82:64:5e:01:49:fc, *, wlan2]*/String[] splitted = line.split(" +");HashMap hashMap = new HashMap();//设备信息判断标准if (splitted.length >= 4 && splitted[3].contains(":")) {String ip = splitted[0]; //获取IP地址信息,代替设备名称String address = splitted[3]; //获取Mac地址信息hashMap.put("name", ip);hashMap.put("address", address);connectedApInfo.add(hashMap);Log.d(TAG, "getConnectedApInfo(),获取连接到手机热点上的设备信息:" + Arrays.toString(splitted) + " connectedApInfo:" + connectedApInfo.size() + " " + connectedApInfo);}}} catch (Exception e) {e.printStackTrace();}return connectedApInfo;}
二. 拓展工具类,控制热点的开启和关闭,热点信息的获取:
import static android.content.Context.CONNECTIVITY_SERVICE;
import java.io.BufferedReader;
import java.io.FileReader;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.net.ConnectivityManager;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager;
import android.os.Build;
import android.util.Log;
import com.android.dx.stock.ProxyBuilder;/*** Description:控制热点的开启和关闭,热点信息的获取* 所需权限:* <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />* <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />* <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />* <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />* <uses-permission android:name="android.permission.WRITE_SETTINGS"* tools:ignore="ProtectedPermissions" /> <!-- 用于Android 6.0 (API 级别 23) 及以上版本 -->*/
public class WifiHotspotManager {private static final String TAG = WifiHotspotManager.class.getSimpleName();private WifiManager wifiManager;private Method method;public WifiHotspotManager(Context context) {wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);}public boolean isApEnabled() {try {if (method == null) {method = wifiManager.getClass().getMethod("isWifiApEnabled");}return (boolean) method.invoke(wifiManager);} catch (Exception e) {Log.e(TAG, "Error checking if AP is enabled", e);return false;}}/*** 开启或关闭热点* @param enabled* @return*/public boolean setApEnabled(boolean enabled) {if (enabled) {Log.d(TAG, "开启热点,Enabling hotspot");} else {Log.d(TAG, "关闭热点,Disabling hotspot");}try {if (method == null) {method = wifiManager.getClass().getMethod("setWifiApEnabled", WifiConfiguration.class, boolean.class);}return (boolean) method.invoke(wifiManager, null, enabled);} catch (Exception e) {Log.e(TAG, "开启或关闭热点 is error,enabling/disabling AP:" + e);return false;}}/*** 配置热点的设置(如SSID和密码)* 需要创建一个WifiConfiguration对象来配置你的热点设置,然后将其传递给configureApState方法* @param apConfig* @return*/public boolean configureApState(WifiConfiguration apConfig) {try {Method method = wifiManager.getClass().getMethod("setWifiApConfiguration", WifiConfiguration.class);return (boolean) method.invoke(wifiManager, apConfig);} catch (Exception e) {Log.e(TAG, "Error setting AP configuration", e);return false;}}/*** 控制热点的开启和关闭(一步到位)*/public boolean controlApSwitch(Context context, boolean flag){WifiManager wifiManager = (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE);try{WifiConfiguration apConfig = new WifiConfiguration();String deviceModel = Build.MODEL; //设备型号apConfig.SSID = deviceModel; //配置热点的名称apConfig.preSharedKey = "12345678"; //配置热点的密码(至少8位)apConfig.allowedKeyManagement.set(4); //配置密码加密方式//通过反射调用设置热点Method method = wifiManager.getClass().getMethod("setWifiApEnabled", WifiConfiguration.class, Boolean.TYPE);Boolean rs = (Boolean) method.invoke(wifiManager, apConfig, flag); //true 开启热点 ,false 关闭热点Log.d(TAG, flag ? "当前设备:" + deviceModel + " 开启热点网络是否成功:" + rs : " 关闭热点网络是否成功:" + rs);return rs;} catch(Exception e){e.printStackTrace();return false;}}/*** 发送隐式广播。此方法会查询与给定意图相匹配的所有广播接收器,并向每个匹配的接收器发送一个显式广播。** @param context 上下文,用于发送广播。* @param intent 需要发送的隐式广播意图。* @param action 执行的动作*/public void sendImplicitBroadcast(Context context, Intent intent, String action) {// 获取包管理器,用于查询广播接收器PackageManager pm = context.getPackageManager();// 查询与intent相匹配的所有广播接收器List<ResolveInfo> matches = pm.queryBroadcastReceivers(intent, 0);// 遍历所有匹配的广播接收器for (ResolveInfo resolveInfo : matches) {// 创建一个新的意图,将其转换为显式意图,目标为当前接收器Intent explicit = new Intent(intent);// 设置组件名称,转换为显式意图ComponentName cn = new ComponentName(resolveInfo.activityInfo.applicationInfo.packageName, resolveInfo.activityInfo.name);explicit.setComponent(cn);// 向每个匹配的广播接收器发送显式广播context.sendBroadcast(explicit);}Log.d(TAG, "sendImplicitBroadcast(),发送隐式广播,action:" + action);}/*** 打开手机的热点* 需要在build.gradle文件添加三方库依赖:implementation 'com.linkedin.dexmaker:dexmaker-mockito:2.12.1'* @param context*/public void startTethering(Context context){ConnectivityManager connectivityManager = ((ConnectivityManager)context.getSystemService(CONNECTIVITY_SERVICE));try{Class classOnStartTetheringCallback = Class.forName("android.net.ConnectivityManager$OnStartTetheringCallback");Method startTethering=connectivityManager.getClass().getDeclaredMethod("startTethering",int.class,boolean.class,classOnStartTetheringCallback);Object proxy = ProxyBuilder.forClass(classOnStartTetheringCallback).handler(new InvocationHandler(){@Overridepublic Object invoke(Object o,Method method,Object[]objects)throws Throwable{return null;}}).build();startTethering.invoke(connectivityManager,0,false,proxy);} catch(Exception e){e.printStackTrace();}Log.d(TAG, "startTethering(),打开手机的热点");}/*** 关闭手机的热点*/public void stopTethering(Context context){ConnectivityManager connectivityManager=((ConnectivityManager)context.getSystemService(CONNECTIVITY_SERVICE));try{Method stopTethering = connectivityManager.getClass().getDeclaredMethod("stopTethering",int.class);stopTethering.invoke(connectivityManager,0);}catch(Exception e){e.printStackTrace();}Log.d(TAG, "stopTethering(),关闭手机的热点");}/*** 判断是否开启手机的热点* @param context* @return*/public boolean isWifiApEnabled(Context context){WifiManager wifiManager = (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE);try{Method method=wifiManager.getClass().getMethod("isWifiApEnabled");method.setAccessible(true);return(Boolean)method.invoke(wifiManager);}catch(NoSuchMethodException e){e.printStackTrace();}catch(Exception e){e.printStackTrace();}Log.d(TAG, "isWifiApEnabled(),判断是否开启手机的热点");return false;}/*** 获取手机的热点信息* @param context* @return*/public String getApInfo(Context context){WifiManager wifiManager = (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE);try{Method localMethod = wifiManager.getClass().getDeclaredMethod("getWifiApConfiguration", new Class[0]);Object config = localMethod.invoke(wifiManager);Log.d(TAG, "getApInfo(),获取手机的热点信息:" + config.toString());}catch(Exception localException){localException.printStackTrace();}return null;}/*** 获取连接到手机热点上的设备信息* @return*/public List<HashMap> getConnectedApInfo() {List<HashMap> connectedApInfo = new ArrayList<>();try {BufferedReader br = new BufferedReader(new FileReader("/proc/net/arp"));String line;while ((line = br.readLine()) != null) {/*** 获取到的数组结果,示例:[192.168.227.138, 0x1, 0x2, 82:64:5e:01:49:fc, *, wlan2]*/String[] splitted = line.split(" +");HashMap hashMap = new HashMap();//设备信息判断标准if (splitted.length >= 4 && splitted[3].contains(":")) {String ip = splitted[0]; //获取IP地址信息,代替设备名称String address = splitted[3]; //获取Mac地址信息hashMap.put("name", ip);hashMap.put("address", address);connectedApInfo.add(hashMap);Log.d(TAG, "getConnectedApInfo(),获取连接到手机热点上的设备信息:" + Arrays.toString(splitted) + " connectedApInfo:" + connectedApInfo.size() + " " + connectedApInfo);}}} catch (Exception e) {e.printStackTrace();}return connectedApInfo;}
三. 调用示例:
//返回的是一个数据形式是包含HahMap集合的List集合,可根据HashMap的键值对取值并显示
WifiHotspotManager wifiHotspotManager = new WifiHotspotManager(requireActivity());List<HashMap> connectedApInfo = wifiHotspotManager.getConnectedApInfo();Log.d(TAG, "connectedApInfo:" + connectedApInfo.size() + " " + connectedApInfo);
四.手机热点已连接设备与功能效果图
参考文章:Android获取实时连接热点的设备IP_安卓设备获取ip-CSDN博客