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

简介: 【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的相关信息

代码如下

package com.example.location;
import com.example.location.util.IPv4Util;
import com.example.location.util.NetUtil;
import android.annotation.SuppressLint;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.os.Handler;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Looper;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.widget.TextView;
@SuppressLint("DefaultLocale")
public class WifiInfoActivity extends AppCompatActivity {
    private static final String TAG = "WifiInfoActivity";
    private TextView tv_info; // 声明一个文本视图对象
    private Handler mHandler = new Handler(Looper.myLooper()); // 声明一个处理器对象
    private String[] mWifiStateArray = {"正在断开", "已断开", "正在连接", "已连接", "未知"};
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_wifi_info);
        tv_info = findViewById(R.id.tv_info);
        mHandler.postDelayed(mRefresh, 50); // 延迟50毫秒后启动网络刷新任务
    }
    // 定义一个网络刷新任务
    private Runnable mRefresh = new Runnable() {
        @Override
        public void run() {
            getAvailableNet(); // 获取可用的网络信息
            // 延迟1秒后再次启动网络刷新任务
            mHandler.postDelayed(this, 1000);
        }
    };
    // 获取可用的网络信息
    private void getAvailableNet() {
        String desc = "";
        // 从系统服务中获取电话管理器
        TelephonyManager tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
        // 从系统服务中获取连接管理器
        ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
        // 通过连接管理器获得可用的网络信息
        NetworkInfo info = cm.getActiveNetworkInfo();
        if (info != null && info.getState() == NetworkInfo.State.CONNECTED) { // 有网络连接
            if (info.getType() == ConnectivityManager.TYPE_WIFI) { // WiFi网络(无线热点)
                // 从系统服务中获取无线网络管理器
                WifiManager wm = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
                int state = wm.getWifiState(); // 获得无线网络的状态
                WifiInfo wifiInfo = wm.getConnectionInfo(); // 获得无线网络信息
                String SSID = wifiInfo.getSSID(); // 获得无线网络的名称
                if (TextUtils.isEmpty(SSID) || SSID.contains("unknown")) {
                    desc = "\n当前联网的网络类型是WiFi,但未成功连接已知的WiFi信号";
                } else {
                    desc = String.format("当前联网的网络类型是WiFi,状态是%s。\nWiFi名称是:%s\n路由器MAC是:%s\nWiFi信号强度是:%d\n连接速率是:%s\n手机的IP地址是:%s\n手机的MAC地址是:%s\n网络编号是:%s\n",
                            mWifiStateArray[state], SSID, wifiInfo.getBSSID(),
                            wifiInfo.getRssi(), wifiInfo.getLinkSpeed(),
                            IPv4Util.intToIp(wifiInfo.getIpAddress()),
                            wifiInfo.getMacAddress(), wifiInfo.getNetworkId());
                }
            } else if (info.getType() == ConnectivityManager.TYPE_MOBILE) { // 移动网络(数据连接)
                int net_type = info.getSubtype();
                desc = String.format("\n当前联网的网络类型是%s %s",
                        NetUtil.getNetworkTypeName(tm, net_type),
                        NetUtil.getClassName(tm, net_type));
            } else {
                desc = String.format("\n当前联网的网络类型是%d", info.getType());
            }
        } else { // 无网络连接
            desc = "\n当前无上网连接";
        }
        tv_info.setText(desc);
    }
}

二、扫描周围的无线网络

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

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

代码如下

package com.example.location;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiManager;
import android.os.Build;
import android.os.Bundle;
import android.widget.ListView;
import android.widget.TextView;
import com.example.location.adapter.ScanListAdapter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@RequiresApi(api = Build.VERSION_CODES.M)
public class WifiScanActivity extends AppCompatActivity {
    private final static String TAG = "WifiScanActivity";
    private TextView tv_result; // 声明一个文本视图对象
    private ListView lv_scan; // 声明一个列表视图对象
    private WifiManager mWifiManager; // 声明一个WiFi管理器对象
    private WifiScanReceiver mWifiScanReceiver = new WifiScanReceiver(); // 声明一个WiFi扫描接收器对象
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_wifi_scan);
        tv_result = findViewById(R.id.tv_result);
        lv_scan = findViewById(R.id.lv_scan);
        findViewById(R.id.btn_scan).setOnClickListener(v -> mWifiManager.startScan());
        // 从系统服务中获取WiFi管理器
        mWifiManager = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
    }
    @Override
    protected void onResume() {
        super.onResume();
        IntentFilter filter = new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
        registerReceiver(mWifiScanReceiver, filter); // 注册WiFi扫描的广播接收器
    }
    @Override
    protected void onPause() {
        super.onPause();
        unregisterReceiver(mWifiScanReceiver); // 注销WiFi扫描的广播接收器
    }
    // 定义一个扫描周边WiFi的广播接收器
    private class WifiScanReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            // 获取WiFi扫描的结果列表
            List<ScanResult> scanList = mWifiManager.getScanResults();
            if (scanList != null) {
                // 查找符合80211标准的WiFi路由器集合
                Map<String, ScanResult> m80211mcMap = find80211mcResults(scanList);
                runOnUiThread(() -> showScanResult(scanList, m80211mcMap));
            }
        }
    }
    // 查找符合80211标准的WiFi路由器集合
    private Map<String, ScanResult> find80211mcResults(List<ScanResult> originList) {
        Map<String, ScanResult> resultMap = new HashMap<>();
        for (ScanResult scanResult : originList) { // 遍历扫描发现的WiFi列表
            if (scanResult.is80211mcResponder()) { // 符合80211标准
                resultMap.put(scanResult.BSSID, scanResult); // BSSID表示MAC地址
            }
        }
        return resultMap;
    }
    // 显示过滤后的WiFi扫描结果
    private void showScanResult(List<ScanResult> list, Map<String, ScanResult> map) {
        tv_result.setText(String.format("找到%d个WiFi热点,其中有%d个支持RTT。",
                                        list.size(), map.size()));
        lv_scan.setAdapter(new ScanListAdapter(this, list, map));
    }
}

