I'm working on a Wifi auto connect feature and I am shocked how broken that API is.
I'm using now 5 different APIs and I still don't get it in a way the user would expect it.
I have a setting to enable wifi auto connection on Android 10+ I'll try this:
- Check if I hold the
ACCESS_WIFI_STATEpermission with:
When I own the permission I go on with 2. if not I continue with 6.appOpsManager.unsafeCheckOp("android:change_wifi_state", Process.myUid(), context.packageName) == AppOpsManager.MODE_ALLOWED - When I hold the permission I'll check on Android 11+ if from a previous run my wifi suggestion was saved
wifiManager.networkSuggestions.isNotEmpty()if that is true I check which Wifi I'm currently connected with see step x. On lower levels I skip this and go to step 3 - I use the wifi suggestion API with the
WifiNetworkSuggestion.Builder()and suggest the user my wifi withval status = wifiManager.addNetworkSuggestions(listOf(suggestion)) // Strage bug: On first usage the return value is always SUCCESS val success = status == WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS - When the user accepts my suggestion I'm fine so far. I cannot verify on Android 10 if my suggestion was accepted. On Android 11 this is possible (see step 2). However I still don't know if the device actually connected with the wifi. So I go to step 7
- When the user rejected my suggestion I'm almost out of the game I can never ask the user again (well technically there is a well hidden feature where you can switch the permission, but no user will ever find it). On Android 10 I can just check if I'm connected with the right wifi, well at least theoretically (see step 7).
- On Android 11+ I can fallback to the
Settings.ACTION_WIFI_ADD_NETWORKSintent which can always add Wifis (with the downside that the user can share the wifi password) - I need to verify if the steps before worked and the user is actually connected to the desired wifi. To do so I already own the permissions
ACCESS_WIFI_STATE,ACCESS_NETWORK_STATE,ACCESS_COARSE_LOCATIONandACCESS_FINE_LOCATION. However theConnectivityManagerAPI don't return the actualSSID, that drives me crazy. - If the user is not connected to the right wifi I would try to use the
Settings.Panel.ACTION_WIFIaction to let the user to connect to the right wifi
To summarize that:
- I use the
WifiNetworkSuggestionAPI - I fallback to
Settings.ACTION_WIFI_ADD_NETWORKSwhere possible - I try to verify if the user is currently connected to the right wifi
- I try to assist the user to conenct to the right wifi (or even turn wifi on) with the
Settings.Panel.ACTION_WIFIaction
Is that really such a mess or is there a easier way?
I'm currently accessing the SSID like this:
private val currentSsid: String?
get() =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
val wifiInfo = connectivityManager.getNetworkCapabilities(connectivityManager.activeNetwork)?.transportInfo as? WifiInfo
wifiInfo?.ssid
} else {
wifiManager.connectionInfo?.ssid
}
Based on Unable to get WIFI SSID using onCapabilitiesChanged in Android 12 I think that way I access the value is not supported. I get currently the value "<unknown ssid>".
ACCESS_WIFI_STATEis anormalpermission, one that has been around since Android 1.0. Outside of rooted devices or crazy ROMs, if your app is installed and running, you have the permission. Are there scenarios where you see otherwise?ACCESS_FINE_LOCATION. Note that depending on circumstance, you may getnullfor the SSID, specifically if you are connecting to a network without Internet access and the user has not accepted the notification that alerts them of this fact. Once they accept the notification, you should get the SSID.ACCESS_WIFI_STATEpermission check this bug: issuetracker.google.com/issues/224071894 it seems that when you press on "no thanks" that this permission is revoked (the way to change this is documented there too)"<unknown ssid>". See Unable to get WIFI SSID using onCapabilitiesChanged in Android 12 I think that way I access the value is not supported. I'll try now that broadcast receiver with that flag.null-- it has been a bit since I poked at this scenario. I know that there's an interim value until the user accepts that notification. However, I'm not usingonCapabilitiesChanged()in a callback; perhapsgetNetworkCapabilities()behaves a bit differently, somehow.