170

From android doc here http://developer.android.com/reference/android/app/Activity.html, it said 'Activity comes into foreground' will call onPause(), and 'Activity is no longer visible' will call onStop().

Isn't 'Activity comes into foreground' same as 'Activity is no longer visible'? Can you please tell me what is the difference between them?

ElOjcar
  • 301
  • 2
  • 4
  • 12
michael
  • 106,540
  • 116
  • 246
  • 346
  • 20
    +1 for an excellent question. Also, a `paused` activity is **completely alive** (it maintains all state and member information and remains attached to the window manager). A `stopped` activity also retains all state and member information, but is no longer attached to the `window manager`. – ateiob Aug 08 '12 at 19:25

8 Answers8

116

No, if some activity comes into foreground, that doesn't necessarily mean that the other activity is completely invisible. Consider the following case:

Activity with the theme Theme.Dialog

Here we see both activities at the same time. The first activity with the fields is obscured by another activity, and the user can no longer interact with it. However, it is still visible with all the resulting consequences.

That leaves a question which activity is considered fully opaque and covering the whole screen and which isn't. This decision is based on the window containing the activity. If the window has a flag windowIsFloating or windowIsTranslucent, then it is considered that the activity doesn't make the underlying stuff invisible, otherwise it does and will cause onStop() to be called. The relevant code can be found in com.android.server.am.ActivityRecord:

fullscreen = ent != null && !ent.array.getBoolean(
        com.android.internal.R.styleable.Window_windowIsFloating, false)
        && !ent.array.getBoolean(
        com.android.internal.R.styleable.Window_windowIsTranslucent, false);
Malcolm
  • 41,014
  • 11
  • 68
  • 91
  • 10
    +1 for a great explanation, focusing on partial vs. total (in)visibility. It would be interesting to know the threshold percentage of the screen that makes Android decide between `onPause()` and `onStop()`. Is it 100%? If only one pixel from the previous activity is visible, is it still `onPause()`? – ateiob Aug 08 '12 at 19:13
  • 3
    @ateiob It is not said anywhere, but I think so. However, it is usually obvious because most activities which don't fill entire screen simply use one of the system provided styles for dialogs. – Malcolm Aug 09 '12 at 18:27
  • 1
    Strange, but in my application `onPause()` isn't called at all when a dialog is displayed. `onPause()` is only called when I press the **home** button. How is this possible? – ateiob Aug 10 '12 at 21:46
  • This should be the correct answer. By the way, the foreground thing is a dialog or activity? – Sam YC Sep 05 '12 at 02:34
  • 3
    @GMsoF An activity. That's the main point: not every dialog is actually a dialog. You can make an activity look like a dialog, so it is actually smaller than the entire screen. – Malcolm Sep 05 '12 at 03:11
  • Can we also say that during the activity's transition from visible state (After onResume() call) to the invisible state (Before onStop() call), onPause() will be called??? – Srinivasan N Mar 04 '15 at 18:40
  • @SrinivasanN `onResume()` call will always happen before `onStop()` if the activity has been resumed, that's how the lifecycle is defined. – Malcolm Mar 04 '15 at 20:01
  • What's when I "tab" out of the whole app by e.g. using the "tasks" button? I.e. technically I still see my App (or the current activity) but got other apps running in the stack. – Wecherowski May 05 '18 at 23:07
  • @Wecherowski You only see a snapshot of your application, this is not the actual application. – Malcolm May 06 '18 at 11:55
48

