How to Detect Network Connection Type on Android
TLDR: Use ConnectivityManager and NetworkCapabilities (Android 6.0+) to detect network type. Call getActiveNetwork() and getNetworkCapabilities() to check for WiFi, cellular, or Ethernet. For older devices, use the deprecated getActiveNetworkInfo(). Register a NetworkCallback to monitor connection changes in real-time. Always request ACCESS_NETWORK_STATE permission in your manifest.
Android apps often need to know what type of network connection is available - WiFi, cellular, or none. This helps optimize data usage, adjust quality settings, or warn users about expensive mobile data.
Required Permission
First, add the network state permission to your AndroidManifest.xml:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.yourapp">
<!-- Required to check network connectivity -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application>
...
</application>
</manifest>
This permission is normal-level (not dangerous), so you don't need to request it at runtime - just declare it in the manifest.
Modern Approach (Android 6.0+)
For apps targeting Android M (API 23) and higher, use NetworkCapabilities:
import android.content.Context
import android.net.ConnectivityManager
import android.net.NetworkCapabilities
fun getNetworkType(context: Context): String {
val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE)
as ConnectivityManager
// Get the currently active network
val network = connectivityManager.activeNetwork ?: return "No connection"
// Get the capabilities of the active network
val capabilities = connectivityManager.getNetworkCapabilities(network)
?: return "No connection"
return when {
capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> "WiFi"
capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> "Cellular"
capabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) -> "Ethernet"
capabilities.hasTransport(NetworkCapabilities.TRANSPORT_BLUETOOTH) -> "Bluetooth"
capabilities.hasTransport(NetworkCapabilities.TRANSPORT_VPN) -> "VPN"
else -> "Unknown"
}
}
// Usage
val networkType = getNetworkType(context)
Log.d("Network", "Connected via: $networkType")
This API is cleaner and more reliable than the older methods. It correctly handles VPN connections and provides more detailed transport information.
Checking for Internet Connectivity
Having a network connection doesn't guarantee internet access. Check for validated internet:
fun hasInternetConnection(context: Context): Boolean {
val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE)
as ConnectivityManager
val network = connectivityManager.activeNetwork ?: return false
val capabilities = connectivityManager.getNetworkCapabilities(network)
?: return false
return capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) &&
capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)
}
NET_CAPABILITY_VALIDATED means Android has verified the connection can reach the internet (by contacting a server).
Checking for Metered Connections
Cellular connections and some WiFi networks (like hotspots) are metered - they have data limits:
fun isMeteredConnection(context: Context): Boolean {
val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE)
as ConnectivityManager
val network = connectivityManager.activeNetwork ?: return false
val capabilities = connectivityManager.getNetworkCapabilities(network)
?: return false
return !capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED)
}
// Use this to adjust behavior
if (isMeteredConnection(context)) {
// User is on cellular or metered WiFi
// Reduce video quality, defer large downloads, etc.
downloadQuality = Quality.LOW
} else {
// User is on unlimited WiFi
downloadQuality = Quality.HIGH
}
Legacy Approach (Pre-Android 6.0)
For compatibility with older devices, use the deprecated but still functional NetworkInfo:
@Suppress("DEPRECATION")
fun getNetworkTypeLegacy(context: Context): String {
val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE)
as ConnectivityManager
val networkInfo = connectivityManager.activeNetworkInfo
return when {
networkInfo == null -> "No connection"
!networkInfo.isConnected -> "No connection"
networkInfo.type == ConnectivityManager.TYPE_WIFI -> "WiFi"
networkInfo.type == ConnectivityManager.TYPE_MOBILE -> "Cellular"
networkInfo.type == ConnectivityManager.TYPE_ETHERNET -> "Ethernet"
else -> "Unknown"
}
}
Note the @Suppress("DEPRECATION") annotation - this API is deprecated but still works. Use it only if you need to support very old Android versions.
Monitoring Network Changes
To respond when the network changes (WiFi to cellular, or vice versa), register a NetworkCallback:
class NetworkMonitor(private val context: Context) {
private val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE)
as ConnectivityManager
private val networkCallback = object : ConnectivityManager.NetworkCallback() {
override fun onAvailable(network: Network) {
Log.d("Network", "Network available")
// Network connection is available
}
override fun onLost(network: Network) {
Log.d("Network", "Network lost")
// Network connection lost
}
override fun onCapabilitiesChanged(
network: Network,
capabilities: NetworkCapabilities
) {
Log.d("Network", "Network capabilities changed")
when {
capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> {
Log.d("Network", "Connected to WiFi")
// Switch to high quality
}
capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> {
Log.d("Network", "Connected to cellular")
// Switch to lower quality to save data
}
}
}
override fun onUnavailable() {
Log.d("Network", "Network unavailable")
// No network available
}
}
fun startMonitoring() {
connectivityManager.registerDefaultNetworkCallback(networkCallback)
}
fun stopMonitoring() {
connectivityManager.unregisterNetworkCallback(networkCallback)
}
}
// Usage in Activity or Service
class MainActivity : AppCompatActivity() {
private lateinit var networkMonitor: NetworkMonitor
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
networkMonitor = NetworkMonitor(this)
networkMonitor.startMonitoring()
}
override fun onDestroy() {
super.onDestroy()
networkMonitor.stopMonitoring()
}
}
The callback runs whenever the network state changes, letting you adjust your app's behavior dynamically.
Real-World Example: Adaptive Video Quality
Here's how you might use network detection for adaptive streaming:
class VideoPlayer(private val context: Context) {
private var currentQuality = VideoQuality.AUTO
enum class VideoQuality {
LOW, // 360p
MEDIUM, // 720p
HIGH, // 1080p
AUTO
}
fun determineOptimalQuality(): VideoQuality {
val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE)
as ConnectivityManager
val network = connectivityManager.activeNetwork ?: return VideoQuality.LOW
val capabilities = connectivityManager.getNetworkCapabilities(network)
?: return VideoQuality.LOW
// No internet? Use lowest quality (if cached)
if (!capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)) {
return VideoQuality.LOW
}
// Get connection type and bandwidth
return when {
capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> {
// WiFi - check if metered
if (capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED)) {
VideoQuality.HIGH // Unlimited WiFi - go HD
} else {
VideoQuality.MEDIUM // Metered WiFi - be careful
}
}
capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> {
// Cellular - check bandwidth estimate
val downstreamBandwidth = capabilities.linkDownstreamBandwidthKbps
when {
downstreamBandwidth > 5000 -> VideoQuality.MEDIUM // 5+ Mbps - 4G/5G
downstreamBandwidth > 1000 -> VideoQuality.LOW // 1-5 Mbps - 3G
else -> VideoQuality.LOW // <1 Mbps - 2G
}
}
capabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) -> {
VideoQuality.HIGH // Wired connection - full quality
}
else -> VideoQuality.LOW // Unknown connection type - be conservative
}
}
fun setQuality(quality: VideoQuality) {
currentQuality = quality
Log.d("VideoPlayer", "Video quality set to: $quality")
// Apply quality to video player
when (quality) {
VideoQuality.LOW -> loadVideoUrl(lowQualityUrl)
VideoQuality.MEDIUM -> loadVideoUrl(mediumQualityUrl)
VideoQuality.HIGH -> loadVideoUrl(highQualityUrl)
VideoQuality.AUTO -> setQuality(determineOptimalQuality())
}
}
private fun loadVideoUrl(url: String) {
// Load video from URL
Log.d("VideoPlayer", "Loading: $url")
}
}
Java Version
If you're using Java instead of Kotlin:
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.Network;
import android.net.NetworkCapabilities;
public class NetworkUtils {
public static String getNetworkType(Context context) {
ConnectivityManager connectivityManager =
(ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
if (connectivityManager == null) {
return "No connection";
}
Network network = connectivityManager.getActiveNetwork();
if (network == null) {
return "No connection";
}
NetworkCapabilities capabilities =
connectivityManager.getNetworkCapabilities(network);
if (capabilities == null) {
return "No connection";
}
if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
return "WiFi";
} else if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
return "Cellular";
} else if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET)) {
return "Ethernet";
} else {
return "Unknown";
}
}
public static boolean isConnectedToWiFi(Context context) {
return "WiFi".equals(getNetworkType(context));
}
public static boolean isConnectedToCellular(Context context) {
return "Cellular".equals(getNetworkType(context));
}
public static boolean hasInternet(Context context) {
ConnectivityManager connectivityManager =
(ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
if (connectivityManager == null) return false;
Network network = connectivityManager.getActiveNetwork();
if (network == null) return false;
NetworkCapabilities capabilities =
connectivityManager.getNetworkCapabilities(network);
return capabilities != null &&
capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) &&
capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED);
}
}
Common Use Cases
Download Large Files Only on WiFi
fun downloadLargeFile(context: Context, url: String) {
val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE)
as ConnectivityManager
val network = connectivityManager.activeNetwork
val capabilities = connectivityManager.getNetworkCapabilities(network)
val isWiFi = capabilities?.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) == true
if (isWiFi) {
// Start download
startDownload(url)
} else {
// Show dialog asking user if they want to download on cellular
showDataWarningDialog {
startDownload(url)
}
}
}
Sync Data Based on Connection Type
fun syncData(context: Context) {
val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE)
as ConnectivityManager
val network = connectivityManager.activeNetwork ?: return
val capabilities = connectivityManager.getNetworkCapabilities(network) ?: return
when {
capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> {
// Full sync with images and videos
syncAll()
}
capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> {
// Sync only essential data, no media
syncEssentialDataOnly()
}
else -> {
// No suitable connection
deferSync()
}
}
}
Show Network Status in UI
class NetworkStatusViewModel(application: Application) : AndroidViewModel(application) {
private val _networkStatus = MutableLiveData<String>()
val networkStatus: LiveData<String> = _networkStatus
private val connectivityManager =
application.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
private val networkCallback = object : ConnectivityManager.NetworkCallback() {
override fun onCapabilitiesChanged(
network: Network,
capabilities: NetworkCapabilities
) {
val status = when {
capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) ->
"Connected via WiFi"
capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) ->
"Connected via Cellular"
else -> "Connected"
}
_networkStatus.postValue(status)
}
override fun onLost(network: Network) {
_networkStatus.postValue("No connection")
}
}
init {
connectivityManager.registerDefaultNetworkCallback(networkCallback)
}
override fun onCleared() {
super.onCleared()
connectivityManager.unregisterNetworkCallback(networkCallback)
}
}
Testing Network Detection
During development, you can simulate different network conditions:
- Android Emulator: Use the Extended Controls (three dots) → Cellular → Network type
- Physical Device: Toggle WiFi and cellular in settings
- Network Speed: Use Android Studio's Network Profiler to throttle bandwidth
The key to good network detection in Android is using the modern NetworkCapabilities API, monitoring changes with callbacks, and adapting your app's behavior to save users' data and provide a better experience on different connection types.
Found an issue?