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

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

相关文章
|
19天前
|
移动开发 小程序
仿青藤之恋社交交友软件系统源码 即时通讯 聊天 微信小程序 App H5三端通用
仿青藤之恋社交交友软件系统源码 即时通讯 聊天 微信小程序 App H5三端通用
47 3
|
21天前
|
JSON JavaScript 前端开发
harmony-chatroom 自研纯血鸿蒙OS Next 5.0聊天APP实战案例
HarmonyOS-Chat是一个基于纯血鸿蒙OS Next5.0 API12实战开发的聊天应用程序。这个项目使用了ArkUI和ArkTS技术栈,实现了类似微信的消息UI布局、输入框光标处插入文字、emoji表情图片/GIF动图、图片预览、红包、语音/位置UI、长按语音面板等功能。
45 2
|
1月前
|
移动开发 HTML5
HTML5熊猫弹跳手机小游戏源码
一款html5手机端小游戏源码,熊猫跳跃小游戏源码下载。熊猫脚底有弹簧,长按变化力度跳跃,计分游戏,html5手机熊猫也疯狂小游戏源代码。
41 5
|
1月前
|
移动开发 HTML5
HTML5实现手机端红包下落抢红包特效源码
HTML5实现手机端红包下落抢红包特效源码是一款手机移动端的抢红包小游戏源码下载。红包像下雪一样,点击抓我呀,可以抢红包,需要此款代码的朋友们可以前来下载使用。本段代码兼容目前最新的各类主流浏览器,是一款非常优秀的特效源码。
36 4
|
1月前
|
监控 安全 开发者
山东布谷科技:关于直播源码|语音源码|一对一直播源码提交App Store的流程及重构经验
分享提交直播源码,一对一直播源码,语音源码到Appstore的重构经验!
|
1月前
|
NoSQL 应用服务中间件 PHP
布谷一对一直播源码服务器环境配置及app功能
一对一直播源码阿里云服务器环境配置及要求
|
1月前
|
机器人
布谷直播App系统源码开发之后台管理功能详解
直播系统开发搭建管理后台功能详解!
|
2月前
|
NoSQL PHP Redis
布谷语音app源码服务器环境配置及技术开发语言
布谷语音app源码服务器环境配置及技术语言研发。。
|
7月前
|
Android开发 Python
Python封装ADB获取Android设备wifi地址的方法
Python封装ADB获取Android设备wifi地址的方法
156 0
|
7月前
|
XML API Android开发
Android WIFI使用简述(上)
Android WIFI使用简述(上)
295 0

热门文章

最新文章