Android 掃描WIFI權(quán)限詳解
權(quán)限
上篇文章 Android 獲取IP和UA中提及了獲取WIFI的IP地址,本篇文章介紹下如何掃描WIFI。
根據(jù)官方文檔描述,掃描WIFI需要申請(qǐng)相關(guān)權(quán)限,如下:
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以上,當(dāng)usesPermissionFlags設(shè)置為neverForLocation時(shí),無需再申請(qǐng)ACCESS_FINE_LOCATION權(quán)限--> <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>
需要注意,在實(shí)際測(cè)試中,Android 13以上的設(shè)備仍然需要申請(qǐng)android.permission.ACCESS_FINE_LOCATION
才能掃描到WIFI,測(cè)試設(shè)備為小米13。
注冊(cè)廣播監(jiān)聽掃描狀態(tài)
通過注冊(cè)廣播監(jiān)聽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) // 注冊(cè)廣播 registerReceiver(scanResultReceiver, IntentFilter().apply { addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION) }) } override fun onDestroy() { super.onDestroy() // 移除廣播 unregisterReceiver(scanResultReceiver) } }
掃描WIFI
通過WifiManager掃描WIFI,并獲取掃描結(jié)果,代碼如下:
// 列表適配器 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) { // 申請(qǐng)定位權(quán)限通過,掃描WIFI if (wifiManager?.isWifiEnabled == true) { wifiManager?.startScan() } } else { //未同意授權(quán) if (!shouldShowRequestPermissionRationale(requestPermissionName)) { //用戶拒絕權(quán)限并且系統(tǒng)不再?gòu)棾稣?qǐng)求權(quán)限的彈窗 //這時(shí)需要我們自己處理,比如自定義彈窗告知用戶為何必須要申請(qǐng)這個(gè)權(quán)限 } } } 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信號(hào)強(qiáng)度 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)) } // 根據(jù)信號(hào)強(qiáng)度降序排列 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 { // 檢測(cè)定位權(quán)限 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) } }
效果如圖:
示例
在示例Demo中添加了相關(guān)的演示代碼。
以上就是Android 掃描WIFI權(quán)限詳解的詳細(xì)內(nèi)容,更多關(guān)于Android 掃描WIFI權(quán)限的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Android實(shí)現(xiàn)用戶圓形頭像和模糊背景
這篇文章主要介紹了Android實(shí)現(xiàn)用戶圓形頭像和模糊背景 ,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-04-04詳解如何從原生Android 跳轉(zhuǎn)到hbuilder項(xiàng)目
這篇文章主要介紹了從原生Android 跳轉(zhuǎn)到hbuilder項(xiàng)目,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-08-08monkeyrunner之電腦安裝驅(qū)動(dòng)(5)
這篇文章主要為大家詳細(xì)介紹了monkeyrunner之電腦安裝驅(qū)動(dòng)的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-12-12android studio 新建項(xiàng)目報(bào)錯(cuò)的解決之路
這篇文章主要介紹了android studio 新建工程報(bào)錯(cuò),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-03-03Android自定義View圓形和拖動(dòng)圓跟隨手指拖動(dòng)
這篇文章主要介紹了Android自定義View圓形和拖動(dòng)圓跟隨手指拖動(dòng),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-11-11Android Dialog 設(shè)置字體大小的具體方法
這篇文章介紹了Android Dialog 設(shè)置字體大小的具體方法,希望能幫助到有同樣需求的朋友,可能我的方法不是最好的,也希望有朋友指點(diǎn)2013-09-09Android Studio如何快速導(dǎo)入jar和.so文件
這篇文章主要介紹了Android Studio如何快速導(dǎo)入jar和.so文件的相關(guān)知識(shí),非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2017-12-12Android 調(diào)用設(shè)備已有的相機(jī)應(yīng)用詳情
這篇文章主要介紹了Android 調(diào)用設(shè)備已有的相機(jī)應(yīng)用,如果我們只是需要讓用戶能夠拍攝照片,則可以直接請(qǐng)求已有相機(jī)應(yīng)用拍攝照片并將照片返回給我們,下面我們一起來看看這些功能,需要的朋友可以參考一下2021-10-10