0


【Android App】检查手机连接WiFi信息以及扫描周围WiFi的讲解及实战(附源码和演示 超详细必看)

需要全部代码请点赞关注收藏后评论区留言私信~~~

一、检查是否连接WiFi以及输出WiFi信息

传统的定位方式不适用于室内的垂直定位,原因如下: (1)卫星定位要求没有障碍物遮挡,它在户外比较精准,在室内信号就变差。 (2)基站定位依赖于运营商的通讯服务,如果身处基站信号尚未覆盖的偏僻空间,就无法使用基站定位。 室内WiFi定位纳入了IEEE的802.11标准,名叫WLAN RTT (IEEE 802.11mc)。

RTT是Round-Trip-Time的缩写,即往返时间,可以用于计算网络两端的距离

室内WiFi定义的实现步骤有以下三步

(1)检查是否连接无线网络 通过无线网络管理器WifiManager获取WiFi信息。

(2)扫描周围的无线网络 用到无线网络管理器的startScan和getScanResults两个方法。

(3)计算WiFi路由器的往返时延 通过WifiRttManager对目标路由器测距。

上网方式主要有两种 即数据连接和WiFi,不过连接管理器ConnectivityManager只能笼统地判断能否上网,并不能获知WiFi连接的详细信息,在当前网络类型是WiFi时,要想得知WiFi上网的具体信息,还需另外通过无线网络管理器WifiManager获取 它的部分方法如下

isWifiEnabled 判断WLAN功能是否开启

setWifiEnabled 开启或关闭WLAN功能

getWifiState 获取当前的WiFi连接状态

实战效果如下 会输出所连接Wifi的相关信息

代码如下

  1. package com.example.location;
  2. import com.example.location.util.IPv4Util;
  3. import com.example.location.util.NetUtil;
  4. import android.annotation.SuppressLint;
  5. import android.content.Context;
  6. import android.net.ConnectivityManager;
  7. import android.net.NetworkInfo;
  8. import android.net.wifi.WifiInfo;
  9. import android.net.wifi.WifiManager;
  10. import android.os.Bundle;
  11. import android.os.Handler;
  12. import androidx.appcompat.app.AppCompatActivity;
  13. import android.os.Looper;
  14. import android.telephony.TelephonyManager;
  15. import android.text.TextUtils;
  16. import android.widget.TextView;
  17. @SuppressLint("DefaultLocale")
  18. public class WifiInfoActivity extends AppCompatActivity {
  19. private static final String TAG = "WifiInfoActivity";
  20. private TextView tv_info; // 声明一个文本视图对象
  21. private Handler mHandler = new Handler(Looper.myLooper()); // 声明一个处理器对象
  22. private String[] mWifiStateArray = {"正在断开", "已断开", "正在连接", "已连接", "未知"};
  23. @Override
  24. protected void onCreate(Bundle savedInstanceState) {
  25. super.onCreate(savedInstanceState);
  26. setContentView(R.layout.activity_wifi_info);
  27. tv_info = findViewById(R.id.tv_info);
  28. mHandler.postDelayed(mRefresh, 50); // 延迟50毫秒后启动网络刷新任务
  29. }
  30. // 定义一个网络刷新任务
  31. private Runnable mRefresh = new Runnable() {
  32. @Override
  33. public void run() {
  34. getAvailableNet(); // 获取可用的网络信息
  35. // 延迟1秒后再次启动网络刷新任务
  36. mHandler.postDelayed(this, 1000);
  37. }
  38. };
  39. // 获取可用的网络信息
  40. private void getAvailableNet() {
  41. String desc = "";
  42. // 从系统服务中获取电话管理器
  43. TelephonyManager tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
  44. // 从系统服务中获取连接管理器
  45. ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
  46. // 通过连接管理器获得可用的网络信息
  47. NetworkInfo info = cm.getActiveNetworkInfo();
  48. if (info != null && info.getState() == NetworkInfo.State.CONNECTED) { // 有网络连接
  49. if (info.getType() == ConnectivityManager.TYPE_WIFI) { // WiFi网络(无线热点)
  50. // 从系统服务中获取无线网络管理器
  51. WifiManager wm = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
  52. int state = wm.getWifiState(); // 获得无线网络的状态
  53. WifiInfo wifiInfo = wm.getConnectionInfo(); // 获得无线网络信息
  54. String SSID = wifiInfo.getSSID(); // 获得无线网络的名称
  55. if (TextUtils.isEmpty(SSID) || SSID.contains("unknown")) {
  56. desc = "\n当前联网的网络类型是WiFi,但未成功连接已知的WiFi信号";
  57. } else {
  58. desc = String.format("当前联网的网络类型是WiFi,状态是%s。\nWiFi名称是:%s\n路由器MAC是:%s\nWiFi信号强度是:%d\n连接速率是:%s\n手机的IP地址是:%s\n手机的MAC地址是:%s\n网络编号是:%s\n",
  59. mWifiStateArray[state], SSID, wifiInfo.getBSSID(),
  60. wifiInfo.getRssi(), wifiInfo.getLinkSpeed(),
  61. IPv4Util.intToIp(wifiInfo.getIpAddress()),
  62. wifiInfo.getMacAddress(), wifiInfo.getNetworkId());
  63. }
  64. } else if (info.getType() == ConnectivityManager.TYPE_MOBILE) { // 移动网络(数据连接)
  65. int net_type = info.getSubtype();
  66. desc = String.format("\n当前联网的网络类型是%s %s",
  67. NetUtil.getNetworkTypeName(tm, net_type),
  68. NetUtil.getClassName(tm, net_type));
  69. } else {
  70. desc = String.format("\n当前联网的网络类型是%d", info.getType());
  71. }
  72. } else { // 无网络连接
  73. desc = "\n当前无上网连接";
  74. }
  75. tv_info.setText(desc);
  76. }
  77. }

