Reputation: 3249
I know you can write code through which you can determine whether the device is connected to a network.
But in my app what I want to do is get a notification if the device changes its state from 'network' to 'no network'. This would happen, for example, when the user travels into a tunnel and loses signal, etc. Or when on WiFi, the user goes out of range of the access point and no longer has access to the internet.
Does the Android API provide something where you can register a listener so that you get notified every time there is a change in network state?
I found this code and tried to use it, but it does not do anything. I don't get any notifications when the network state changes.
public class ConnectivityManager extends PhoneStateListener{
Activity activity;
public ConnectivityManager(Activity a){
TelephonyManager telephonyManager = (TelephonyManager)a.getSystemService(Context.TELEPHONY_SERVICE);
telephonyManager.listen(this, PhoneStateListener.LISTEN_DATA_CONNECTION_STATE);
activity = a;
}
@Override
public void onDataConnectionStateChanged(int state) {
super.onDataConnectionStateChanged(state);
switch (state) {
case TelephonyManager.DATA_DISCONNECTED:
new AlertDialog.Builder(activity).
setCancelable(false).
setTitle("Connection Manager").
setMessage("There is no network connection. Please connect to internet and start again.").
setNeutralButton("Ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
System.exit(0);
}
}).create();
break;
case TelephonyManager.DATA_CONNECTED:
break;
}
}
}
Also, I have added the appropriate permissions in AndroidManifest.xml:
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
<uses-permission android:name="android.permission.READ_PHONE_STATE"></uses-permission>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"></uses-permission>
Upvotes: 31
Views: 35933
Reputation: 5422
You can easily use Merlin and his beard. Here you can also get a type of connection: mobile or wifi.
implementation 'com.novoda:merlin:1.2.0'
private MerlinsBeard merlinsBeard;
private NetworkChecker(Context context){
Merlin merlin = new Merlin.Builder()
.withConnectableCallbacks()
.withDisconnectableCallbacks()
.build(context);
merlinsBeard = new MerlinsBeard.Builder().build(context);
merlin.registerConnectable(() -> {
Timber.d("Connection enabled");
});
merlin.registerDisconnectable(() -> {
Timber.d("Connection disabled");
});
merlin.bind();
}
public boolean getConnected(){
return merlinsBeard.isConnected();
}
Upvotes: 0
Reputation: 671
If you are trying to do that in Kotlin. Use this
val isInternetWorking: Boolean by lazy {
var success = false
try {
val url = URL("https://google.com")
val connection = url.openConnection() as HttpURLConnection
connection.connectTimeout = 10000
connection.connect()
success = connection.responseCode === 200
} catch (e: IOException) {
e.printStackTrace()
}
return@lazy success
}
Do this in a thread.
Upvotes: 0
Reputation: 235
I implemented this feature by polling ConnectivityManager.
_connectivityManager = (ConnectivityManager)getSystemService(CONNECTIVITY_SERVICE);
Once we have a connectivity manager just poll it every now and then to see if you are still connected
private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
final Runnable networkStatusChecker = new Runnable() {
public void run() {
NetworkInfo activeNetwork = _connectivityManager.getActiveNetworkInfo();
boolean isConnected = activeNetwork != null && activeNetwork.isConnectedOrConnecting();
if(!isConnected) {
System.out.println("disconnected from network");
networkCheckerHandle.cancel(true);
}
}
};
final ScheduledFuture networkCheckerHandle = scheduler.scheduleAtFixedRate(networkStatusChecker, 10, 10, SECONDS);
Upvotes: 1
Reputation: 13218
The accepted answer didn't work for me (my tablet was connected to WiFi - no 3G). The following code worked for me:
public class ConnectivityChangeReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
System.out.println("*** Action: " + intent.getAction());
if(intent.getAction().equalsIgnoreCase("android.net.conn.CONNECTIVITY_CHANGE")) {
Toast.makeText(context, "Connection changed", Toast.LENGTH_SHORT).show();
}
}
}
and the change to AndroidManifest.xml
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<receiver android:name=".custom.ConnectivityChangeReceiver">
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
</intent-filter>
</receiver>
Upvotes: 9
Reputation: 192
myTelephonyManager=(TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
callStateListener = new PhoneStateListener(){
public void onDataConnectionStateChanged(int state){
switch(state){
case TelephonyManager.DATA_DISCONNECTED:
Log.i("State: ", "Offline");
// String stateString = "Offline";
// Toast.makeText(getApplicationContext(),
// stateString, Toast.LENGTH_LONG).show();
break;
case TelephonyManager.DATA_SUSPENDED:
Log.i("State: ", "IDLE");
// stateString = "Idle";
// Toast.makeText(getApplicationContext(),
// stateString, Toast.LENGTH_LONG).show();
break;
}
}
};
myTelephonyManager.listen(callStateListener,
PhoneStateListener.LISTEN_DATA_CONNECTION_STATE);
Upvotes: 16
Reputation: 22342
You might want to consider using a BroadcastReceiver
for ConnectivityManager.CONNECTIVITY_ACTION
instead. From the docs:
A change in network connectivity has occurred. A connection has either been established or lost. The NetworkInfo for the affected network is sent as an extra; it should be consulted to see what kind of connectivity event occurred.
This receiver works for both WiFi and cellular data connectivity, unlike PhoneStateListener.LISTEN_DATA_CONNECTION_STATE
, which will only notify you for changes in cellular networks.
Upvotes: 25