override fun setR2SettingData(cmd: String, status: String) {
val requestbuilder = NetworkRequest.Builder()
requestbuilder.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
connectivityManager.requestNetwork(
requestbuilder.build(),
object : ConnectivityManager.NetworkCallback() {
override fun onAvailable(network: Network) {
val builder1 = OkHttpClient.Builder()
builder1.socketFactory(network.socketFactory)
val apiService =
RetrofitInstance.getApiServiceXMLForR2(
Constants.BASE_URL_CAMERA_R2,
builder1
)
trackDisposable(
apiService.requestCameraR2URLForSettingResponse(cmd, status)
.subscribeOn(schedulerProvider.io())
.observeOn(schedulerProvider.ui())
.subscribe()
)
}
})
}
This code i am using network call when we call API some time I am recieving the following error: android.net.ConnectivityManager$TooManyRequestsException
Process: com.rovedashcam.android, PID: 25285
android.net.ConnectivityManager$TooManyRequestsException
at android.net.ConnectivityManager.convertServiceException(ConnectivityManager.java:3378)
at android.net.ConnectivityManager.sendRequestForNetwork(ConnectivityManager.java:3564)
at android.net.ConnectivityManager.requestNetwork(ConnectivityManager.java:3585)
at android.net.ConnectivityManager.requestNetwork(ConnectivityManager.java:3661)
at android.net.ConnectivityManager.requestNetwork(ConnectivityManager.java:3622)
at
connectivityManager.requestNetwork
can anyone tell me why I am getting this error?
I have tried resolving this by integration connectivityManager with fragment lifecycle methods
Here is my implementation.
Create Class properties
private var connectivityManager:ConnectivityManager? = null
private val connectionCallback = object : ConnectivityManager.NetworkCallback() {
override fun onAvailable(network: Network) {//perform your stuff}
override fun onLost(network: Network) {//perform your stuff}
}
Initialise and register ConnectivityManager in onCreateView()
connectivityManager = requireContext().getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
connectivityManager?.registerDefaultNetworkCallback(connectionCallback)
unregisterNetworkCallback in onPause()/onStop()/onDestroy() based on your requirement
connectivityManager?.unregisterNetworkCallback(connectionCallback)
Related
I'm trying to connect to wifi from my android application, using the wifi Network request API.
Here is the code:
val builder =
WifiNetworkSpecifier.Builder()
.setBssid(MacAddress.fromString(item.bssid))
.setWpa2Passphrase("somePassword")
if (item.ssid.isNotEmpty()) {
builder.setSsid(item.ssid)
}
val networkRequest = NetworkRequest.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
.setNetworkSpecifier(builder.build())
.build()
Next I do that
cm.requestNetwork(
networkRequest,
WifiConnectionCallBack(ConnectivityManager)
)
WifiConnectionCallBack is my class, what extends NetworkCallback
class WifiConnectionCallBack(
private val connectionWatcher : ConnectionWatcher,
private val bssid : String,
private val connManager: ConnectivityManager,
private val onConnection : (Boolean, Network) -> Unit
) : NetworkCallback() {
override fun onAvailable(network: Network) {
super.onAvailable(network)
val result = connManager.bindProcessToNetwork(network)
onConnection.invoke(result, network)
connectionWatcher.onChangeState(ConnectionState.WifiConnected(bssid, network))
}
override fun onUnavailable() {
super.onUnavailable()
connectionWatcher.onChangeState(ConnectionState.UnAvailable)
}
override fun onLinkPropertiesChanged(network: Network, linkProperties: LinkProperties) {
super.onLinkPropertiesChanged(network, linkProperties)
connectionWatcher.onChangeState(
ConnectionState.LinkPropertiesChanged(
bssid,
network,
linkProperties
)
)
}
override fun onLost(network: Network) {
super.onLost(network)
connectionWatcher.onChangeState(ConnectionState.Lost(network))
}
It works fine... But, when I HAVE NO access to the internet. Any suggestions, what can be wrong here?
Thank you for reading this!
I tried methods from this topic Connect to Wifi in Android Q programmatically
But it doesnt work
Hey I am new in jetpack compose. I am checking in internet is available or not and consume through live data. Now I started learning jetpack compose so I want to use Flow, So any guys help me to convert this LiveData to flow and use in jetpack compose.
NetworkConnection.kt
import android.app.Application
import android.content.Context
import android.net.ConnectivityManager
import android.net.Network
import android.net.NetworkRequest
import androidx.lifecycle.LiveData
class NetworkConnection(private val connectivityManager: ConnectivityManager) : LiveData<Boolean>() {
constructor(application: Application) : this(application.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager)
private val networkCallback = object : ConnectivityManager.NetworkCallback() {
override fun onAvailable(network: Network) {
super.onAvailable(network)
postValue(true)
}
override fun onLost(network: Network) {
super.onLost(network)
postValue(false)
}
}
override fun onActive() {
super.onActive()
val builder = NetworkRequest.Builder()
connectivityManager.registerNetworkCallback(builder.build(), networkCallback)
}
override fun onInactive() {
super.onInactive()
connectivityManager.unregisterNetworkCallback(networkCallback)
}
}
Can someone help me which way of doing recommendations for kotlin flow in jetpack compose.
MainActivity.kt
class MainActivity : ComponentActivity() {
private lateinit var checkNetworkConnection: NetworkConnection
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
checkNetworkConnection = NetworkConnection(application)
setContent {
SportsResultTheme {
SetupView()
}
}
}
}
I am confused also how can I use flow in my compose in recommendation way. Thanks
NetworkConnection.kt ->
class NetworkConnection(private val connectivityManager: ConnectivityManager) {
init {
registerNetworkCallback()
}
constructor(application: Application) : this(application.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager)
val stateFlow: StateFlow<State>
get() = _stateFlow
private val _stateFlow: MutableStateFlow<State> = MutableStateFlow(State.Init)
private val networkCallback = object : ConnectivityManager.NetworkCallback() {
override fun onAvailable(network: Network) {
super.onAvailable(network)
_stateFlow.value = State.Available
}
override fun onLost(network: Network) {
super.onLost(network)
_stateFlow.value = State.Gone
}
}
fun registerNetworkCallback(){
val builder = NetworkRequest.Builder()
connectivityManager.registerNetworkCallback(builder.build(), networkCallback)
}
fun unregisterNetworkCallback() {
connectivityManager.unregisterNetworkCallback(networkCallback)
}
sealed interface State {
object Init : State
object Available : State
object Gone : State
}
}
MainActivity.kt
class MainActivity : ComponentActivity() {
private lateinit var checkNetworkConnection: NetworkConnection
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
checkNetworkConnection = NetworkConnection(application)
setContent {
SportsResultTheme {
checkNetworkConnection.stateFlow.collectAsState()
SetupView()
}
}
}
}
Jetpack compose has function (LiveData.observeAsState()) available to convert LiveData to State that you can use in your Compose UI. You don't have to use Flow if you already have a LiveData in your code base. Pass you live data into the composable and convert it to a state. You can also convert live data to state before you call the SetupView composable and just pass the state itself.
#Composable
fun SetupView(networkConnection : NetworkConnection) {
val isConnected = networkConnection.observeAsState()
if(isConnected) {
// update for connected state
} else {
// handle offline state
}
}
In my application I want use RxJava and I want check internet connection.
I write below code, but just check first time when application started!
I want check every time and when internet connection lost or available show user!
My class codes :
class InternetConnection {
#Suppress("DEPRECATION")
private fun isConnectedOld(context: Context): Boolean {
val connManager = context.getSystemService(CONNECTIVITY_SERVICE) as ConnectivityManager
val networkInfo = connManager.activeNetworkInfo
return networkInfo!!.isConnected
}
#RequiresApi(Build.VERSION_CODES.M)
private fun isConnectedNewApi(context: Context): Boolean {
val cm = context.getSystemService(CONNECTIVITY_SERVICE) as ConnectivityManager
val capabilities = cm.getNetworkCapabilities(cm.activeNetwork)
return capabilities?.hasCapability(NET_CAPABILITY_INTERNET) == true
}
fun isConnected(context: Context): Observable<Boolean> {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
Observable.just(isConnectedNewApi(context))
} else {
Observable.just(isConnectedOld(context))
}
}
}
Activity codes :
class TestCheckNetworkActivity : AppCompatActivity() {
private lateinit var binding: ActivityTestCheckNetworkBinding
private val internet by lazy { InternetConnection() }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityTestCheckNetworkBinding.inflate(layoutInflater)
setContentView(binding.root)
internet.isConnected(this)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe {
binding.checkNetTxt.text = it.toString()
}
}
}
How can I change my codes for check internet for every time, not just when application created ?
my current android application has a requirement to inform the user when internet access has been lost during a user session
i employ the following callback listener:-
#OptIn(DelicateCoroutinesApi::class)
class ConnectivityListener #Inject constructor() : CoroutineScope by GlobalScope, ConnectivityManager.NetworkCallback() {
private var backgroundStateJob: Job? = null
private val internalSharedWorkState = MutableSharedFlow<BackgroundState>(replay = 1, extraBufferCapacity = 7, onBufferOverflow = BufferOverflow.DROP_OLDEST)
private val sharedWorkScheduleState: SharedFlow<BackgroundState> = internalSharedWorkState
override fun onBlockedStatusChanged(network: Network, blocked: Boolean) {
Timber.e( "onBlockedStatusChanged() called with: network = $network, blocked = $blocked")
}
override fun onLosing(network: Network, maxMsToLive: Int) {
Timber.e( "onLosing() called with: network = $network, maxMsToLive = $maxMsToLive")
}
override fun onCapabilitiesChanged(network: Network, networkCapabilities: NetworkCapabilities) {
Timber.e( "onCapabilitiesChanged() called with: network = $network, networkCapabilities = $networkCapabilities")
}
override fun onLinkPropertiesChanged(network: Network, linkProperties: LinkProperties) {
Timber.e( "onLinkPropertiesChanged() called with: network = $network, linkProperties = $linkProperties")
}
override fun onUnavailable() {
Timber.e( "onUnavailable() called")
}
override fun onAvailable(network: Network) {
Timber.e("onAvailable() called with: network = $network")
backgroundStateJob?.cancel()
backgroundStateJob = launch(Dispatchers.IO) {
internalSharedWorkState.emit(BackgroundState.Connected())
}
}
override fun onLost(network: Network) {
Timber.e("onLost() called with: network = $network")
backgroundStateJob?.cancel()
backgroundStateJob = launch(Dispatchers.IO) {
internalSharedWorkState.emit(BackgroundState.Disconnected())
}
}
fun stateFlow(): SharedFlow<BackgroundState> {
return sharedWorkScheduleState
}
}
this listener is employed within my base activity as follow:-
private val networkRequest = NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.addCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)
.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
.addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET)
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
.build()
...
override fun onResume() {
Timber.e("onResume() called")
super.onResume()
val connectivityManager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
connectivityManager.registerNetworkCallback(networkRequest, connectivityListener)
}
override fun onPause() {
Timber.e("onPause() called")
super.onPause()
val connectivityManager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
connectivityManager.unregisterNetworkCallback(connectivityListener)
}
the listener works as expected while the application is in the foreground and reliable informs the user on the current network status whenever internet access is lost.
the listener also works fine when i exit the application, it goes into the background and is subsequently resumed. the listener successfully reports i have internet access.
however the listener does not work as required when i put the application into the background, enable airplane mode then resume the application.
it does not detect that there is no internet access, even though it does detect when internet access is available when the app is resumed from the background and airplane mode is not enabled.
what am i doing wrong?
how can i detect the current network status when resuming my application from the background?
i managed to achieve the desired result by adding a second
network callback as follows with a timeout by employing requestNetwork()
override fun onResume() {
super.onResume()
val connectivityManager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
connectivityManager.registerNetworkCallback(networkRequest, connectivityListenerMonitor)
connectivityManager.requestNetwork(networkRequest, connectivityListener, 1000)
}
override fun onPause() {
super.onPause()
val connectivityManager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
connectivityManager.unregisterNetworkCallback(connectivityListener)
connectivityManager.unregisterNetworkCallback(connectivityListenerMonitor)
}
now when my application is in the background and i enable airplane mode
then bring my application to the foreground my users are notified that there is no internet connection.
I'm working on an Android application which monitors the device's network usage in the background. As far as I know, a couple years ago the go-to approach would have been to register a BroadcastReceiver which catches every CONNECTIVITY_CHANGE event, but it seems like it was deprecated in Android 7. I can see a class named JobScheduler has been introduced since as a sort of replacement, but I'm not sure that might suit this specific use case.
Use ConnectivityManager class to listen about connectivity change.
From official doc
Class that answers queries about the state of network connectivity. It
also notifies applications when network connectivity changes.
Use registerNetworkCallback to receive notifications about all networks which satisfy the given NetworkRequest
Here is sample code in Kotlin:
enum class NetworkResult {
CONNECTED,
DISCONNECTED,
DISCONNECTING
}
class NetworkCallback : ConnectivityManager.NetworkCallback(){
val result = MutableLiveData<NetworkResult>()
override fun onCapabilitiesChanged(network: Network, networkCapabilities: NetworkCapabilities) {
super.onCapabilitiesChanged(network, networkCapabilities)
}
override fun onLost(network: Network) {
Timber.i("onLost networkL $network")
result.postValue(NetworkResult.DISCONNECTED)
}
override fun onLosing(network: Network, maxMsToLive: Int) {
Timber.i("onLosing: network: $network maxMsToLive: $maxMsToLive")
result.postValue(NetworkResult.DISCONNECTING)
}
override fun onAvailable(network: Network) {
Timber.i("onAvailable: network: $network")
result.postValue(NetworkResult.CONNECTED)
}
}
class ConnectivityFactory {
fun internetRequest() : NetworkRequest{
return NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
.build()
}
}
class NetworkConnectionManager(val context: Context){
private val factory : ConnectivityFactory = ConnectivityFactory()
private val callback : NetworkCallback = NetworkCallback()
private val connectivityManager = context.getSystemService(CONNECTIVITY_SERVICE) as ConnectivityManager
val result : LiveData<NetworkResult> get() = callback.result
fun registerCallback(){
val request = factory.internetRequest()
connectivityManager.registerNetworkCallback(request, callback)
}
fun unregisterCallback(){
connectivityManager.unregisterNetworkCallback(callback)
}
}
Usage:
val networkManager : NetworkConnectionManager by lazy { NetworkConnectionManager(this) }
// observer state
networkManager.result.observe(this, Observer {
Timber.i(it.name)
})
// register
networkManager.registerCallback()()
// unregister
networkManager.unregisterCallback()