home-assistant / home-assistant/android

Concurrent Local-Only Wifi Support

Open
#3,961 9 comments 11 reactions 0 assignees View on GitHub
enhancement
Dominant language
Kotlin
Stars
3.9k
Forks
1.1k
Avg merge
1d 12h
Merged PRs (30d)
81

Description

**Is your feature request related to a problem? Please describe.**

Home Assistant is designed with a focus on local control. If a Home Assistant server is on a local only network (no internet access) in recent versions of Android (tested in 13 & 14, but I believe 12 is also an issue), the Android device will drop the WiFi network and only stay connected to the mobile network if one is present. This forces a user to disable the LTE on their phone to connect to the Wi-Fi network and control their Home Assistant Server. This is a very frustrating user experience for offline servers of Home Assistant when using the Android app with LTE connection.

**Describe the solution you'd like**

I would like to take advantage of [Concurrent local-only and internet connection](https://source.android.com/docs/core/connect/wifi-sta-sta-concurrency#local-only) in more recent Android SDKs. This allows for the internet to be provided by LTE or a primary WiFi network, while the app connects to a secondary WiFi that does not have internet access for local only access. It was designed for IoT support, but should work well with an offline Home Assistant server.

We would allow a checkbox next to Home network WiFi SSD entry screen to allow users to designate if a Wi-Fi network may only have local access (no internet).

We could then use the SSID from the local access only network to connect to the server by using `WifiNetworkSpecifier.Builder()` similar to this:

```
fun connectToLocalOnlyNetwork(ssid: String, context: Context) {
val wifiNetworkSpecifier = WifiNetworkSpecifier.Builder()
.setSsid(ssid)
.build()

val networkRequest = NetworkRequest.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN) // Ensure it's not a VPN
.setNetworkSpecifier(wifiNetworkSpecifier)
.build()

val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager

val networkCallback = object : ConnectivityManager.NetworkCallback() {
override fun onAvailable(network: Network) {
super.onAvailable(network)
// Local-only WiFi is connected
}

override fun onUnavailable() {
super.onUnavailable()
// Failed to connect
}
}

connectivityManager.requestNetwork(networkRequest, networkCallback)
}
```

We would want to enable the checkbox to support this only on devices with Android 10 or later and maybe only for devices where `WifiManager#isStaConcurrencyForLocalOnlyConnectionsSupported()` is true. However, that might just need to be a warning that selecting local support will disconnect their other WiFi in order to connect to Home Assistant if it is false.

I think the primary issue to determine is how to create the connection to the local only WiFi network for just regular metrics updates and not drain the battery with a WiFi scan if it is disconnected. Testing is certainly required for that.

**Describe alternatives you've considered, if any**

The primary alternative here is turning off LTE access to connect to a WiFi network. We could also consider Concurrent restricted and internet connection or a `bindProcessToNetwork()`, but I think both of these have drawbacks that Concurrent local-only and internet connection do not have.

**Additional context**

This is related to #675 which was closed due to a lack of support at the time from Android SDK to support this.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.