10

I want to create an Android service, which notifies the main activity whenever disconnects and when internet reconnects again. I have following function for checking internet connectivity:.

private boolean haveInternet(){
        NetworkInfo info=(NetworkInfo)((ConnectivityManager)this.getSystemService(Context.CONNECTIVITY_SERVICE)).getActiveNetworkInfo();

        if(info==null || !info.isConnected()){
            return false;
        }
        if(info.isRoaming()){
            //here is the roaming option you can change it if you want to disable internet while roaming, just return false
            return true;
        }
        return true;
    }

But I want to know, how to use it in a service.

Adnan
  • 2,986
  • 7
  • 43
  • 63

2 Answers2

28

Services are designed for long backgroud running task. You should use a BroadcastReceiver:

This is a sample method I use to monitor the network state into my main Activity:

private void installListener() {

        if (broadcastReceiver == null) {

            broadcastReceiver = new BroadcastReceiver() {

                @Override
                public void onReceive(Context context, Intent intent) {

                    Bundle extras = intent.getExtras();

                    NetworkInfo info = (NetworkInfo) extras
                            .getParcelable("networkInfo");

                    State state = info.getState();
                    Log.d("InternalBroadcastReceiver", info.toString() + " "
                            + state.toString());

                    if (state == State.CONNECTED) {

                        onNetworkUp();

                    } else {

                        onNetworkDown();

                    }

                }
            };

            final IntentFilter intentFilter = new IntentFilter();
            intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
            registerReceiver(broadcastReceiver, intentFilter);
        }
    }

Remember to call unregisterReceiver when the onDestroy event occurs

Hope this help.

Francesco Laurita
  • 23,434
  • 8
  • 55
  • 63
  • Brilliant answer! I love how you created a method, and added the onNetworkUp and Down callbacks – Bhargav Jul 18 '16 at 06:09
  • 2
    Im using this and works great but I would like to have this in a class or a listener. so I can use it in more then one activity but I want to avoid code repetition. What would be the proper way to do so ? – Nelson Silva Jan 27 '18 at 18:59
  • hello, some help please ? – Nelson Silva Jan 29 '18 at 20:30
  • I added an answer with a class, as suggested by @NelsonSilva. I believe it's a starting point and we can continue to improve it. – JCarlosR Jul 25 '20 at 03:19
0

This is a Kotlin version, following Francesco Laurita's solution:

private val broadcastReceiver by lazy {
    NetworkListener.create({
        btnOnlineVideos.visibility = View.VISIBLE
    }, {
        btnOnlineVideos.visibility = View.GONE
    })
}

override fun onResume() {
    super.onResume()

    NetworkListener.register(this, broadcastReceiver)
}

override fun onPause() {
    super.onPause()

    NetworkListener.unregister(this, broadcastReceiver)
}

For this to work I simply override the onResume and onPause methods, to register and unregister the BroadcastReceiver.

How does this work?

I created the following class that helps to initialize, register and unregister the BroadcastReceiver. That way there is no need to repeate most of the boilerplate code.

package com.programacionymas.app.services

import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.net.ConnectivityManager
import android.net.NetworkInfo
import android.os.Parcelable
import android.util.Log

object NetworkListener {

    fun create(onNetworkUp: () -> Unit, onNetworkDown: () -> Unit): BroadcastReceiver {
        return object : BroadcastReceiver() {
            override fun onReceive(context: Context, intent: Intent) {

                intent.extras?.getParcelable<Parcelable>("networkInfo")?.let {
                    val info = it as NetworkInfo
                    val state: NetworkInfo.State = info.state

                    Log.d("BroadcastReceiver", "$info $state")
                    if (state === NetworkInfo.State.CONNECTED) {
                        onNetworkUp()
                    } else {
                        onNetworkDown()
                    }
                }

            }
        }
    }

    fun register(context: Context, broadcastReceiver: BroadcastReceiver) {
        val intentFilter = IntentFilter()
        intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION)
        context.registerReceiver(broadcastReceiver, intentFilter)
    }

    fun unregister(context: Context, broadcastReceiver: BroadcastReceiver) {
        context.unregisterReceiver(broadcastReceiver)
    }

}

In case you need to execute sentences only for one of the states, you can pass a null anonymous function too:

private val broadcastReceiver by lazy {
    NetworkListener.create(null, {
        toast(getString(R.string.check_your_internet))
        finish()
    })
}

And declare the parameters as optionals in the create method:

fun create(onNetworkUp: (()->Unit)?, onNetworkDown: (()->Unit)?): BroadcastReceiver {/* ... */}

As well as invoking the functions only if they were sent as arguments:

if (state === NetworkInfo.State.CONNECTED) {
    onNetworkUp?.invoke()
} else {
    onNetworkDown?.invoke()
}
JCarlosR
  • 1,598
  • 3
  • 19
  • 32
  • `NetworkInfo` is deprecated on Android 10+. You should update the implementation to use [`ConnectivityManager.NetworkCallback`](https://developer.android.com/reference/kotlin/android/net/ConnectivityManager.NetworkCallback) – Panos Gr Jan 28 '21 at 15:21