Android 开发一款Wifi管理器的问题
- 问题:我遇到了一个密码连接的操作,正确的密码无法连接,下面是我的核心代码
\app\src\main\java\com\example\qs_wifi\WifiConnectionManager.kt
WifiConnectionManager.kt
package com.example.qs_wifi
import android.content.Context
import android.net.wifi.WifiManager
import android.net.wifi.WifiNetworkSuggestion
import android.os.Build
import android.util.Log
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import android.net.wifi.WifiConfiguration
import android.net.wifi.WifiInfo
import android.content.IntentFilter
import android.net.wifi.WifiManager.NETWORK_STATE_CHANGED_ACTION
import android.net.wifi.WifiManager.SUPPLICANT_STATE_CHANGED_ACTION
import android.net.wifi.SupplicantState
import android.os.Handler
import android.os.Looper
import kotlin.coroutines.resume
import kotlin.coroutines.suspendCoroutine
import android.content.BroadcastReceiver
import android.content.Intent
import android.net.ConnectivityManager
import android.net.NetworkInfo
import android.os.Parcelable
class WifiConnectionManager(private val context: Context) {
private val wifiManager = context.getSystemService(Context.WIFI_SERVICE) as WifiManager
private val handler = Handler(Looper.getMainLooper())
private val TAG = "WifiConnectionManager"
suspend fun connectToWifi(ssid: String, password: String): Boolean = withContext(Dispatchers.IO) {
try {
Log.d(TAG, "=== 开始WiFi连接流程 ===")
Log.d(TAG, "目标网络: $ssid")
Log.d(TAG, "密码长度: ${password.length}")
// 检查WiFi是否已启用
if (!wifiManager.isWifiEnabled) {
Log.e(TAG, "WiFi未启用,无法连接")
return@withContext false
}
Log.d(TAG, "WiFi已启用")
// 检查是否已连接
val currentWifi = wifiManager.connectionInfo
val currentSsid = currentWifi?.ssid?.removeSurrounding("\"")
Log.d(TAG, "当前连接的网络: $currentSsid")
if (currentSsid == ssid) {
Log.d(TAG, "已经连接到目标网络")
return@withContext true
}
// 尝试连接
Log.d(TAG, "开始尝试连接...")
val success = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
connectWithSuggestion(ssid, password)
} else {
connectWithConfiguration(ssid, password)
}
if (!success) {
Log.e(TAG, "连接请求失败")
return@withContext false
}
// 等待连接结果
Log.d(TAG, "等待连接结果...")
waitForConnection(ssid)
} catch (e: Exception) {
Log.e(TAG, "连接WiFi时发生错误", e)
false
}
}
private suspend fun waitForConnection(ssid: String): Boolean = suspendCoroutine { continuation ->
var isConnected = false
var retryCount = 0
val maxRetries = 20 // 最多等待10秒
val receiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
when (intent.action) {
NETWORK_STATE_CHANGED_ACTION -> {
@Suppress("DEPRECATION")
val networkInfo = intent.getParcelableExtra<NetworkInfo>(WifiManager.EXTRA_NETWORK_INFO)
Log.d(TAG, "网络状态变化: ${networkInfo?.isConnected}")
if (networkInfo?.isConnected == true) {
val currentWifi = wifiManager.connectionInfo
val currentSsid = currentWifi?.ssid?.removeSurrounding("\"")
Log.d(TAG, "当前连接的网络: $currentSsid")
if (currentSsid == ssid) {
// 验证连接状态
val supplicantState = wifiManager.connectionInfo.supplicantState
Log.d(TAG, "Supplicant状态: $supplicantState")
if (supplicantState == SupplicantState.COMPLETED) {
Log.d(TAG, "连接成功完成")
isConnected = true
context.unregisterReceiver(this)
continuation.resume(true)
} else {
Log.d(TAG, "连接未完成,当前状态: $supplicantState")
}
}
}
}
SUPPLICANT_STATE_CHANGED_ACTION -> {
@Suppress("DEPRECATION")
val state = intent.getParcelableExtra<SupplicantState>(WifiManager.EXTRA_NEW_STATE)
Log.d(TAG, "Supplicant状态变化: $state")
when (state) {
SupplicantState.DISCONNECTED -> {
retryCount++
Log.d(TAG, "连接断开,重试次数: $retryCount")
if (retryCount >= maxRetries) {
Log.e(TAG, "达到最大重试次数,连接失败")
context.unregisterReceiver(this)
continuation.resume(false)
}
}
SupplicantState.AUTHENTICATING -> {
Log.d(TAG, "正在验证...")
}
SupplicantState.ASSOCIATING -> {
Log.d(TAG, "正在关联...")
}
SupplicantState.ASSOCIATED -> {
Log.d(TAG, "已关联")
}
SupplicantState.FOUR_WAY_HANDSHAKE -> {
Log.d(TAG, "正在进行四次握手...")
}
SupplicantState.COMPLETED -> {
Log.d(TAG, "连接完成")
}
else -> {
Log.d(TAG, "其他状态: $state")
}
}
}
}
}
}
// 注册接收器
val filter = IntentFilter().apply {
addAction(NETWORK_STATE_CHANGED_ACTION)
addAction(SUPPLICANT_STATE_CHANGED_ACTION)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
addAction(WifiManager.ACTION_WIFI_NETWORK_SUGGESTION_POST_CONNECTION)
}
}
context.registerReceiver(receiver, filter)
Log.d(TAG, "已注册网络状态监听器")
// 设置超时
handler.postDelayed({
if (!isConnected) {
Log.e(TAG, "连接超时")
context.unregisterReceiver(receiver)
continuation.resume(false)
}
}, 10000) // 10秒超时
}
private fun connectWithSuggestion(ssid: String, password: String): Boolean {
Log.d(TAG, "使用WifiNetworkSuggestion方式连接")
val suggestion = WifiNetworkSuggestion.Builder()
.setSsid(ssid)
.setWpa2Passphrase(password)
.setIsAppInteractionRequired(true)
.build()
val suggestions = listOf(suggestion)
val status = wifiManager.addNetworkSuggestions(suggestions)
return when (status) {
WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS -> {
Log.d(TAG, "网络建议添加成功")
true
}
WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_DUPLICATE -> {
Log.d(TAG, "网络建议已存在")
true
}
else -> {
Log.e(TAG, "添加网络建议失败,状态码: $status")
false
}
}
}
private fun connectWithConfiguration(ssid: String, password: String): Boolean {
Log.d(TAG, "使用WifiConfiguration方式连接")
val config = WifiConfiguration().apply {
SSID = "\"$ssid\""
preSharedKey = "\"$password\""
status = WifiConfiguration.Status.ENABLED
allowedProtocols.clear()
allowedKeyManagement.clear()
allowedPairwiseCiphers.clear()
allowedGroupCiphers.clear()
// 设置WPA2加密
allowedProtocols.set(WifiConfiguration.Protocol.RSN)
allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK)
allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP)
allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP)
}
val netId = wifiManager.addNetwork(config)
if (netId == -1) {
Log.e(TAG, "添加网络配置失败")
return false
}
Log.d(TAG, "网络配置添加成功,netId: $netId")
val success = wifiManager.enableNetwork(netId, true)
Log.d(TAG, "启用网络结果: $success")
return success
}
}
\app\src\main\java\com\example\qs_wifi\MainActivity.kt
MainActivity.kt
// MainActivity.kt
package com.example.qs_wifi
import android.Manifest
import android.content.*
import android.content.pm.PackageManager
import android.net.wifi.ScanResult
import android.net.wifi.WifiManager
import android.os.Bundle
import android.provider.Settings
import android.util.Log
import android.widget.Toast
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.LinearLayoutManager
import com.example.qs_wifi.databinding.ActivityMainBinding
import com.example.qs_wifi.databinding.DialogConnectWifiBinding
import com.example.qs_wifi.databinding.DialogProgressBinding
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
class MainActivity : AppCompatActivity() {
private val TAG = "MainActivity"
private lateinit var binding: ActivityMainBinding
private lateinit var wifiManager: WifiManager
private lateinit var wifiConnectionManager: WifiConnectionManager
private lateinit var wifiAdapter: WifiAdapter
private var isScanning = false
private var progressDialog: AlertDialog? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Log.d(TAG, "=== 应用启动 ===")
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
wifiManager = getSystemService(Context.WIFI_SERVICE) as WifiManager
wifiConnectionManager = WifiConnectionManager(this)
Log.d(TAG, "WiFi管理器初始化完成")
setupUI()
checkPermissions()
}
private fun setupUI() {
Log.d(TAG, "设置UI组件")
binding.wifiList.layoutManager = LinearLayoutManager(this)
wifiAdapter = WifiAdapter { wifiItem ->
Log.d(TAG, "用户点击WiFi: ${wifiItem.ssid}")
showConnectDialog(wifiItem)
}
binding.wifiList.adapter = wifiAdapter
binding.swipeRefresh.setOnRefreshListener {
Log.d(TAG, "用户触发刷新")
startWifiScan()
}
binding.fabScan.setOnClickListener {
Log.d(TAG, "用户点击扫描按钮")
startWifiScan()
}
}
private fun showConnectDialog(wifiItem: WifiItem) {
Log.d(TAG, "显示连接对话框: ${wifiItem.ssid}")
if (wifiItem.isConnected) {
Log.d(TAG, "网络已连接,无需操作")
return
}
val dialogBinding = DialogConnectWifiBinding.inflate(layoutInflater)
val dialog = MaterialAlertDialogBuilder(this)
.setTitle("连接 ${wifiItem.ssid}")
.setView(dialogBinding.root)
.setPositiveButton("连接") { dialog, _ ->
val password = dialogBinding.passwordInput.text.toString()
Log.d(TAG, "用户输入密码,长度: ${password.length}")
connectToWifi(wifiItem.ssid, password)
dialog.dismiss()
}
.setNegativeButton("取消", null)
.create()
dialog.show()
}
private fun connectToWifi(ssid: String, password: String) {
Log.d(TAG, "开始连接WiFi: $ssid")
showProgressDialog("正在连接...")
lifecycleScope.launch {
try {
val success = wifiConnectionManager.connectToWifi(ssid, password)
Log.d(TAG, "连接结果: $success")
withContext(Dispatchers.Main) {
progressDialog?.dismiss()
if (success) {
showToast("连接成功")
startWifiScan() // 刷新列表
} else {
showToast("连接失败,请检查密码")
}
}
} catch (e: Exception) {
Log.e(TAG, "连接过程发生异常", e)
withContext(Dispatchers.Main) {
progressDialog?.dismiss()
showToast("连接失败: ${e.message}")
}
}
}
}
private fun startWifiScan() {
if (isScanning) {
Log.d(TAG, "扫描正在进行中,忽略请求")
return
}
Log.d(TAG, "开始WiFi扫描")
isScanning = true
binding.swipeRefresh.isRefreshing = true
binding.fabScan.isEnabled = false
wifiManager.startScan()
registerReceiver(wifiScanReceiver, IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION))
}
private val wifiScanReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
Log.d(TAG, "收到扫描结果广播")
if (intent.action == WifiManager.SCAN_RESULTS_AVAILABLE_ACTION) {
context.unregisterReceiver(this)
handleScanResults()
}
}
}
private fun handleScanResults() {
Log.d(TAG, "处理扫描结果")
try {
val results = wifiManager.scanResults
Log.d(TAG, "扫描到 ${results.size} 个网络")
// 获取当前连接的网络
val currentWifi = wifiManager.connectionInfo
val currentSsid = currentWifi?.ssid?.removeSurrounding("\"")
Log.d(TAG, "当前连接的网络: $currentSsid")
// 获取已保存的网络列表
val savedNetworks = wifiManager.configuredNetworks
val savedSsids = savedNetworks?.map { it.SSID.removeSurrounding("\"") } ?: emptyList()
Log.d(TAG, "已保存的网络: $savedSsids")
// 处理扫描结果
val wifiItems: List<WifiItem> = results
.filter { it.SSID.isNotEmpty() }
.groupBy { it.SSID }
.mapNotNull { (ssid, networks) ->
networks.maxByOrNull { it.level }?.let { bestNetwork ->
val signalStrength = WifiManager.calculateSignalLevel(bestNetwork.level, 100)
val isSecure = bestNetwork.capabilities.contains("WPA") ||
bestNetwork.capabilities.contains("WPA2") ||
bestNetwork.capabilities.contains("WPA3") ||
bestNetwork.capabilities.contains("WEP")
WifiItem(
ssid = ssid,
signalStrength = signalStrength,
isSecure = isSecure,
isSaved = savedSsids.contains(ssid),
isConnected = ssid == currentSsid
)
}
}
.sortedByDescending { it.signalStrength }
Log.d(TAG, "处理后的网络列表大小: ${wifiItems.size}")
wifiAdapter.updateWifiList(wifiItems)
} catch (e: Exception) {
Log.e(TAG, "处理扫描结果时发生错误", e)
} finally {
isScanning = false
binding.swipeRefresh.isRefreshing = false
binding.fabScan.isEnabled = true
}
}
private fun showProgressDialog(message: String) {
Log.d(TAG, "显示进度对话框: $message")
val dialogBinding = DialogProgressBinding.inflate(layoutInflater)
dialogBinding.message.text = message
progressDialog = MaterialAlertDialogBuilder(this)
.setView(dialogBinding.root)
.setCancelable(false)
.create()
progressDialog?.show()
}
private fun showToast(message: String) {
Log.d(TAG, "显示Toast: $message")
Toast.makeText(this, message, Toast.LENGTH_SHORT).show()
}
private fun checkPermissions() {
if (hasRequiredPermissions()) {
startWifiScan()
} else {
requestPermissions()
}
}
private fun hasRequiredPermissions(): Boolean {
return REQUIRED_PERMISSIONS.all {
ActivityCompat.checkSelfPermission(this, it) == PackageManager.PERMISSION_GRANTED
}
}
private fun requestPermissions() {
ActivityCompat.requestPermissions(this, REQUIRED_PERMISSIONS, PERMISSIONS_REQUEST_CODE)
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
if (requestCode == PERMISSIONS_REQUEST_CODE) {
if (grantResults.all { it == PackageManager.PERMISSION_GRANTED }) {
startWifiScan()
} else {
Toast.makeText(this, "需要位置权限才能扫描WiFi", Toast.LENGTH_SHORT).show()
}
}
}
override fun onDestroy() {
super.onDestroy()
try {
unregisterReceiver(wifiScanReceiver)
} catch (e: Exception) {
Log.e(TAG, "取消注册接收器失败", e)
}
progressDialog?.dismiss()
}
companion object {
private const val PERMISSIONS_REQUEST_CODE = 101
private val REQUIRED_PERMISSIONS = arrayOf(
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION
)
}
}
\app\src\main\java\com\example\qs_wifi\WifiItem.kt
WifiItem.kt
package com.example.qs_wifi
data class WifiItem(
val ssid: String,
val signalStrength: Int,
val isSecure: Boolean,
val isSaved: Boolean,
val isConnected: Boolean
) {
companion object {
fun fromScanResult(result: android.net.wifi.ScanResult, isConnected: Boolean, isSaved: Boolean): WifiItem {
val signalStrength = android.net.wifi.WifiManager.calculateSignalLevel(result.level, 100)
val isSecure = result.capabilities.contains("WPA") ||
result.capabilities.contains("WPA2") ||
result.capabilities.contains("WPA3") ||
result.capabilities.contains("WEP")
return WifiItem(
ssid = result.SSID,
signalStrength = signalStrength,
isSecure = isSecure,
isSaved = isSaved,
isConnected = isConnected
)
}
}
}
408

被折叠的 条评论
为什么被折叠?



