Linora
Linora

Reputation: 10988

Run code when Android app is closed/sent to background

I have an Android application which sends some data to a webservice. I need to send this data as soon as the application is closed or sent to background.. But how do I accomplish this?

My current solution is to run it on the OnPause() on my home activity, but I need this to run no matter which activity the user is on when closing the app.. Is this possible or do I have to add the OnPause method to all activities?

Upvotes: 38

Views: 87833

Answers (8)

Antonio Craveiro
Antonio Craveiro

Reputation: 121

If you are trying to submit/save data the user input, there are better ways to go about it than doing it when he tries to close the app. There are many ways to close an app. The user could even turn down the phone. So it's hard to take precautions against all of them.

I'd suggest you submit the data everytime the user stops writing, every any number of seconds or when he presses a button for example if your call to the webservice is too slow.

This way it's more safeproof and it's easier to implement.

Upvotes: 0

shubham chauhan
shubham chauhan

Reputation: 29

you can use onAppForegroundStateChange() method which call when app is open and closed.this method is only called when your app comes in foreground/background. onAppForegroundStateChange() method is better then you used onPause() method because onPause method is also called every time when you go to other activity.

you can use this method like that

public class MyApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        AppForegroundStateManager.getInstance().addListener(this);
    }

    @Override
    public void onAppForegroundStateChange(AppForegroundStateManager.AppForegroundState newState) {
        if (AppForegroundStateManager.AppForegroundState.IN_FOREGROUND == newState) {
            // App just entered the foreground. Do something here!
        } else {
            // App just entered the background. Do something here!
        }
    }
}

Upvotes: 1

Jorge Aguilar
Jorge Aguilar

Reputation: 3450

Maybe this can be helpfull, tell me if it worked for you. only when you return from background the value of activities would be 0 (zero) the rest of the times would be a number higher than 0(zero) when the onRestart() is executed.

public class FatherClass extends Activity {

private static int activities = 0;

public void onCreate(Bundle savedInstanceState, String clase) {
    super.onCreate(savedInstanceState);
}

protected void onRestart()
{
    super.onRestart();
    if(activities == 0){
        Log.i("APP","BACK FROM BACKGROUND");
    }
}

protected void onStop(){
    super.onStop();
    activities = activities - 1;
}

protected void onStart(){
    super.onStart();
    activities = activities + 1;
}

}

All of your classes must extend from this class for this to work.

Explanation: The onStart is executed one the activity is "visible" and the onStop when the activity is "not visible". So when your APP (it says APP not activity) goes to background all the activities are "not visible" so they execute the onStop method, so the idea behind this is to ADD ONE each time an activity es started, and SUBTRACT ONE each time an activity es hided, so if the value of the variable "activities" is zero that means that all the activities that where started in some point are now not visible, so when you APP returns from background and executes the onRestart method on the activity in "front" you can check whether comes from background or is just restarting an activity.

Upvotes: 3

Adil Soomro
Adil Soomro

Reputation: 37729

Edit

This answer only serves for one purpose, that is, running a code in onPause() for all activities. It doesn't let you run a code when your app is sent to background.

Original Answer

Make an Activity named YourBasicActivity and override its onPause() method and extend every Activity from YourBasicActivity

Upvotes: 23

peceps
peceps

Reputation: 17557

Check this solution first https://stackoverflow.com/a/5862048/1037294 before you decide to use the code below!


To check if your application is sent to background, you can call this code on onPause() or onStop() on every activity in your application:

 /**
   * Checks if the application is being sent in the background (i.e behind
   * another application's Activity).
   * 
   * @param context the context
   * @return <code>true</code> if another application will be above this one.
   */
  public static boolean isApplicationSentToBackground(final Context context) {
    ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
    List<RunningTaskInfo> tasks = am.getRunningTasks(1);
    if (!tasks.isEmpty()) {
      ComponentName topActivity = tasks.get(0).topActivity;
      if (!topActivity.getPackageName().equals(context.getPackageName())) {
        return true;
      }
    }

    return false;
  }

For this to work you should include this in your AndroidManifest.xml

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

Upvotes: 25

RPM
RPM

Reputation: 3436

This is the method that I used and it seems to work pretty well:

I have a top level Application class of my own that extends Application as such

