软件编程
位置:首页>> 软件编程>> Android编程>> Android 扫描WIFI权限详解

Android 扫描WIFI权限详解

作者:ChenYhong  发布时间:2023-07-03 11:34:32 

标签:Android,WIFI,扫描,权限

权限

上篇文章 Android 获取IP和UA中提及了获取WIFI的IP地址,本篇文章介绍下如何扫描WIFI。

官方文档

根据官方文档描述,扫描WIFI需要申请相关权限,如下:

Android 13以上

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
   <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
   <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
   <!--在Android13以上,当usesPermissionFlags设置为neverForLocation时,无需再申请ACCESS_FINE_LOCATION权限-->
   <uses-permission
       android:name="android.permission.NEARBY_WIFI_DEVICES"
       android:usesPermissionFlags="neverForLocation" />
</manifest>

Android 13以下

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
   <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
   <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
   <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
</manifest>

需要注意,在实际测试中,Android 13以上的设备仍然需要申请android.permission.ACCESS_FINE_LOCATION才能扫描到WIFI,测试设备为小米13。

注册广播监听扫描状态

通过注册广播监听WIFI扫描是否完成,代码如下:

class WIFIExampleActivity : AppCompatActivity() {
   private val scanResultReceiver = object : BroadcastReceiver() {
       override fun onReceive(context: Context?, intent: Intent?) {
           if (intent?.getBooleanExtra(WifiManager.EXTRA_RESULTS_UPDATED, false) == true) {
               // 扫描完成
           }
       }
   }
   override fun onCreate(savedInstanceState: Bundle?) {
       super.onCreate(savedInstanceState)
       // 注册广播
       registerReceiver(scanResultReceiver, IntentFilter().apply {
           addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)
       })
   }
   override fun onDestroy() {
       super.onDestroy()
       // 移除广播
       unregisterReceiver(scanResultReceiver)
   }
}

扫描WIFI

通过WifiManager扫描WIFI,并获取扫描结果,代码如下:

// 列表适配器
class WIFIAdapter : RecyclerView.Adapter<WIFIAdapter.WIFIViewHolder>() {
   private val wifiData = ArrayList<WIFIEntity>()
   override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): WIFIViewHolder {
       return WIFIViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.layout_wifi_item, parent, false))
   }
   override fun onBindViewHolder(holder: WIFIViewHolder, position: Int) {
       wifiData[position].run {
           holder.tvWifiName.text = wifiSSID
           holder.tvWifiSSID.text = wifiBSSID
           holder.ivWifiStrength.setImageResource(getStrengthIcon(wifiStrength))
           holder.ivNeedPassword.setImageResource(if (needPassword) R.drawable.icon_lock else R.drawable.icon_unlock)
       }
   }
   override fun getItemCount(): Int {
       return wifiData.size
   }
   fun setNewData(wifiData: ArrayList<WIFIEntity>?) {
       val lastItemCount = itemCount
       if (lastItemCount != 0) {
           this.wifiData.clear()
           notifyItemRangeRemoved(0, lastItemCount)
       }
       wifiData?.let { this.wifiData.addAll(it) }
       notifyItemChanged(0, itemCount)
   }
   private fun getStrengthIcon(wifiStrength: Int): Int {
       return when (wifiStrength) {
           0 -> R.drawable.wifi_strength_0
           1 -> R.drawable.wifi_strength_1
           2 -> R.drawable.wifi_strength_2
           else -> R.drawable.wifi_strength_3
       }
   }
   interface ItemClickListener {
       fun onItemClick(wifiInfo: WIFIEntity)
   }
   class WIFIViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
       val tvWifiName: AppCompatTextView = itemView.findViewById(R.id.tv_wifi_name)
       val tvWifiSSID: AppCompatTextView = itemView.findViewById(R.id.tv_wifi_ssid)
       val ivNeedPassword: AppCompatImageView = itemView.findViewById(R.id.iv_need_password)
       val ivWifiStrength: AppCompatImageView = itemView.findViewById(R.id.iv_wifi_strength)
   }
}
class WIFIExampleActivity : AppCompatActivity() {
   private lateinit var binding: LayoutWifiExampleActivityBinding
   private val wifiAdapter = WIFIAdapter()
   private var wifiManager: WifiManager? = null
   private var requestPermissionName: String = Manifest.permission.ACCESS_FINE_LOCATION
   private val requestSinglePermissionLauncher = registerForActivityResult(ActivityResultContracts.RequestPermission()) { granted: Boolean ->
       if (granted) {
           // 申请定位权限通过,扫描WIFI
           if (wifiManager?.isWifiEnabled == true) {
               wifiManager?.startScan()
           }
       } else {
           //未同意授权
           if (!shouldShowRequestPermissionRationale(requestPermissionName)) {
               //用户拒绝权限并且系统不再弹出请求权限的弹窗
               //这时需要我们自己处理,比如自定义弹窗告知用户为何必须要申请这个权限
           }
       }
   }
   private val scanResultReceiver = object : BroadcastReceiver() {
       override fun onReceive(context: Context?, intent: Intent?) {
           if (intent?.getBooleanExtra(WifiManager.EXTRA_RESULTS_UPDATED, false) == true) {
               val wifiData = ArrayList<WIFIEntity>()
               wifiManager?.scanResults?.forEach {
                   val ssid = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
                       it.wifiSsid.toString()
                   } else {
                       it.SSID
                   }
                   val bssid = it.BSSID
                   // 获取WIFI加密类型
                   val capabilities = it.capabilities
                   // 获取WIFI信号强度
                   val level = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
                       wifiManager?.calculateSignalLevel(it.level) ?: 0
                   } else {
                       WifiManager.calculateSignalLevel(it.level, 4)
                   }
                   wifiData.add(WIFIEntity(ssid, bssid, capabilities.contains("wpa", true) || capabilities.contains("web", true), capabilities, level))
               }
               // 根据信号强度降序排列
               wifiData.sortByDescending { it.wifiStrength }
               wifiAdapter.setNewData(wifiData)
           }
       }
   }
   override fun onCreate(savedInstanceState: Bundle?) {
       super.onCreate(savedInstanceState)
       binding = DataBindingUtil.setContentView(this, R.layout.layout_wifi_example_activity)
       wifiManager = applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager
       binding.includeTitle.tvTitle.text = "WIFI Example"
       binding.btnStartScan.setOnClickListener {
           // 检测定位权限
           if (ActivityCompat.checkSelfPermission(this, requestPermissionName) == PackageManager.PERMISSION_GRANTED) {
               if (wifiManager?.isWifiEnabled == true) {
                   wifiManager?.startScan()
               }
           } else {
               requestSinglePermissionLauncher.launch(requestPermissionName)
           }
       }
       binding.rvWifiInfo.adapter = wifiAdapter
       registerReceiver(scanResultReceiver, IntentFilter().apply {
           addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)
       })
   }
   override fun onDestroy() {
       super.onDestroy()
       unregisterReceiver(scanResultReceiver)
   }
}

