Prateek Ratnaker
Prateek Ratnaker

Reputation: 817

Android Detect Network change when Internet is available even when app is closed

I have made a broadcast receiver that Toasts a message on screen when connected to internet. My Code is ->

MainActivity.java

import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Build;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        int PERMISSION_ALL = 1;
        String[] PERMISSIONS = {Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.INTERNET, Manifest.permission.WRITE_SETTINGS, Manifest.permission.ACCESS_NETWORK_STATE};

        if (!hasPermissions(this, PERMISSIONS)) {
            ActivityCompat.requestPermissions(this, PERMISSIONS, PERMISSION_ALL);
        }
    }

    public static boolean hasPermissions(Context context, String... permissions) {
        if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && context != null && permissions != null) {
            for (String permission : permissions) {
                if (ActivityCompat.checkSelfPermission(context, permission) != PackageManager.PERMISSION_GRANTED) {
                    return false;
                }
            }
        }
        return true;
    }

    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);

    }
}

Manifest

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.INTERNET" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <receiver
            android:name=".NetworkChangeReceiver"
            android:exported="true">
            <intent-filter>
                <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
                <action android:name="android.net.wifi.WIFI_STATE_CHANGED" />
            </intent-filter>
        </receiver>
    </application>

Broadcast Receiver

public class NetworkChangeReceiver extends BroadcastReceiver {

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

        final ConnectivityManager connMgr = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);

        final NetworkInfo activeNetwork = connMgr.getActiveNetworkInfo();
        if(activeNetwork != null && activeNetwork.isConnected())
        {
            Toast.makeText(context, "Connected", Toast.LENGTH_SHORT).show();
        }
       /* if (activeNetwork.getType() == ConnectivityManager.TYPE_WIFI || activeNetwork.getType() == ConnectivityManager.TYPE_MOBILE) {


            Toast.makeText(context, "Network Available", Toast.LENGTH_SHORT).show();
        }*/


    }
}

However,it works only when application is open.When Application is closed,it doesn't work,how to make this work even when application is closed?

Upvotes: 1

Views: 3218

Answers (2)

Khaledonian
Khaledonian

Reputation: 2203

What you're looking for is Services. You're most recommended to read the documention by Android Studio here.

Services will allow a very specific part of your application to survive at all times. Even when the user restart their devices and never run your application again. There is a lot to perceive about Services, but at the moment I believe a snippet will be most helpful to you, here is a little code,

First in your manifest

    <!--notification-->
    <service android:name="services.HelloService"
        android:exported="false"
        android:description="My notification Center"/>
    <!--notification-->

Second

Create a class called HelloService

and paste the following code inside with the proper imports*

public class HelloService extends Service {
private Looper mServiceLooper;
private ServiceHandler mServiceHandler;

// Handler that receives messages from the thread
 private final class ServiceHandler extends Handler {
  public ServiceHandler(Looper looper) {
      super(looper);
  }
  @Override
  public void handleMessage(Message msg) {
      // Normally we would do some work here, like download a file.
      // For our sample, we just sleep for 5 seconds.
      try {
          Thread.sleep(5000);
      } catch (InterruptedException e) {
          // Restore interrupt status.
          Thread.currentThread().interrupt();
      }
      // Stop the service using the startId, so that we don't stop
      // the service in the middle of handling another job
      stopSelf(msg.arg1);
  }
}

@Override
public void onCreate() {
// Start up the thread running the service.  Note that we create a
// separate thread because the service normally runs in the process's
// main thread, which we don't want to block.  We also make it
// background priority so CPU-intensive work will not disrupt our UI.
HandlerThread thread = new HandlerThread("ServiceStartArguments",
        Process.THREAD_PRIORITY_BACKGROUND);
thread.start();

// Get the HandlerThread's Looper and use it for our Handler
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
  }

  @Override
   public int onStartCommand(Intent intent, int flags, int startId) {
   Toast.makeText(this, "servicestarting",Toast.LENGTH_SHORT).show();


  Message msg = mServiceHandler.obtainMessage();
  msg.arg1 = startId;
  mServiceHandler.sendMessage(msg);

  // If we get killed, after returning from here, restart
  return START_STICKY;
      }

@Override
public IBinder onBind(Intent intent) {
   // We don't provide binding, so return null
   return null;
          }


 @Override
 public void onDestroy() {
   Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show();
 }
}

Inside the 'handleMessage Method' add your bit of code, for example ;

  @Override
public void handleMessage(Message msg) {

 //... your bit of code goes here 

  try {
      Thread.sleep(5000);
  } catch (InterruptedException e) {
      // Restore interrupt status.
      Thread.currentThread().interrupt();
  }


    //stopSelf(msg.arg1);
}

Lastly, to activate the service class, in your function to trigger the service, first import the HelloService.class, then create an Intent and fire up!

 Intent intent = new Intent(this, HelloService.class);
 startActivity(intent)

Upvotes: 0

Deep Patel
Deep Patel

Reputation: 2644

First of all declare your receiver to Menifest file,

    <receiver android:name=".services.ConnectivityBroadcastReceiver">
    <intent-filter>
    <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
    </intent-filter>
    </receiver>

ConnectivityBroadcastReceiver.java

public class ConnectivityBroadcastReceiver extends BroadcastReceiver {
    static final String CONNECTIVITY_CHANGE_ACTION = "android.net.conn.CONNECTIVITY_CHANGE";

    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        if (CONNECTIVITY_CHANGE_ACTION.equals(action)) {
            //check internet connection
            if (!ConnectionHelper.isConnectedOrConnecting(context)) {
                if (context != null) {
                    boolean show = false;
                    if (ConnectionHelper.lastNoConnectionTs == -1) {//first time
                        show = true;
                        ConnectionHelper.lastNoConnectionTs = System.currentTimeMillis();
                    } else {
                        if (System.currentTimeMillis() - ConnectionHelper.lastNoConnectionTs > 1000) {
                            show = true;
                            ConnectionHelper.lastNoConnectionTs = System.currentTimeMillis();
                        }
                    }

                    if (show && ConnectionHelper.isOnline) {
                        ConnectionHelper.isOnline = false;
                        context.stopService(new Intent(context, SyncData.class));
                        Log.e("Connection lost.");
                    }
                }
            } else {
                Log.e("Connected.");
                // Perform your actions here
                ConnectionHelper.isOnline = true;
            }
        }
    }
}

ConnectionHelper.java

public class ConnectionHelper {

    public static long lastNoConnectionTs = -1;
    public static boolean isOnline = true;

    public static boolean isConnected(Context context) {
        ConnectivityManager cm =(ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo activeNetwork = cm.getActiveNetworkInfo();

        return activeNetwork != null && activeNetwork.isConnected();
    }

    public static boolean isConnectedOrConnecting(Context context) {
        ConnectivityManager cm =(ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo activeNetwork = cm.getActiveNetworkInfo();

        return activeNetwork != null &&
                activeNetwork.isConnectedOrConnecting();
    }

}

Upvotes: 2

Related Questions