最近在做一个wifi相关的项目,因此去了解了官方文档和相关技术资料,整理了一下目前wifi连接的可行性和办法,包括扫描、连接、状态监听。
二、使用方法
目前安卓10开始官方已经弃用原来的连接wifi了,改用对等连接:
developer.android.com/guide/topic…
而这个对等连接其实就是APP内部连接到该wifi,但是手机本身是保持原来连接的wifi的,所以原来那种修改系统wifi连接的已经弃用了,想继续使用,需要把项目targetSdkVersion修改为小于29。
1.wifi管理类
object WifiUtils {
val mWifiManager by lazy {
WiFiMoneyApplication.getApplication ()?.applicationContext?.getSystemService(Context.WIFI_SERVICE) as WifiManager
开启wifi
fun openWifi () {
mWifiManager.isWifiEnabled = true
连接wifi
@SuppressLint("MissingPermission" )
fun connectWifi (context: Context , scanResults: List <ScanResult >, ssid: String , connect: (success : Boolean , scanResult : ScanResult ) -> Unit ) {
if (!mWifiManager.isWifiEnabled) {
return
val scanResult = scanResults.singleOrNull { it.SSID == ssid }
if (scanResult != null ) {
val config = mWifiManager.configuredNetworks.singleOrNull { it.SSID.replace("\"" , "" ) == ssid }
if (config != null && config.status != WifiConfiguration.Status.DISABLED) {
if (BuildConfig.LOG_DEBUG) {
Log.d(TAG, "找到了历史wifi:${scanResult.SSID} " )
connect.invoke(mWifiManager.enableNetwork(config.networkId, true ), scanResult)
} else {
val type = getCipherType(scanResult.capabilities)
if (type == WifiCapability.WIFI_CIPHER_NO_PASS) {
val padWifiNetwork =
createWifiConfig(
scanResult.SSID,
type = getCipherType(scanResult.capabilities))
val netId = mWifiManager.addNetwork(padWifiNetwork)
if (BuildConfig.LOG_DEBUG) {
Log.d(TAG, "不需要密码连接wifi:${scanResult.SSID} " )
connect.invoke(mWifiManager.enableNetwork(netId, true ), scanResult)
} else {
if (BuildConfig.LOG_DEBUG) {
Log.d(TAG, "需要密码连接wifi:${scanResult.SSID} " )
connect.invoke(false , scanResult)
} else {
if (BuildConfig.LOG_DEBUG) {
Log.d(TAG, "connectWifi 没有找到" )
@SuppressLint("MissingPermission" )
fun createWifiConfig (
ssid: String ,
password: String = "" ,
type: WifiCapability
) : WifiConfiguration {
val config = WifiConfiguration()
config.allowedAuthAlgorithms.clear()
config.allowedGroupCiphers.clear()
config.allowedKeyManagement.clear()
config.allowedPairwiseCiphers.clear()
config.allowedProtocols.clear()
config.SSID = "\"" + ssid + "\""
val tempConfig = mWifiManager.configuredNetworks.singleOrNull { it.BSSID == "\"$ssid \"" }
if (tempConfig != null ) {
val isDisable = mWifiManager.disableNetwork(tempConfig.networkId)
val isRemove = mWifiManager.removeNetwork(tempConfig.networkId)
val isSave = mWifiManager.saveConfiguration()
if (BuildConfig.LOG_DEBUG) {
Log.d(TAG, "清除wifi配置:${tempConfig.SSID + (isDisable && isRemove && isSave)} " )
if (type == WifiCapability.WIFI_CIPHER_NO_PASS) {
config.allowedKeyManagement.set (WifiConfiguration.KeyMgmt.NONE)
} else if (type == WifiCapability.WIFI_CIPHER_WEP) {
config.hiddenSSID = true
config.wepKeys[0 ] = "\"" + password + "\""
config.allowedAuthAlgorithms.set (WifiConfiguration.AuthAlgorithm.OPEN)
config.allowedAuthAlgorithms.set (WifiConfiguration.AuthAlgorithm.SHARED)
config.allowedKeyManagement.set (WifiConfiguration.KeyMgmt.NONE)
config.wepTxKeyIndex = 0
} else if (type == WifiCapability.WIFI_CIPHER_WPA) {
config.preSharedKey = "\"" + password + "\""
config.hiddenSSID = true
config.allowedAuthAlgorithms.set (WifiConfiguration.AuthAlgorithm.OPEN)
config.allowedGroupCiphers.set (WifiConfiguration.GroupCipher.TKIP)
config.allowedKeyManagement.set (WifiConfiguration.KeyMgmt.WPA_PSK)
config.allowedPairwiseCiphers.set (WifiConfiguration.PairwiseCipher.TKIP)
config.allowedGroupCiphers.set (WifiConfiguration.GroupCipher.CCMP)
config.allowedPairwiseCiphers.set (WifiConfiguration.PairwiseCipher.CCMP)
config.status = WifiConfiguration.Status.ENABLED
return config
fun getCipherType (capabilities: String ) : WifiCapability {
return when {
capabilities.contains("WEB" ) -> {
WifiCapability.WIFI_CIPHER_WEP
capabilities.contains("PSK" ) -> {
WifiCapability.WIFI_CIPHER_WPA
capabilities.contains("WPS" ) -> {
WifiCapability.WIFI_CIPHER_NO_PASS
else -> {
WifiCapability.WIFI_CIPHER_NO_PASS
enum class WifiCapability {
WIFI_CIPHER_WEP, WIFI_CIPHER_WPA, WIFI_CIPHER_NO_PASS
fun connectWifi (item: ScanResult) {
if (item.BSSID == WifiUtils.mWifiManager.connectionInfo.bssid) {
ToastUtils.showToast (context, getString(R.string.wifi_home_connect_error))
return
if (BuildConfig.LOG_DEBUG) {
Log.d (TAG, "开始切换wifi")
WifiUtils.connectWifi (context!!, mWifiList, item.SSID) { success, scanResult ->
if (success) {
} else {
activity?.let { activity ->
InputPasswordDialog (activity, scanResult.SSID) { password ->
val padWifiNetwork =
WifiUtils.createWifiConfig (
scanResult.SSID,
password,
WifiUtils.getCipherType(scanResult.capabilities)
val netId = WifiUtils.mWifiManager .addNetwork (padWifiNetwork)
val success2 = WifiUtils.mWifiManager .enableNetwork (netId, true)
if (success2) {
if (BuildConfig.LOG_DEBUG) {
Log.d (TAG, "这个时候找到wifi,开始连接:${success2}")
startConnectAni (item)
} else {
if (BuildConfig.LOG_DEBUG) {
Log.d (TAG, "创建连接失败")
ToastUtils.showToast (context!!, "创建连接失败")
}?.show ()
wifi强度获取
fun getNetworkWifiLevel (wifiInfo: ScanResult ) : Int {
val level = wifiInfo.level
return if (level <= 0 && level >= -50 ) {
else if (level < -50 && level >= -70 ) {
else if (level < -70 && level >= -80 ) {
else if (level < -80 && level >= -100 ) {
else {
2.wifi连接状态监听
private fun registerWifiStatusListener () {
val filter = IntentFilter ()
filter .addAction (SUPPLICANT_STATE_CHANGED_ACTION)
filter .addAction (WIFI_STATE_CHANGED_ACTION)
filter .addAction (NETWORK_STATE_CHANGED_ACTION)
filter .addAction (SCAN_RESULTS_AVAILABLE_ACTION)
filter .addAction ("android.net.conn.CONNECTIVITY_CHANGE")
activity?.application ?.registerReceiver (mWifiReceiver, filter)
private val mWifiReceiver: BroadcastReceiver by lazy {
object : BroadcastReceiver () {
override fun onReceive (context: Context?, intent: Intent) {
if (intent.action === WIFI_STATE_CHANGED_ACTION) {
when (intent.getIntExtra(EXTRA_WIFI_STATE, WIFI_STATE_UNKNOWN)) {
WIFI_STATE_DISABLED -> {
updateWifiStatus (6 )
WIFI_STATE_DISABLING -> {}
WIFI_STATE_ENABLED -> {}
WIFI_STATE_ENABLING -> {
updateWifiStatus (5 )
WIFI_STATE_UNKNOWN -> {
updateWifiStatus (1 )
} else if (NETWORK_STATE_CHANGED_ACTION == intent.getAction()) {
val info: NetworkInfo = intent.getParcelableExtra (EXTRA_NETWORK_INFO)
if (NetworkInfo.State.DISCONNECTED == info.state) {
if (BuildConfig.LOG_DEBUG) {
Log.d (TAG, "连接已断开")
} else if (NetworkInfo.State.CONNECTED == info.state) {
if (BuildConfig.LOG_DEBUG) {
Log.d ("TAG, "wifi连接上了")
refreshWifiList ()
} else if (NetworkInfo.State.CONNECTING == info.state) {
if (BuildConfig.LOG_DEBUG) {
Log.d (TAG, "wifi正在连接")
} else if (SCAN_RESULTS_AVAILABLE_ACTION == intent.action) {
val success = intent.getBooleanExtra (WifiManager.EXTRA_RESULTS_UPDATED, false)
if (success) {
scanSuccess ()
} else {
scanFailure ()
} else if (SUPPLICANT_STATE_CHANGED_ACTION == intent.action) {
val error = intent.getIntExtra (EXTRA_SUPPLICANT_ERROR, -1 )
if (error == ERROR_AUTHENTICATING) {
if (BuildConfig.LOG_DEBUG) {
Log.d (TAG, "获取连接状态:密码错误")
return
val supplicantState: SupplicantState =
intent.getParcelableExtra (EXTRA_NEW_STATE)
when (supplicantState) {
SupplicantState.COMPLETED
-> {
if (BuildConfig.LOG_DEBUG) {
Log.d (TAG, "获取连接状态:成功")
SupplicantState.INACTIVE -> {
if (BuildConfig.LOG_DEBUG) {
Log.d (TAG, "获取连接状态:不活跃的")
SupplicantState.INTERFACE_DISABLED -> {
if (BuildConfig.LOG_DEBUG) {
Log.d (TAG, "获取连接状态:接口禁用")
SupplicantState.DISCONNECTED -> {
if (BuildConfig.LOG_DEBUG) {
Log.d (TAG, "获取连接状态:断开连接")
SupplicantState.SCANNING -> {
if (BuildConfig.LOG_DEBUG) {
Log.d (TAG, "获取连接状态:正在扫描")
SupplicantState.AUTHENTICATING -> {
if (BuildConfig.LOG_DEBUG) {
Log.d (TAG, "获取连接状态:正在验证")
SupplicantState.ASSOCIATING -> {
if (BuildConfig.LOG_DEBUG) {
Log.d (TAG, "获取连接状态:正在关联")
SupplicantState.ASSOCIATED -> {
if (BuildConfig.LOG_DEBUG) {
Log.d (TAG, "获取连接状态:已经关联")
SupplicantState.FOUR_WAY_HANDSHAKE -> {
if (BuildConfig.LOG_DEBUG) {
Log.d (TAG, "获取连接状态:四次握手")
SupplicantState.GROUP_HANDSHAKE -> {
if (BuildConfig.LOG_DEBUG) {
Log.d (TAG, "获取连接状态:组握手")
SupplicantState.DORMANT -> {
if (BuildConfig.LOG_DEBUG) {
Log.d (TAG, "获取连接状态:休眠")
SupplicantState.UNINITIALIZED -> {
if (BuildConfig.LOG_DEBUG) {
Log.d (TAG, "获取连接状态:未初始化")
SupplicantState.INVALID -> {
if (BuildConfig.LOG_DEBUG) {
Log.d (TAG, "获取连接状态:无效的")
else -> {
if (BuildConfig.LOG_DEBUG) {
Log.d (TAG, "wifi连接结果通知")
} else if ("android.net.conn.CONNECTIVITY_CHANGE" == intent.action) {
if (BuildConfig.LOG_DEBUG) {
Log.d (TAG, "网络类型切换了")
updateNetWorkType ()
3.wifi相关权限申请
RxPermissions (this).request (
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.CHANGE_WIFI_STATE,
Manifest.permission.ACCESS_WIFI_STATE
).subscribe {
if (!it) {
4.wifi列表更新
fun refreshWifiList () {
if (!WifiUtils.mWifiManager.isWifiEnabled) {
return
mWifiList.clear ()
val originList = WifiUtils.mWifiManager .scanResults
val currentWifi = originList.singleOrNull {
it.BSSID == WifiUtils.mWifiManager .connectionInfo .bssid &&
WifiUtils.mWifiManager .connectionInfo .supplicantState == SupplicantState.COMPLETED
for ((i, _) in originList.withIndex ()) {
val position : Int = getItemPosition (mWifiList, originList[i])
// 过滤没有名字的,没有意义
if (originList[i].SSID.isNotEmpty ()) {
if (position != -1 ) {
if (mWifiList[position].level < originList[i].level) {
mWifiList.removeAt (position)
mWifiList.add (position, originList[i])
} else {
mWifiList.add (originList[i])
mWifiList.sortWith (Comparator { t1, t2 -> t2.level - t1.level })
var p = -1
currentWifi?.let {
for ((i, value) in mWifiList.withIndex ()) {
if (currentWifi.BSSID == value.BSSID) {
p = i
updateWifiName ()
if (p != -1 && currentWifi != null) {
mWifiList.removeAt (p)
mWifiList.add (0 , currentWifi)
mWifiAdapter.connectPosition = 0
} else {
mWifiAdapter.connectPosition = -1
mWifiAdapter.notifyDataSetChanged ()
if (mLastStatus != 2 || (mLastStatus == 2 && currentWifi != null)) {
if (mWifiList.isNotEmpty()) {
updateWifiStatus (1 )
} else {
updateWifiStatus (4 )
updateListOpenOrNot ()
5.正在使用的网络类型判断(在监听关闭wifi网络的时候,调用这个依然返回有网络)
object NetworkUtils {
const val NETWORK_NOT_DEFINE = -2
const val NETWORK_NONE = -1
const val NETWORK_WIFI = 1
const val NETWORK_2G = 2
const val NETWORK_3G = 3
const val NETWORK_4G = 4
const val NETWORK_5G = 5
const val NETWORK_MOBILE = 0
* 获取当前网络连接的类型
* @param context context
* @return int
fun getNetworkState (context: Context ) : Int {
val connManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
val activeNetInfo = connManager.activeNetworkInfo
if (activeNetInfo == null || !activeNetInfo.isAvailable) {
return NETWORK_NONE
val wifiInfo = connManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI)
if (null != wifiInfo) {
val state = wifiInfo.state
if (null != state) {
if (state == NetworkInfo.State.CONNECTED || state == NetworkInfo.State.CONNECTING) {
return NETWORK_WIFI
val telephonyManager = context.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
val networkType = telephonyManager.networkType
return when (networkType) {
TelephonyManager.NETWORK_TYPE_GPRS, TelephonyManager.NETWORK_TYPE_CDMA, TelephonyManager.NETWORK_TYPE_EDGE, TelephonyManager.NETWORK_TYPE_1xRTT, TelephonyManager.NETWORK_TYPE_IDEN -> NETWORK_2G
TelephonyManager.NETWORK_TYPE_EVDO_A, TelephonyManager.NETWORK_TYPE_UMTS, TelephonyManager.NETWORK_TYPE_EVDO_0, TelephonyManager.NETWORK_TYPE_HSDPA, TelephonyManager.NETWORK_TYPE_HSUPA, TelephonyManager.NETWORK_TYPE_HSPA, TelephonyManager.NETWORK_TYPE_EVDO_B, TelephonyManager.NETWORK_TYPE_EHRPD, TelephonyManager.NETWORK_TYPE_HSPAP -> NETWORK_3G
TelephonyManager.NETWORK_TYPE_LTE -> NETWORK_4G
TelephonyManager.NETWORK_TYPE_NR -> NETWORK_5G
else -> NETWORK_MOBILE
* 是否正在用手机流量
fun isMobileNetwork (context: Context ) : Boolean {
val a = getNetworkState(context)
if (BuildConfig.LOG_DEBUG) {
Log.d(TAG, "是否正在用手机流量 getNetworkState:${a} " )
return a != NETWORK_NONE && a != NETWORK_NOT_DEFINE && a != NETWORK_WIFI
6.wifi相关api需要定位功能,需要判断用户有没有开定位
* 手机是否开启位置服务
fun isLocServiceEnable (context: Context ) : Boolean {
val locationManager = context.getSystemService(Context.LOCATION_SERVICE) as LocationManager
val gps = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)
val network = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)
return gps || network
7.android10以上新功能,也列出来吧。
P2P连接Wifi就是对等连接,在APP内部会出现对话框,请求某个wifi连接,仅APP内部使用
@RequiresApi(Build.VERSION_CODES.Q)
fun connectByP2P (context: Context , scanResult: ScanResult , password: String , successListener: ((Network ?) -> Unit )? = null , failListener: (() -> Unit )? = null ) {
val specifier = WifiNetworkSpecifier.Builder()
.setSsidPattern(PatternMatcher(scanResult.SSID, PatternMatcher.PATTERN_PREFIX))
.setWpa2Passphrase(password)
.build()
val request =
NetworkRequest.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
.removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.setNetworkSpecifier(specifier)
.build()
val connectivityManager =
context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
val networkCallback = object : ConnectivityManager.NetworkCallback() {
override fun onAvailable (network: Network ?) {
connectivityManager.bindProcessToNetwork(network)
successListener?.invoke(network)
override fun onUnavailable () {
failListener?.invoke()
connectivityManager.requestNetwork(request, networkCallback)
这个是给系统提建议,个人感觉非常鸡肋
@RequiresApi(Build.VERSION_CODES.Q)
private fun connectBySug (ssid: String , password: String ) {
val suggestion = WifiNetworkSuggestion.Builder()
.setSsid(ssid)
.setWpa2Passphrase(password)
.setIsAppInteractionRequired(true )
.build()
val suggestionsList = listOf(suggestion)
val status = wifiManager.addNetworkSuggestions(suggestionsList)
if (status != WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS) {
val intentFilter = IntentFilter(WifiManager.ACTION_WIFI_NETWORK_SUGGESTION_POST_CONNECTION);
val broadcastReceiver = object : BroadcastReceiver() {
override fun onReceive (context: Context
, intent: Intent ) {
if (!intent.action.equals(WifiManager.ACTION_WIFI_NETWORK_SUGGESTION_POST_CONNECTION)) {
return
context.registerReceiver(broadcastReceiver, intentFilter);
总结:在开发过程中发现wifi的监听真的非常多,估计并没有列出完全监听,欢迎大家可以补充,有问题可以评论讨论。
3748
西瓜king
Android
Kotlin
4522
小余的自习室
Android
掘金·金石计划
1207
西瓜king
Android
Kotlin
2257
TechMerger
Android
Kotlin
Android Studio
1778
RainyJiang
Android
Glide