三、计算往返时延RTT

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

代码如下

package com.example.location;
import android.Manifest;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiManager;
import android.net.wifi.rtt.RangingRequest;
import android.net.wifi.rtt.RangingResult;
import android.net.wifi.rtt.RangingResultCallback;
import android.net.wifi.rtt.WifiRttManager;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import java.util.ArrayList;
import java.util.List;
@RequiresApi(api = Build.VERSION_CODES.P)
public class WifiRttActivity extends AppCompatActivity {
    private final static String TAG = "WifiRttActivity";
    private TextView tv_result; // 声明一个文本视图对象
    private WifiManager mWifiManager; // 声明一个WiFi管理器对象
    private WifiScanReceiver mWifiScanReceiver = new WifiScanReceiver(); // 声明一个WiFi扫描接收器对象
    private WifiRttManager mRttManager; // 声明一个RTT管理器对象
    private WifiRttReceiver mWifiRttReceiver = new WifiRttReceiver(); // 声明一个RTT接收器对象
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_wifi_rtt);
        tv_result = findViewById(R.id.tv_result);
        findViewById(R.id.btn_indoor_rtt).setOnClickListener(v -> mWifiManager.startScan());
        // 从系统服务中获取WiFi管理器
        mWifiManager = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
        // 从系统服务中获取RTT管理器
        mRttManager = (WifiRttManager) getSystemService(Context.WIFI_RTT_RANGING_SERVICE);
        if (getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI_RTT)) {
            tv_result.setText("当前设备支持室内WiFi定位");
        } else {
            tv_result.setText("当前设备不支持室内WiFi定位");
        }
    }
    @Override
    protected void onResume() {
        super.onResume();
        IntentFilter filterScan = new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
        registerReceiver(mWifiScanReceiver, filterScan); // 注册Wifi扫描的广播接收器
        IntentFilter filterRtt = new IntentFilter(WifiRttManager.ACTION_WIFI_RTT_STATE_CHANGED);
        registerReceiver(mWifiRttReceiver, filterRtt); // 注册RTT状态变更的广播接收器
    }
    @Override
    protected void onPause() {
        super.onPause();
        unregisterReceiver(mWifiScanReceiver); // 注销Wifi扫描的广播接收器
        unregisterReceiver(mWifiRttReceiver); // 注销RTT状态变更的广播接收器
    }
    // 定义一个扫描周边WiFi的广播接收器
    private class WifiScanReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            // 获取WiFi扫描的结果列表
            List<ScanResult> scanList = mWifiManager.getScanResults();
            if (scanList != null) {
                // 查找符合80211标准的WiFi路由器集合
                List<ScanResult> m80211mcList = find80211mcResults(scanList);
                runOnUiThread(() -> {
                    String desc = String.format("找到%d个Wifi热点,其中有%d个支持RTT。",
                            scanList.size(), m80211mcList.size());
                    tv_result.setText(desc);
                });
                if (m80211mcList.size() > 0) {
                    rangingRtt(m80211mcList.get(0)); // 测量与RTT节点之间的距离
                }
            }
        }
    }
    // 查找符合80211标准的WiFi路由器集合
    private List<ScanResult> find80211mcResults(List<ScanResult> originList) {
        List<ScanResult> resultList = new ArrayList<>();
        for (ScanResult scanResult : originList) { // 遍历扫描发现的WiFi列表
            if (scanResult.is80211mcResponder()) { // 符合80211标准
                resultList.add(scanResult);
            }
        }
        return resultList;
    }
    // 测量与RTT节点之间的距离
    private void rangingRtt(ScanResult scanResult) {
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            tv_result.setText("请先授予定位权限");
            return;
        }
        RangingRequest.Builder builder = new RangingRequest.Builder();
        builder.addAccessPoint(scanResult); // 添加测距入口,参数为ScanResult类型
