Android
Wi-Fi
Programming
Connectivity
Network

How do I connect to a specific Wi-Fi network in Android programmatically?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Connecting to a specific Wi-Fi network programmatically in Android depends heavily on platform version. Older APIs allowed direct network configuration changes, while modern Android versions emphasize user consent and privacy. The correct implementation therefore starts with version checks and the right API per range.

Android Version Model You Need to Follow

For Android 10 and newer, direct connection using legacy WifiManager configuration is restricted for normal apps. The supported approach is WifiNetworkSpecifier for temporary connections or WifiNetworkSuggestion for user-approved ongoing suggestions.

For older devices, WifiManager with WifiConfiguration may still work, but that path is legacy.

Android 10 and Newer with WifiNetworkSpecifier

Use a network request through ConnectivityManager.

kotlin
1import android.content.Context
2import android.net.*
3import android.net.wifi.WifiNetworkSpecifier
4import androidx.annotation.RequiresApi
5
6@RequiresApi(29)
7fun connectToWifi(context: Context, ssid: String, passphrase: String) {
8    val specifier = WifiNetworkSpecifier.Builder()
9        .setSsid(ssid)
10        .setWpa2Passphrase(passphrase)
11        .build()
12
13    val request = NetworkRequest.Builder()
14        .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
15        .setNetworkSpecifier(specifier)
16        .build()
17
18    val connectivityManager =
19        context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
20
21    val callback = object : ConnectivityManager.NetworkCallback() {
22        override fun onAvailable(network: Network) {
23            connectivityManager.bindProcessToNetwork(network)
24        }
25
26        override fun onUnavailable() {
27            // handle connection failure in UI
28        }
29    }
30
31    connectivityManager.requestNetwork(request, callback)
32}

This gives app-scoped routing while active. Clean up callback registration when no longer needed.

Ongoing Network Preference with Suggestions

If your app should recommend known networks over time, use suggestions.

kotlin
1import android.net.wifi.WifiManager
2import android.net.wifi.WifiNetworkSuggestion
3
4fun suggestWifi(wifiManager: WifiManager, ssid: String, passphrase: String): Int {
5    val suggestion = WifiNetworkSuggestion.Builder()
6        .setSsid(ssid)
7        .setWpa2Passphrase(passphrase)
8        .build()
9
10    return wifiManager.addNetworkSuggestions(listOf(suggestion))
11}

Users still control final connection behavior, which aligns with current Android security principles.

Legacy Path for Older Devices

For pre-Android-10 environments, legacy configuration may be necessary.

kotlin
1@Suppress("DEPRECATION")
2fun legacyConnect(wifiManager: WifiManager, ssid: String, passphrase: String) {
3    val config = android.net.wifi.WifiConfiguration().apply {
4        SSID = ""$ssid""
5        preSharedKey = ""$passphrase""
6    }
7
8    val networkId = wifiManager.addNetwork(config)
9    wifiManager.disconnect()
10    wifiManager.enableNetwork(networkId, true)
11    wifiManager.reconnect()
12}

Use this only when targeting old API levels where it is still permitted.

Permissions and UX Requirements

Modern Android Wi-Fi flows require both technical and user-facing handling. Missing permission prompts are a common reason connection code appears to do nothing.

Typical requirements include location permission and enabled location services, depending on API level and operation type. Check and request them before initiating connection.

kotlin
1if (checkSelfPermission(android.Manifest.permission.ACCESS_FINE_LOCATION)
2    != android.content.pm.PackageManager.PERMISSION_GRANTED) {
3    requestPermissions(arrayOf(android.Manifest.permission.ACCESS_FINE_LOCATION), 1001)
4}

Also provide clear UI messaging when the network is unavailable or credentials are rejected. Users need actionable feedback, not silent failure. Combine callback-based status updates with visible state in your screen model.

Enterprise environments may also require WPA3, hidden SSIDs, or certificate-based authentication. Model these as explicit options in your connection layer rather than hardcoding one security mode. That keeps your implementation adaptable when deployment environments change.

For supportability, capture connection attempt telemetry such as target SSID, API path used, and callback outcome code. Structured logs make field debugging much faster when users report intermittent failures.

Pair telemetry with privacy-safe data handling and clear retention rules.

Common Pitfalls

A common pitfall is using only one code path for all Android versions. Behavior changes significantly across API levels, so version-guard your implementation.

Another issue is missing permissions and runtime location requirements for Wi-Fi scans and connection flows.

Developers also forget lifecycle cleanup. If you bind process network routing, unbind when the operation ends so the app does not stay pinned unexpectedly.

Finally, test on physical devices. Emulator Wi-Fi behavior is limited and can mask real-world connection issues.

Summary

  • Wi-Fi connection APIs are version-dependent in Android.
  • Use WifiNetworkSpecifier for modern app-scoped connection requests.
  • Use WifiNetworkSuggestion for user-approved ongoing network recommendations.
  • Keep legacy WifiManager code only for older API ranges.
  • Validate permissions, lifecycle cleanup, and behavior on real hardware.

Course illustration
Course illustration

All Rights Reserved.