If you can still see any part of it (Activity coming to foreground either doesn't occupy the whole screen, or it is somewhat transparent), onPause() will be called. If you cannot see any part of it, onStop() will be called.

A dialog**, for example, may not cover the entire previous Activity, and this would be a time for onPause() to be called.

**I am not referring to an Android Dialog here, rather a conceptual idea of something that pops up and only obscures part of the user screen. This note was added to clarify based on a comment from @GMsoF below

nicholas.hauschild
  • 42,483
  • 9
  • 127
  • 120
  • 36
    NO. This is misleading. A dialog showed will not call onPause() because dialog use current activity's context, consider activity alive. – Sam YC Sep 05 '12 at 02:32
  • 6
    @GMsoF It sounds like when I said dialog, you thought I meant `Dialog`, as in the Android class. What I was getting at, though, is something that partly obscures the first `Activity` to illustrate the idea that all new `Activity`'s do not need to completely cover up the previous. – nicholas.hauschild Nov 12 '12 at 21:38
24

Practically, one should consider the difference between “onPause()” and “onPause() + onStop()”.

Whenever some new activity occurs and occupies some partial space of the Screen. So your previously running activity is still visible to some extent. In this Case, the previously running activity is not pushed to Back Stack. So, here only onPause() method is called.

On other hands, if some new Activity occurs and occupies the full screen so that your previously running activity is disappeared. In this Case, your previously running activity is moved to Back Stack. Here, onPause() + onStop() are called.

To Summaries-

onPause()- Screen is partially covered by other new activity. The Activity is not moved to Back Stack.

onPause() + onStop()- Screen is fully covered by other new activity. The Activity is moved to Back Stack.

Know more about- Back Stack.

Yash
  • 1,787
  • 1
  • 22
  • 23
11

Being in the foreground means that the activity has input focus. For instance, an activity can be visible but partially obscured by a dialog that has focus. In that case, onPause() will be called, but not onStop(). When the dialog goes away, the activity's onResume() method will be called (but not onStart()).

Ted Hopp
  • 232,168
  • 48
  • 399
  • 521
  • 5
    The dialog thing could be misleading. Let's a warning dialog is popped up from the main UI thread of this activity, onPause() will not be called in this case. Only if this dialog is popped up from other Activity or other App. – Sam003 Jul 13 '15 at 19:31
  • 1
    @Zhisheng - I agree with your comment. I was just paraphrasing [the Activites guide topic](http://developer.android.com/guide/components/activities.html#ImplementingLifecycleCallbacks): _"`onPause()` is called when the device goes to sleep or when a dialog appears"_. As [this thread](http://stackoverflow.com/a/7384782/535871) makes clear, though, a dialog doesn't _necessarily_ mean that an activity is paused (although it would be for, say, an [activity shown as a dialog](http://developer.android.com/guide/topics/ui/dialogs.html#ActivityAsDialog)). – Ted Hopp Jul 13 '15 at 21:28
2

whenever a new ACTIVITY starts the previous activity's onPause will be defiantly called in any circumstances.

actually there will be two circumstances:

1- a part of previous activity is visible or the new activity is transparent: only onPause will be called.

2- previous activity is completely covered by new activity: both onPause and onStop will be called

----Good to state some notes:

NOTE 1: if a dialog starts on top of an activity NONE of onPause or onStop will be called.

NOTE 2: if its an Activity whose theme is set to a dialog, the behavior will be just like a normal activity.

NOTE 3: apparently a system dialog like permission dialog since marshmallow will cause onPause.

Amir Ziarati
  • 14,248
  • 11
  • 47
  • 52
0

In concise words:

onStop() of previous activity life-cycle method is invoked when another activity is shown. When you have Dialogue on the top of activity, there onPause() is invoked.

Note: Activities are those components which fill your entire screen.

Note: Dialogues are not Activity as they don't completely fill the screen.

Saleh
  • 1,819
  • 1
  • 17
  • 44
Uddhav P. Gautam
  • 7,362
  • 3
  • 47
  • 64
0

I faced many problems with onPause and onStop methods and hence I will clear three scenarios that I came across-
1. When you click on the recent app button, no life cycle method is called but the onWindowFocusChanged(boolean hasFocus) is called with hasFocus value passed as false. In android version before 5 , onPause method used to get called, on pressing the recent app button.

2. When a pop up like activity appear over your activity, as mentioned by Malcolm, the onPause button is called. If new activity that takes up the whole screen is called, then onStop is called on previous activity. Android permission dialog also cause your activity to call onPause.

3. If screen times out on your activity, then onPause is called. After sometime if you will not open the screen then onStop will be called.

Also one important thing mentioned by the ateiob that completes the answer

A paused activity is completely alive (it maintains all state and member information and remains attached to the window manager). A stopped activity also retains all state and member information, but is no longer attached to the window manager


Hope it helps.

royatirek
  • 2,437
  • 2
  • 20
  • 34
-5

Yeap, I try to understand and I can explain this below:

There are 2 activities: ActivityA & ActivityB

public class ActivityA extends Activity implements OnClickListener {

// button
private Button mBtnChangeActivity;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_a);
    initialize();
    setEvent();
}

private void initialize() {
    Log.i("Activity A", "Initialize()");
    mBtnChangeActivity = (Button) findViewById(R.id.btn_change_activity);
}

private void setEvent() {
    Log.i("Activity A", "setEvent()");
    mBtnChangeActivity.setOnClickListener(this);
}

@Override
protected void onStart() {
    super.onStart();
    Log.i("Activity A", "onStart");
}

@Override
protected void onResume() {
    super.onResume();
    Log.i("Activity A", "onResume");
}

@Override
protected void onPause() {
    super.onPause();
    Log.i("Activity A", "onPause");
}

@Override
protected void onStop() {
    super.onStop();
    Log.i("Activity A", "onStop");
}

@Override
protected void onDestroy() {
    super.onDestroy();
    Log.i("Activity A", "onDestroy");
}

@Override
public void onClick(View v) {
    switch (v.getId()) {
    case R.id.btn_change_activity:
        Intent activityB = new Intent(this, ActivityB.class);
        startActivity(activityB);
        break;
    default:
        break;
    }
}

Here is activity B. Follow my comment in code

public class ActivityB extends Activity implements OnClickListener {

// button
private Button mBtnChangeActivity;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_a);
    initialize();
    setEvent();
    // if call finish() here, activityA will don't stop, just pause
    // Activity A will call onStop() when Activity B call onStart() method
    finish();
}

private void initialize() {
    Log.i("Activity B", "Initialize()");
    mBtnChangeActivity = (Button) findViewById(R.id.btn_change_activity);
}

private void setEvent() {
    Log.i("Activity B", "setEvent()");
    mBtnChangeActivity.setOnClickListener(this);
}

@Override
protected void onStart() {
    super.onStart();
    Log.i("Activity B", "onStart");
}

@Override
protected void onResume() {
    super.onResume();
    Log.i("Activity B", "onResume");
}


@Override
public void onClick(View v) {
    switch (v.getId()) {
    case R.id.btn_change_activity:
        finish();
        break;
    default:
        break;
    }
}
}

I hope this is clearly