二、扫描周围的无线网络

扫描周边Wifi主要用到WiFi滚力气的startScan方法和getScanResults方法,前者表示开始扫描周围的网络,后者表示获取扫描的结果列表,它们两个方法不能紧跟着,因为扫描动作是异步进行的,必须等到收到扫描结束的广播,然后在广播接收器中才能获取扫描结果

点击开始扫描后结果如下 会输出附近的WiFi信息

代码如下

  1. package com.example.location;
  2. import androidx.annotation.RequiresApi;
  3. import androidx.appcompat.app.AppCompatActivity;
  4. import android.content.BroadcastReceiver;
  5. import android.content.Context;
  6. import android.content.Intent;
  7. import android.content.IntentFilter;
  8. import android.net.wifi.ScanResult;
  9. import android.net.wifi.WifiManager;
  10. import android.os.Build;
  11. import android.os.Bundle;
  12. import android.widget.ListView;
  13. import android.widget.TextView;
  14. import com.example.location.adapter.ScanListAdapter;
  15. import java.util.HashMap;
  16. import java.util.List;
  17. import java.util.Map;
  18. @RequiresApi(api = Build.VERSION_CODES.M)
  19. public class WifiScanActivity extends AppCompatActivity {
  20. private final static String TAG = "WifiScanActivity";
  21. private TextView tv_result; // 声明一个文本视图对象
  22. private ListView lv_scan; // 声明一个列表视图对象
  23. private WifiManager mWifiManager; // 声明一个WiFi管理器对象
  24. private WifiScanReceiver mWifiScanReceiver = new WifiScanReceiver(); // 声明一个WiFi扫描接收器对象
  25. @Override
  26. protected void onCreate(Bundle savedInstanceState) {
  27. super.onCreate(savedInstanceState);
  28. setContentView(R.layout.activity_wifi_scan);
  29. tv_result = findViewById(R.id.tv_result);
  30. lv_scan = findViewById(R.id.lv_scan);
  31. findViewById(R.id.btn_scan).setOnClickListener(v -> mWifiManager.startScan());
  32. // 从系统服务中获取WiFi管理器
  33. mWifiManager = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
  34. }
  35. @Override
  36. protected void onResume() {
  37. super.onResume();
  38. IntentFilter filter = new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
  39. registerReceiver(mWifiScanReceiver, filter); // 注册WiFi扫描的广播接收器
  40. }
  41. @Override
  42. protected void onPause() {
  43. super.onPause();
  44. unregisterReceiver(mWifiScanReceiver); // 注销WiFi扫描的广播接收器
  45. }
  46. // 定义一个扫描周边WiFi的广播接收器
  47. private class WifiScanReceiver extends BroadcastReceiver {
  48. @Override
  49. public void onReceive(Context context, Intent intent) {
  50. // 获取WiFi扫描的结果列表
  51. List<ScanResult> scanList = mWifiManager.getScanResults();
  52. if (scanList != null) {
  53. // 查找符合80211标准的WiFi路由器集合
  54. Map<String, ScanResult> m80211mcMap = find80211mcResults(scanList);
  55. runOnUiThread(() -> showScanResult(scanList, m80211mcMap));
  56. }
  57. }
  58. }
  59. // 查找符合80211标准的WiFi路由器集合
  60. private Map<String, ScanResult> find80211mcResults(List<ScanResult> originList) {
  61. Map<String, ScanResult> resultMap = new HashMap<>();
  62. for (ScanResult scanResult : originList) { // 遍历扫描发现的WiFi列表
  63. if (scanResult.is80211mcResponder()) { // 符合80211标准
  64. resultMap.put(scanResult.BSSID, scanResult); // BSSID表示MAC地址
  65. }
  66. }
  67. return resultMap;
  68. }
  69. // 显示过滤后的WiFi扫描结果
  70. private void showScanResult(List<ScanResult> list, Map<String, ScanResult> map) {
  71. tv_result.setText(String.format("找到%d个WiFi热点,其中有%d个支持RTT。",
  72. list.size(), map.size()));
  73. lv_scan.setAdapter(new ScanListAdapter(this, list, map));
  74. }
  75. }

