【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定位功能不可使用"));
            }
        }
    }
}

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

相关文章
|
2月前
|
传感器 数据采集 移动开发
基于STM32的智能手环wifi连接手机APP(下)
基于STM32的智能手环wifi连接手机APP(下)
108 0
|
1月前
|
移动开发 HTML5
HTML5熊猫弹跳手机小游戏源码
一款html5手机端小游戏源码,熊猫跳跃小游戏源码下载。熊猫脚底有弹簧,长按变化力度跳跃,计分游戏,html5手机熊猫也疯狂小游戏源代码。
46 5
|
1月前
|
移动开发 HTML5
HTML5实现手机端红包下落抢红包特效源码
HTML5实现手机端红包下落抢红包特效源码是一款手机移动端的抢红包小游戏源码下载。红包像下雪一样,点击抓我呀,可以抢红包,需要此款代码的朋友们可以前来下载使用。本段代码兼容目前最新的各类主流浏览器,是一款非常优秀的特效源码。
39 4
|
2月前
|
小程序 JavaScript API
微信小程序开发之:保存图片到手机,使用uni-app 开发小程序;还有微信原生保存图片到手机
这篇文章介绍了如何在uni-app和微信小程序中实现将图片保存到用户手机相册的功能。
963 0
微信小程序开发之:保存图片到手机,使用uni-app 开发小程序;还有微信原生保存图片到手机
|
3月前
|
移动开发 Android开发 数据安全/隐私保护
移动应用与系统的技术演进:从开发到操作系统的全景解析随着智能手机和平板电脑的普及,移动应用(App)已成为人们日常生活中不可或缺的一部分。无论是社交、娱乐、购物还是办公,移动应用都扮演着重要的角色。而支撑这些应用运行的,正是功能强大且复杂的移动操作系统。本文将深入探讨移动应用的开发过程及其背后的操作系统机制,揭示这一领域的技术演进。
本文旨在提供关于移动应用与系统技术的全面概述,涵盖移动应用的开发生命周期、主要移动操作系统的特点以及它们之间的竞争关系。我们将探讨如何高效地开发移动应用,并分析iOS和Android两大主流操作系统的技术优势与局限。同时,本文还将讨论跨平台解决方案的兴起及其对移动开发领域的影响。通过这篇技术性文章,读者将获得对移动应用开发及操作系统深层理解的钥匙。
101 12
|
2月前
|
传感器 存储 编解码
基于STM32的智能手环wifi连接手机APP(上)
基于STM32的智能手环wifi连接手机APP(上)
74 0
|
4月前
|
Ubuntu 网络安全 数据安全/隐私保护
ubuntu server连接wifi教程
本文提供了一个简化Ubuntu Server在Raspberry Pi系统上配置过程的脚本"config_ubuntu_server",包括自动和手动两种方法来设置root权限、SSH配置,并连接WiFi,同时支持无密码SSH访问,适合初学者和高级用户。
103 3
|
4月前
|
移动开发 HTML5
自适应手机端青蛙吃蚊子小游戏html源码
HTML5青蛙吃蚊子游戏源码分享,音乐可以改的,自己在目录替换一下音乐就可以了训练手速和眼力的时候到了!
44 0
自适应手机端青蛙吃蚊子小游戏html源码
|
4月前
|
存储 数据可视化 C语言
【C语言】C语言 手机通讯录系统的设计 (源码+数据+论文)【独一无二】
【C语言】C语言 手机通讯录系统的设计 (源码+数据+论文)【独一无二】
|
5月前
|
JavaScript Java 测试技术
基于SpringBoot+Vue+uniapp的多功能智能手机阅读APP的详细设计和实现(源码+lw+部署文档+讲解等)
基于SpringBoot+Vue+uniapp的多功能智能手机阅读APP的详细设计和实现(源码+lw+部署文档+讲解等)
下一篇
DataWorks