//            builder.addWifiAwarePeer(); // MacAddress类型
        RangingRequest request = builder.build();
        // 开始测量当前设备与指定RTT节点(路由器)之间的距离
        mRttManager.startRanging(request, getMainExecutor(), new RangingResultCallback() {
            // 测距失败时触发
            @Override
            public void onRangingFailure(int code) {
                Log.d(TAG, "RTT扫描失败,错误代码为"+code);
            }
            // 测距成功时触发
            @Override
            public void onRangingResults(List<RangingResult> results) {
                for (RangingResult result : results) {
                    if (result.getStatus() == RangingResult.STATUS_SUCCESS
                            && scanResult.BSSID.equals(result.getMacAddress().toString())) {
                        result.getDistanceMm(); // 获取当前设备与路由器之间的距离(单位毫米)
                        result.getDistanceStdDevMm(); // 获取测量偏差(单位毫米)
                        result.getRangingTimestampMillis(); // 获取测量耗时(单位毫秒)
                        result.getRssi(); // 获取路由器的信号
                    }
                }
            }
        });
    }
    private class WifiRttReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (mRttManager.isAvailable()) {
                runOnUiThread(() -> tv_result.setText("室内WiFi定位功能可以使用"));
            } else {
                runOnUiThread(() -> tv_result.setText("室内WiFi定位功能不可使用"));
            }
        }
    }
}

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

目录
打赏
0
1
1
1
153
分享
相关文章
【03】仿站技术之python技术,看完学会再也不用去购买收费工具了-修改整体页面做好安卓下载发给客户-并且开始提交网站公安备案-作为APP下载落地页文娱产品一定要备案-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
【03】仿站技术之python技术,看完学会再也不用去购买收费工具了-修改整体页面做好安卓下载发给客户-并且开始提交网站公安备案-作为APP下载落地页文娱产品一定要备案-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
109 13
【03】仿站技术之python技术,看完学会再也不用去购买收费工具了-修改整体页面做好安卓下载发给客户-并且开始提交网站公安备案-作为APP下载落地页文娱产品一定要备案-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
移动端数据抓取:Android App的TLS流量解密方案
本文介绍了一种通过TLS流量解密技术抓取知乎App热榜数据的方法。利用Charles Proxy解密HTTPS流量,分析App与服务器通信内容;结合Python Requests库模拟请求,配置特定请求头以绕过反爬机制。同时使用代理IP隐藏真实IP地址,确保抓取稳定。最终成功提取热榜标题、内容简介、链接等信息,为分析热点话题和用户趋势提供数据支持。此方法也可应用于其他Android App的数据采集,但需注意选择可靠的代理服务。
63 11
移动端数据抓取:Android App的TLS流量解密方案
布谷一对一直播源码android版环境配置流程及功能明细
部署需基于 CentOS 7.9 系统,硬盘不低于 40G,使用宝塔面板安装环境,包括 PHP 7.3(含 Redis、Fileinfo 扩展)、Nginx、MySQL 5.6、Redis 和最新 Composer。Swoole 扩展需按步骤配置。2021.08.05 后部署需将站点目录设为 public 并用 ThinkPHP 伪静态。开发环境建议 Windows 操作系统与最新 Android Studio,基础配置涉及 APP 名称修改、接口域名更换、包名调整及第三方登录分享(如 QQ、微信)的配置,同时需完成阿里云与腾讯云相关设置。
【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
85 8
【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
【02】仿站技术之python技术,看完学会再也不用去购买收费工具了-本次找了小影-感觉页面很好看-本次是爬取vue需要用到Puppeteer库用node.js扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
【02】仿站技术之python技术,看完学会再也不用去购买收费工具了-本次找了小影-感觉页面很好看-本次是爬取vue需要用到Puppeteer库用node.js扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
94 7
【02】仿站技术之python技术,看完学会再也不用去购买收费工具了-本次找了小影-感觉页面很好看-本次是爬取vue需要用到Puppeteer库用node.js扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
74 4
【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
Python封装ADB获取Android设备wifi地址的方法
Python封装ADB获取Android设备wifi地址的方法
236 0
Android WIFI使用简述(上)
Android WIFI使用简述(上)
525 0
|
11月前
|
Android 状态栏WiFi图标的显示逻辑
Android 状态栏WiFi图标的显示逻辑
304 0
|
11月前
|
Android获取当前连接的wifi名称
Android获取当前连接的wifi名称
409 6

热门文章

最新文章