三、计算往返时延RTT

这个要求路由器具备RTT功能,还要求手机支持室内wifi定位 效果如下

代码如下

  1. package com.example.location;
  2. import android.Manifest;
  3. import android.content.BroadcastReceiver;
  4. import android.content.Context;
  5. import android.content.Intent;
  6. import android.content.IntentFilter;
  7. import android.content.pm.PackageManager;
  8. import android.net.wifi.ScanResult;
  9. import android.net.wifi.WifiManager;
  10. import android.net.wifi.rtt.RangingRequest;
  11. import android.net.wifi.rtt.RangingResult;
  12. import android.net.wifi.rtt.RangingResultCallback;
  13. import android.net.wifi.rtt.WifiRttManager;
  14. import android.os.Build;
  15. import android.os.Bundle;
  16. import android.util.Log;
  17. import android.widget.TextView;
  18. import androidx.annotation.RequiresApi;
  19. import androidx.appcompat.app.AppCompatActivity;
  20. import androidx.core.app.ActivityCompat;
  21. import java.util.ArrayList;
  22. import java.util.List;
  23. @RequiresApi(api = Build.VERSION_CODES.P)
  24. public class WifiRttActivity extends AppCompatActivity {
  25. private final static String TAG = "WifiRttActivity";
  26. private TextView tv_result; // 声明一个文本视图对象
  27. private WifiManager mWifiManager; // 声明一个WiFi管理器对象
  28. private WifiScanReceiver mWifiScanReceiver = new WifiScanReceiver(); // 声明一个WiFi扫描接收器对象
  29. private WifiRttManager mRttManager; // 声明一个RTT管理器对象
  30. private WifiRttReceiver mWifiRttReceiver = new WifiRttReceiver(); // 声明一个RTT接收器对象
  31. @Override
  32. protected void onCreate(Bundle savedInstanceState) {
  33. super.onCreate(savedInstanceState);
  34. setContentView(R.layout.activity_wifi_rtt);
  35. tv_result = findViewById(R.id.tv_result);
  36. findViewById(R.id.btn_indoor_rtt).setOnClickListener(v -> mWifiManager.startScan());
  37. // 从系统服务中获取WiFi管理器
  38. mWifiManager = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
  39. // 从系统服务中获取RTT管理器
  40. mRttManager = (WifiRttManager) getSystemService(Context.WIFI_RTT_RANGING_SERVICE);
  41. if (getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI_RTT)) {
  42. tv_result.setText("当前设备支持室内WiFi定位");
  43. } else {
  44. tv_result.setText("当前设备不支持室内WiFi定位");
  45. }
  46. }
  47. @Override
  48. protected void onResume() {
  49. super.onResume();
  50. IntentFilter filterScan = new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
  51. registerReceiver(mWifiScanReceiver, filterScan); // 注册Wifi扫描的广播接收器
  52. IntentFilter filterRtt = new IntentFilter(WifiRttManager.ACTION_WIFI_RTT_STATE_CHANGED);
  53. registerReceiver(mWifiRttReceiver, filterRtt); // 注册RTT状态变更的广播接收器
  54. }
  55. @Override
  56. protected void onPause() {
  57. super.onPause();
  58. unregisterReceiver(mWifiScanReceiver); // 注销Wifi扫描的广播接收器
  59. unregisterReceiver(mWifiRttReceiver); // 注销RTT状态变更的广播接收器
  60. }
  61. // 定义一个扫描周边WiFi的广播接收器
  62. private class WifiScanReceiver extends BroadcastReceiver {
  63. @Override
  64. public void onReceive(Context context, Intent intent) {
  65. // 获取WiFi扫描的结果列表
  66. List<ScanResult> scanList = mWifiManager.getScanResults();
  67. if (scanList != null) {
  68. // 查找符合80211标准的WiFi路由器集合
  69. List<ScanResult> m80211mcList = find80211mcResults(scanList);
  70. runOnUiThread(() -> {
  71. String desc = String.format("找到%d个Wifi热点,其中有%d个支持RTT。",
  72. scanList.size(), m80211mcList.size());
  73. tv_result.setText(desc);
  74. });
  75. if (m80211mcList.size() > 0) {
  76. rangingRtt(m80211mcList.get(0)); // 测量与RTT节点之间的距离
  77. }
  78. }
  79. }
  80. }
  81. // 查找符合80211标准的WiFi路由器集合
  82. private List<ScanResult> find80211mcResults(List<ScanResult> originList) {
  83. List<ScanResult> resultList = new ArrayList<>();
  84. for (ScanResult scanResult : originList) { // 遍历扫描发现的WiFi列表
  85. if (scanResult.is80211mcResponder()) { // 符合80211标准
  86. resultList.add(scanResult);
  87. }
  88. }
  89. return resultList;
  90. }
  91. // 测量与RTT节点之间的距离
  92. private void rangingRtt(ScanResult scanResult) {
  93. if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
  94. tv_result.setText("请先授予定位权限");
  95. return;
  96. }
  97. RangingRequest.Builder builder = new RangingRequest.Builder();
  98. builder.addAccessPoint(scanResult); // 添加测距入口,参数为ScanResult类型
  99. // builder.addWifiAwarePeer(); // MacAddress类型
  100. RangingRequest request = builder.build();
  101. // 开始测量当前设备与指定RTT节点(路由器)之间的距离
  102. mRttManager.startRanging(request, getMainExecutor(), new RangingResultCallback() {
  103. // 测距失败时触发
  104. @Override
  105. public void onRangingFailure(int code) {
  106. Log.d(TAG, "RTT扫描失败,错误代码为"+code);
  107. }
  108. // 测距成功时触发
  109. @Override
  110. public void onRangingResults(List<RangingResult> results) {
  111. for (RangingResult result : results) {
  112. if (result.getStatus() == RangingResult.STATUS_SUCCESS
  113. && scanResult.BSSID.equals(result.getMacAddress().toString())) {
  114. result.getDistanceMm(); // 获取当前设备与路由器之间的距离(单位毫米)
  115. result.getDistanceStdDevMm(); // 获取测量偏差(单位毫米)
  116. result.getRangingTimestampMillis(); // 获取测量耗时(单位毫秒)
  117. result.getRssi(); // 获取路由器的信号
  118. }
  119. }
  120. }
  121. });
  122. }
  123. private class WifiRttReceiver extends BroadcastReceiver {
  124. @Override
  125. public void onReceive(Context context, Intent intent) {
  126. if (mRttManager.isAvailable()) {
  127. runOnUiThread(() -> tv_result.setText("室内WiFi定位功能可以使用"));
  128. } else {
  129. runOnUiThread(() -> tv_result.setText("室内WiFi定位功能不可使用"));
  130. }
  131. }
  132. }
  133. }

创作不易 觉得有帮助请点赞关注收藏~~~


本文转载自: https://blog.csdn.net/jiebaoshayebuhui/article/details/128104410
版权归原作者 showswoller 所有, 如有侵权,请联系我们删除。

“【Android App】检查手机连接WiFi信息以及扫描周围WiFi的讲解及实战(附源码和演示 超详细必看)”的评论:

还没有评论