效果如图:

Android 扫描WIFI权限详解

示例

在示例Demo中添加了相关的演示代码。

ExampleDemo github

ExampleDemo gitee

来源:https://juejin.cn/post/7212074532340056123

0
投稿

猜你喜欢

  • Java判断一个字符串是否有中文一般情况是利用Unicode编码(CJK统一汉字的编码区间:0x4e00–0x9fbb)的正则来做判断,但是
  • 先上结论:不要直接用double变量作为构造BigDecimal的参数。线上有这么一段Java代码逻辑:1,接口传来一个JSON串,里面有个
  • 队列的特性很简答,就是先进先出,一般利用数组来实现。实现队列自然要实现几个函数:入队,出队,判断队满,判断队空,获得队头,队尾。实现队列的关
  • JDBC Statement对象实例以下是利用以下三种查询以及打开和关闭说明的例子:boolean execute(String SQL)
  • 本文实例讲述了C#实现汉字转拼音或转拼音首字母的方法。分享给大家供大家参考。具体实现方法如下:/// <summary>///
  • 前言从来没接触过flutter,我将在这里记录下我的flutter学习踩坑历程。安装就从安装开始叭,官网链接在此。先遵照官网教程来叭。系统要
  • 这一节我们先写一个简单点的Demo来测试易宝支付的流程,熟悉这个流程后,再做实际的开发,因为是一个Demo,所以我没有考虑一些设计模式的东西
  • 一、介绍1、"Lambda表达式"是一个特殊的匿名函数,简化了匿名委托的使用,是一种高效的类似于函数式编程的表达式,La
  • 冒泡排序冒泡排序的思想: 每次让当前的元素和它的下一个元素比较大小、如果前一个的元素大于后一个元素的话,交换两个元素。这样的话经历一次扫描之
  • 在Spring Boot集成Mybatis的项目中,如果出现SQL语句执行问题,我们需要进行排查。此时就需要打印对应的SQL语句,那么该如何
  • 安装方式:使用vs自带的nuget管理工具,搜索AutoMapper ,选择第一个安装到你的项目即可。先说说DTODTO是个什么东东?DTO
  • 数组排序在很多的面试题上都会出现数组排序的操作形式。但是这个时候你千万别写上:java.util.Arrays.sort(数组)。而这种排序
  • 本文实例讲述了Java基于二叉查找树实现排序功能。分享给大家供大家参考,具体如下:/** * 无论排序的对象是什么,都要实现Comparab
  • step1. 导包(导入要使用的标签的jar文件)。step2. 使用taglib指令引入要使用的标签。taglib指令: &nb
  • 本文实例为大家分享了C#简单聊天室雏形的具体代码,供大家参考,具体内容如下程序使用的控制台的黑窗口模拟程序,第一次涉及网络编程,写出来方便以
  • 责任链模式责任链模式的定义:使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系, 将这个对象连成一条链,并沿着这条链传递
  • Viewpager 横向滑动效果系统就自带了很多种,比如这个效果 那如果做成竖屏的这种效果呢 。我百度过很多,效果都不是很好,有的代码特别多
  • 一、简介1.为了防止一个应用程序控制CPU而导致其他应用程序和操作系统本身永远被挂起这一可能情况,操作系统不得不使用某种方式将物理计算分割为
  • Android 监听手机GPS打开状态实现代码GPS_Presenterpackage com.yiba.core;import andro
  • 偶然机会看到一种对象初始的方式:// 新建一个列表,并赋值 "Harry","Tony","
手机版 软件编程 asp之家 www.aspxhome.com