13

Can you please tell me how can my activity detect user pressing HOME key?

Thank you.

Shobhit Puri
  • 25,769
  • 11
  • 95
  • 124
n179911
  • 19,547
  • 46
  • 120
  • 162

11 Answers11

45

Update [August 2015]: As per the comment of JM Lord, this answer might not work as desired for devices Lollipop and above. See Alternative to getRunningTasks in Android L


Although, its an old question but most of the answers didn't work for me in API level 17 and above. I am answering what finally worked for me. I've tried many method but none of them are working as today. I tried answers on

Call method when home button pressed on android,

Detect home button press in android and

Overriding the Home button - how do I get rid of the choice?. The gist was that Home is like an emergency escape button. So you can't override it but can detect it in some ways.

Some of the ones I tried( including above answers) and didn't work are:

  1. Using keyCode==KeyEvent.KEYCODE_HOME in many ways as stated above. Now, if you read the documentation of KeyEvent.KEYCODE_HOME, it says that This key is handled by the framework and is never delivered to applications. So its no more valid now.

  2. I tried using onUserLeaveHint(). The documentation says:

    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.

    The issue with that is that the method also gets called when you start an Activity from within the activity where you are calling onUserleaveLint(), as was my case. See Android onBackPressed/onUserLeaveHint question for more. So its not sure that it would be call ONLY by pressing home button.

  3. Calling onStop(). It can also be called when an activity comes on top of the existing activity and fully covers it. So this also wont work.

Finally the following worked for me :

Seeing How to check current running applications in Android? you can say that if yours is the recent task that is shown on long pressing the home button, then it was send to background.

So, In your onPause() of the activity where you are trying to detect the home button pressed, you can check whether the application has been sent to background.

@Override
public void onPause() {
    if (isApplicationSentToBackground(this)){
        // Do what you want to do on detecting Home Key being Pressed 
    }
    super.onPause();
}

Function to check whether yours is the app which has been most recently sent to the background:

public 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;
}

Thanks to @idish for pointing out that don't forget to include the following permission in your manifest:

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

I am not sure whether there are any downsides of this, but it worked for me well. Hope it helps someone someday.

P.S: If you use this method in an Activity which has been launched with FLAG_ACTIVITY_NO_HISTORY flag, then this won't be useful as it checks the recent history for figuring out if Home button was clicked.

Community
  • 1
  • 1
Shobhit Puri
  • 25,769
  • 11
  • 95
  • 124
  • How to distinguish this from multitasking button ? – Renetik Dec 31 '13 at 18:57
  • Can you please clear a bit more? What is a multitasking button? When user presses `Home` button, he/she can see which are apps in background and then can move from one to other? Other than that there are `Back` and `Menu`.. some device also have `Search` button that I am aware of. It would be helpful if you can let me know of this button and the device which has it. Thanks :) – Shobhit Puri Dec 31 '13 at 22:13
  • There are some issues with the suggested solution: http://stackoverflow.com/a/5862048/1037294 – a.ch. Jan 08 '14 at 14:30
  • I was successfully using a similar solution with the ActivityManager to detect the pressing of Home or History Button on KitKat. When upgrading to Lollipop however, the new History pane and Home selector are not anymore visible in the running tasks, hence this method will not work. (tested on Samsung tablet only) – JM Lord Aug 05 '15 at 13:31
  • 2
    Actually, if your target is Lollipop, the method is explicitly deprecated : http://stackoverflow.com/questions/26400469/alternative-to-getrunningtasks-in-android-l – JM Lord Aug 05 '15 at 13:45
  • Its works only for kitkat, not for Lollipop – Tejas Oct 09 '15 at 12:51
  • This does not work on Android Pie. How do we detect the home button click? – user2511882 May 14 '19 at 15:35
12

You can detect a HOME button press via Activity.onUserLeaveHint(). This method is called in two situations; when the user presses HOME and when a new activity is started. Make sure to somehow differenciate between the two.

Springfeed
  • 145
  • 1
  • 2
  • 2
    It's not called when user presses Home, if the current Activity is the currently default Launcher :) – artem Aug 03 '12 at 00:09
  • 1
    It is also called when activity launches other activity. – Blackhex Mar 28 '13 at 17:27
  • I agree to @Blackhex. http://stackoverflow.com/questions/6612058/android-onbackpressed-onuserleavehint/8749061#8749061 question also says the same. So, it won't work in all conditions now. – Shobhit Puri Sep 13 '13 at 23:14
  • `onUserLeaveHint()` is also called when you press task key – almisoft Jun 24 '16 at 20:09
9

There is no formal way to be notified of a "HOME" key press. But there is a pretty simple work around to have your app distinguish between a "HOME" key press and any other action which would cause the Activity to stop.

For each class that need to perform some action on a "HOME" key press have them extend from an activity which contains this:

/**************************************** On Home **********************************/
private boolean leaveCalled = false;

@Override
public void startActivity(Intent intent) {  
    leaveCalled= true;
    super.startActivity(intent);
}

@Override
public void onBackPressed() {
    leaveCalled = true;
    super.onBackPressed();
}

@Override
protected void onStop() {   
    super.onStop();
    // Home button pressed
    if(!leaveCalled) {
        // Do whatever you like.
    }

    leaveCalled = false;
}

EDIT

You will also need to extend your Fragments from a parent class which contains this. This is because fragments would otherwise provide an extra route to switch between activities in your app in an expected and not "HOME" way.

@Override
public void startActivity(Intent intent) {  
    getActivity().startActivity(intent);
}

EDIT 2

I'm getting close to thinking this isn't the easiest way to deal with this... You need to also add onConfigurationChange="orientation" to all of your activities which use this method. Then you can add this:

