Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Unverified Commit 0108098d authored by cketti's avatar cketti Committed by GitHub
Browse files

Merge pull request #5371 from k9mail/more_ConnectivityManager_fixes

Use ConnectivityManager.registerDefaultNetworkCallback() on API 24+
parents ec6e9761 198975dd
Loading
Loading
Loading
Loading
+4 −4
Original line number Diff line number Diff line
@@ -16,9 +16,9 @@ fun interface ConnectivityChangeListener {
}

internal fun ConnectivityManager(systemConnectivityManager: SystemConnectivityManager): ConnectivityManager {
    return if (Build.VERSION.SDK_INT >= 23) {
        ConnectivityManagerApi23(systemConnectivityManager)
    } else {
        ConnectivityManagerApi21(systemConnectivityManager)
    return when {
        Build.VERSION.SDK_INT >= 24 -> ConnectivityManagerApi24(systemConnectivityManager)
        Build.VERSION.SDK_INT >= 23 -> ConnectivityManagerApi23(systemConnectivityManager)
        else -> ConnectivityManagerApi21(systemConnectivityManager)
    }
}
+65 −0
Original line number Diff line number Diff line
package com.fsck.k9.network

import android.net.ConnectivityManager.NetworkCallback
import android.net.Network
import android.net.NetworkCapabilities
import android.os.Build
import androidx.annotation.RequiresApi
import timber.log.Timber
import android.net.ConnectivityManager as SystemConnectivityManager

@RequiresApi(Build.VERSION_CODES.N)
internal class ConnectivityManagerApi24(
    private val systemConnectivityManager: SystemConnectivityManager
) : ConnectivityManagerBase() {
    private var isRunning = false
    private var isNetworkAvailable: Boolean? = null

    private val networkCallback = object : NetworkCallback() {
        override fun onAvailable(network: Network) {
            Timber.v("Network available: $network")
            synchronized(this@ConnectivityManagerApi24) {
                isNetworkAvailable = true
                notifyListeners()
            }
        }

        override fun onLost(network: Network) {
            Timber.v("Network lost: $network")
            synchronized(this@ConnectivityManagerApi24) {
                isNetworkAvailable = false
                notifyListeners()
            }
        }
    }

    @Synchronized
    override fun start() {
        if (!isRunning) {
            isRunning = true

            systemConnectivityManager.registerDefaultNetworkCallback(networkCallback)
        }
    }

    @Synchronized
    override fun stop() {
        if (isRunning) {
            isRunning = false

            systemConnectivityManager.unregisterNetworkCallback(networkCallback)
        }
    }

    override fun isNetworkAvailable(): Boolean {
        return synchronized(this) { isNetworkAvailable } ?: isNetworkAvailableSynchronous()
    }

    // Sometimes this will return 'true' even though networkCallback has already received onLost().
    // That's why isNetworkAvailable() prefers the state derived from the callbacks over this method.
    private fun isNetworkAvailableSynchronous(): Boolean {
        val activeNetwork = systemConnectivityManager.activeNetwork ?: return false
        val networkCapabilities = systemConnectivityManager.getNetworkCapabilities(activeNetwork)
        return networkCapabilities?.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) == true
    }
}