public class MyApplication extends Application implements Application.ActivityLifecycleCallbacks {

You also need to register this Application object in your manifest file:

<application android:label="@string/app_name" android:icon="@drawable/ic_launcher" android:name=".MyApplication">

Notice how I also implement the ActivityLifeCycleCallbacks interface. This interface has the following methods:

public static interface ActivityLifecycleCallbacks {
    void onActivityCreated(android.app.Activity activity, android.os.Bundle bundle);

    void onActivityStarted(android.app.Activity activity);

    void onActivityResumed(android.app.Activity activity);

    void onActivityPaused(android.app.Activity activity);

    void onActivityStopped(android.app.Activity activity);

    void onActivitySaveInstanceState(android.app.Activity activity, android.os.Bundle bundle);

    void onActivityDestroyed(android.app.Activity activity);
}

You need to implement those methods and then register for these events in your applications onCreate() as follows

@Override
public void onCreate() {
    super.onCreate();
    registerActivityLifecycleCallbacks(this);
}

This will then call the callback (the MyApplication object) whenever an activity lifecycle method happens such as onCreate(), onPause etc. In your onActivityPaused() you can then check if the app was backgrounded or not by calling @peceps method : isApplicationSentToBackground(...)

This is what my code looks like then...

/**
 * Application.ActivityLifecycleCallbacks methods
 */
@Override
public void onActivityCreated(Activity activity, Bundle bundle) {

}

@Override
public void onActivityStarted(Activity activity) {
}

@Override
public void onActivityResumed(Activity activity) {
}

@Override
public void onActivityStopped(Activity activity) {
    try {
        boolean foreground = new ForegroundCheckTask().execute(getApplicationContext()).get();
        if(!foreground) {
            //App is in Background - do what you want
        }
    } catch (InterruptedException e) {
        e.printStackTrace();
    } catch (ExecutionException e) {
        e.printStackTrace();
    }
}

@Override
public void onActivityPaused(Activity activity) {
}

@Override
public void onActivitySaveInstanceState(Activity activity, Bundle bundle) {
}

@Override
public void onActivityDestroyed(Activity activity) {
}

Create a new class to go the Foreground checking (which is an async. task). See check android application is in foreground or not? for more.

class ForegroundCheckTask extends AsyncTask<Context, Void, Boolean> {
    @Override
    protected Boolean doInBackground(Context... params) {
        final Context context = params[0];
        return isAppOnForeground(context);
    }

    private boolean isAppOnForeground(Context context) {
        ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
        List<ActivityManager.RunningAppProcessInfo> appProcesses = activityManager.getRunningAppProcesses();
        if (appProcesses == null) {
            return false;
        }
        final String packageName = context.getPackageName();
        for (ActivityManager.RunningAppProcessInfo appProcess : appProcesses) {
            if (appProcess.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND && appProcess.processName.equals(packageName)) {
                return true;
            }
        }
        return false;
    }
}

Upvotes: 24

Barmaley
Barmaley

Reputation: 16363

I think you need to run your own thread which will check whether all running activities in background or destroyed.

MyBasicActivity extends Activity
{
    private static ArrayList<MyBasicActivity> activities=new ArrayList<MyBasicActivities);
    private boolean started;

    public void onCreate()
    {
       activities.add(this);
    } 

    public void onDestroy()
    {
       activities.remove(this);
    } 

    public void onStart()
    {
       this.started=true;
    }

    public void onPause()
    {
       this.started=false;
    }

    public boolean isStarted()
    {
       return started;
    }
}

MyThread implements Runnable
{
    private ArrayList<MyBasicActivity> activities;

    public MyThread(ArrayList<MyBasicActivity> activities) 
    {
        this.activities=activities;
    }

    void run()
    {
          while(!stopped)
          {
              boolean inBackground=true;
              for(MyBasicActivity activity:activities)
              {
                 if(activity.isStarted())
                 {
                      inBackground=false;
                      break;
                 }
              }
              if(inBackground)
                  //run your code here;
              sleep(10000); //10 secs
          }

    }
}

Upvotes: 0

Aman Aalam
Aman Aalam

Reputation: 11251

override the onStop() method of your Home activity and run the code there.

Upvotes: 0

Related Questions