@Override
public void onConfigurationChanged(Configuration newConfig) {   
    super.onConfigurationChanged(newConfig);
    leaveCalled = true;                     
    finish();
    startActivity(getIntent()); 
}

EDIT 3

Urgh

@Override
public void finish() {
    leaveCalled = true;
    super.finish();
}
Graeme
  • 25,714
  • 24
  • 124
  • 186
  • These no good. There is too many case that the Activity's `onStop() `is `leaveCalled = false` like phone call, activity's launch from service, etc... – Yeung Aug 05 '14 at 03:41
  • Agreed - but this is the same problem faced with every other "work around" to catch the home button. It isn't something that is included in the API. – Graeme Aug 06 '14 at 08:19
8

You can't capture the HOME event and intercept it in any way. The user will always be taken to the home screen of their device when they press the home key.

If you need to know when your Activity is being sent to the background, like from the user pressing the home or back keys, I'd implement the onStop() method.

Mark B
  • 183,023
  • 24
  • 297
  • 295
  • 2
    Nope, thats not true. Even if you meant onPause(), this answer wouldnt correct - keep in mind that onStop is not guaranteed to be called, at all. These little "Android-specifics" blow my mind. :-/ – Martin Pfeffer Dec 04 '14 at 04:00
8

use onUserLeaveHint() method in your Activity

@Override
protected void onUserLeaveHint()
{
   super.onUserLeaveHint();
}

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

Sujewan
  • 1,023
  • 10
  • 25
4

It can be done(uptil 2.3 atleast). Tested on android version 2.3.5 non-rooted HTC WildFire-S. Code snippet to catch/disable all the control keys :

@Override
public void onAttachedToWindow() {
    super.onAttachedToWindow();        
    this.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD);


}

public boolean onKeyDown(int keyCode, KeyEvent event) {     

    if(keyCode == KeyEvent.KEYCODE_HOME || keyCode == KeyEvent.KEYCODE_POWER || keyCode == KeyEvent.KEYCODE_BACK || keyCode == KeyEvent.KEYCODE_MENU || keyCode == KeyEvent.KEYCODE_SEARCH  )
    {

       Toast.makeText(getApplicationContext(),"You pressed a control button with keyCode : " + keyCode, Toast.LENGTH_SHORT).show();
       return false;

    }
    else
    {
        Toast.makeText(getApplicationContext(),"You pressed" + keyCode, Toast.LENGTH_SHORT).show();
    }

    return true;
}

public boolean onKeyUp(int keyCode, KeyEvent event) {     

    if(keyCode == KeyEvent.KEYCODE_HOME || keyCode == KeyEvent.KEYCODE_POWER || keyCode == KeyEvent.KEYCODE_BACK || keyCode == KeyEvent.KEYCODE_MENU || keyCode == KeyEvent.KEYCODE_SEARCH  )
    {

       return false;

    }
    else
    {
        // Do nothing
    }

    return true;
}
Vikas Singh
  • 1,781
  • 7
  • 27
  • 54
3

You can write a Broadcast listener and set the filter to

<category android:name="android.intent.category.HOME" />

From the Broadcast receiver start your activity/notify the activity.

halfer
  • 19,824
  • 17
  • 99
  • 186
amiekuser
  • 1,630
  • 1
  • 19
  • 31
2

I found this solution based on the suggestion by @Springfeed. The question being quite generic, note that this particular solution will:

  • Work on Lollipop as well as lower android versions (my precedent code based on the ActivityManager failed on Lollipop)
  • Captures both the Home and History buttons
  • Will not capture Home if the activity itself is defined as Home - Always
  • Will capture Home if the activity is one out of many home options, or not Home at all.

This code is in my base Activity class (of which all activities inherit)

    public boolean startingActivity = false;

    @Override
    protected void onUserLeaveHint()
    {
        if(startingActivity)
        {
            // Reset boolean for next time
            startingActivity = false;
        }
        else
        {
            // User is exiting to another application, do what you want here
            Log.i(TAG, "Exiting");
            ...
        }
    }

    @Override
    public void startActivity(Intent intent)
    {
        startingActivity = true;
        super.startActivity(intent);
    }

    @Override
    public void startActivityForResult(Intent intent, int requestCode)
    {
        startingActivity = true;
        super.startActivityForResult(intent, requestCode);
    }

As some methods might also use the application context to launch intents, I defined a ContextWrapper held by my Application class to switch the boolean as well (note that I have static access to the topmost activity of my own application through that base class).

public class MyContext extends ContextWrapper
{

    public MyContext(Context base)
    {
        super(base);
    }

    @Override
    public void startActivity(Intent intent)
    {
        BaseActivity activity = BaseActivity.getActivity();
        if(activity != null)
        {
            activity.startingActivity = true;
        }

        super.startActivity(intent);
    }

}

One might want to override startActivities(...) as well, if necessary.

Hope this helps :)

JM Lord
  • 1,031
  • 1
  • 13
  • 29
-1
android.text.method.KeyListener.onKeyDown([view],[text],KEYCODE_HOME,[event])

I'm not sure how the other parameters fit in, or even how to implement the above, but the info is all at the keylistner documentation.

But they also mention at another page that the home key ALWAYS goes home, you can't change that. So if you plan on having some kind of "are you sure you want to quit" dialog, that wouldn't work.

Anthony
  • 36,459
  • 25
  • 97
  • 163
-1
public 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;
    }



 public void onPause() {
    super.onPause();
    if(isApplicationSentToBackground(this))
    {
        Log.i("Home", "Home Pressed..!");
    }
 }
AJ0
  • 13
  • 7
-8
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {     

    if(keyCode == KeyEvent.KEYCODE_HOME)
    {

       //The Code Want to Perform. 

    }
});
hharry
  • 422
  • 1
  • 9
  • 21