Distinguish between pushing "home" button and opening another Activity
Asked Answered
S

5

7

I have three activity: - SplashActivity - MainActivity - PlayerActivity

Of course the app starts with SplashActivity, then it starts MainActivity and closes. MainActivity in some moment starts PlayerActivity and goes to backstack. (MainActivity is alive but is onStop) Then I need open MainActivity and set PlayerActivity to background (PlayerActivity is alive but is onStop). Then I need open PlayerActivity again and set MainActivity to background.

So PlayerActivity and MainActivity often gets onPause() and onStop() without onDestroy when app switch one to another and back.

I need finish all activities and start app for SplashActivity each time when user will push "home" button but home button makes the same like switch between activities (onPause() and onStop()). So I can not catch the difference to kill activities.

Please help.

EDITED: Unfortunately, onUserLeaveHint doesn't help, it's the same. If User pushes HOME this calls:

onUserInteraction, onUserLeaveHint, onPause, onStop

This Activity return previous Activity (Main) without any users actions.

public class PlayerActivity extends Activity{

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

    Handler handler = new Handler();
    handler.postDelayed(new Runnable() {
        @Override
        public void run() {
            startActivity(new Intent(PlayerActivity.this, MyActivity.class));
        }
    }, 5000);
}

}

But still have the same:

onUserInteraction, onUserLeaveHint, onPause, onStop

Saviour answered 29/10, 2014 at 0:2 Comment(2)
Drop SplashActivity, if you do nothing in it.Philippeville
Right opposite, app does a lot in SplashActivity so I need it, and I need start SplashActivity any time when user just collapse app with home-button.Saviour
S
2

To my knowledge, there is no way to override the home button or listen for home button press events.

However, your goal is to have the application know and take action when the following occurs:

  • None of your Activities are showing -> One of your Activities is showing.

When this occurs, you want to show a splash dialog.

You can keep track of when the user is in your application and check whether the user navigated to your Activity from within your application.

UPDATE: Instead of modifying all Activities as the example shows below, you could use the ActivityLifecycleCallbacks object to know when any of your Activities' lifecycle callbacks are called. You can take my example and modify it. I believe ActivityLifecycleCallbacks.onActivityStarted() is called after the super.onStart() call, so you will have to check cameFromMyApplication() before you call super.onStart() in Activity.onStart(). This is less prone to error and requires less code.

Modified How to check if activity is in foreground or in visible background? to fit this question

Example Implement custom Application class:

public class MyApplication extends Application {

  public static boolean cameFromMyApplication() {
    return count != 0;
  }  

  public static void activityStarted() {
    count++;
  }

  public static void activityStopped() {
    count--;
  }

  private static int count;
}

Register your application class in AndroidManifest.xml:

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

Add onStart and onStop to every Activity in the project (you may create a common ancestor for your Activities if you'd like to):

@Override
protected void onStart() {
  super.onStart();
  //Do not include this check in the splash screen Activity
  if(!MyApplication.cameFromMyApplication()) {
    //User arrived from outside the application
    //Application specific code (clear Activity backstack & show splash screen in your case)
  }
  MyApplication.activityStarted();
}

@Override
protected void onStop() {
  super.onStop();
  MyApplication.activityStopped();
}
Spoondrift answered 29/10, 2014 at 1:44 Comment(2)
I see, that isn't the way I was hoping, but it is only the one that works. Great Thanks!Saviour
Great. One thing to note: You need to call activityStarted/activityStopped in all Activities. I updated the answer.Spoondrift
U
1

you can check it like this:

ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List<RunningTaskInfo> tasks = am.getRunningTasks(1);
    // check if home was pressed
    if (tasks.get(0).topActivity.getPackageName().equals("com.android.launcher")) {
        // HOME button pressed
    } else {
        // RECENT APPS pressed (you can listen for the key event before)
        // activity with FLAG_ACTIVITY_NEW_TASK started
        // etc.
    }
Ussery answered 6/12, 2016 at 12:44 Comment(0)
A
0

You can catch a "home button click" with the overridable onUserLeavesHint() function, that may be sufficient in your situation.

@Override
public void onUserLeaveHint() {
    super.onUserLeaveHint();
    // Do your thing
}

Documentation from http://developer.android.com/reference/android/app/Activity.html#onUserLeaveHint()

protected void onUserLeaveHint ()

Called as part of the activity lifecycle when an activity is about to go into the background as the result of user choice. For example, when the user presses the Home key, onUserLeaveHint() will be called, but when an incoming phone call causes the in-call Activity to be automatically brought to the foreground, onUserLeaveHint() will not be called on the activity being interrupted. In cases when it is invoked, this method is called right before the activity's onPause() callback.

This callback and onUserInteraction() are intended to help activities manage status bar notifications intelligently; specifically, for helping activities determine the proper time to cancel a notfication.

Armchair answered 29/10, 2014 at 0:14 Comment(1)
tnx, but unfortunately it didn't help, pls see my editing aboveSaviour
L
0

I was looking for a solution to a similar problem and the code provided by ungalcrys above put me in the right direction so here's a more universal solution to the problem and for anyone that needs it

@Override
protected void onStop() {
        super.onStop();

        ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
        List<ActivityManager.RunningTaskInfo> tasks = am.getRunningTasks(1);

        // check if the app is still visible
        if (!tasks.get(0).topActivity.getPackageName().equals(getPackageName())) {
            // for some reason(HOME, BACK, RECENT APPS, etc.) the app is no longer visible
            // do your thing here
            } else {
            // app is still visible, switched to other activity
        }
    }
Lp answered 28/2, 2017 at 9:12 Comment(0)
L
0

I know this question was asked a while ago but I think this answer could help anyone with this issue.

class YourApplication : Application() {

  override fun onCreate() {
    super.onCreate()
    registerActivityLifecycleCallbacks(AppLifecycleTracker())
  }

}


class AppLifecycleTracker : Application.ActivityLifecycleCallbacks  {

  private var numStarted = 0

  override fun onActivityStarted(activity: Activity?) {
    if (numStarted == 0) {
      // app went to foreground
    }
    numStarted++
  }

  override fun onActivityStopped(activity: Activity?) {
    numStarted--
    if (numStarted == 0) {
      // app went to background
    }
  }

}

With that answer, you can differentiate whether another activity was started or the home button was pressed (or the recent apps button also), and you can call your activity method by implementing an interface defined in the new Application class, or any other way you fancy.

This answer is from a Google I/O talk, here is the original answer https://mcmap.net/q/80321/-how-to-detect-when-an-android-app-goes-to-the-background-and-come-back-to-the-foreground

Latticed answered 23/9, 2021 at 21:58 Comment(1)
While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. - From ReviewWilkins

© 2022 - 2024 — McMap. All rights reserved.