Detect home button press in android

2018-12-31 20:10发布

This has been driving me nuts for a while now.

Is there any way of reliably detecting if the home button has been pressed in an android application?

Failing that, is there a robust way of telling what caused an activity to go into onPause? i.e Can we detect if it was caused by a new activity launching or by pressing back/home.

One suggestion I have seen is to override onPause() and call isFinishing() but this will return false when pressing the home button just as it would if a new activity is starting so this fails to distinguish between the two.

Any help much appreciated.

** Update** : Thanks to @android-hungry for this link: http://nisha113a5.blogspot.com/

Overiding the following method:

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

Then the following event WILL get fired for home button presses:

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {     

    if(keyCode == KeyEvent.KEYCODE_HOME)
    {
       //The Code Want to Perform. 
    }
});

I'm not sure if there are any side effects with this line:

this.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD);   

So it would seem that contrary to popular belief, you can in fact listen out for the home key. Worryingly, you can return false and have the home key do nothing.

Update: As expected, there are some side affects with this - it seems that embedded videos and google maps are not visible with this mode enabled.

Update: Supposedly this hack no longer works as of Android 4.0 onwards

14条回答
深知你不懂我心
2楼-- · 2018-12-31 20:26

override onUserLeaveHint method can catch the home press event, but you need also consider user click events. following codes works for me.

private boolean isUserClickToLeave = false;
private Handler mHandler = new Handler();

 Runnable resetUserClickFlagRunnable = new Runnable() {
    @Override
    public void run() {
        isUserClickToLeave = false;
    }
};

@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
    if (ev.getAction() == MotionEvent.ACTION_CANCEL || ev.getAction() == MotionEvent.ACTION_UP) {
        isUserClickToLeave = true;
        mHandler.removeCallbacks(resetUserClickFlagRunnable);
        mHandler.postDelayed(resetUserClickFlagRunnable, 1000);
    }
    return super.dispatchTouchEvent(ev);
}

@Override
protected void onUserLeaveHint() {
    super.onUserLeaveHint();
    if (!isUserClickToLeave ) {
        //user press home button case.
       onHomePressed();
    }
    isUserClickToLeave = false;
}

private onHomePressed() {
    //do something here.
}
查看更多
浪荡孟婆
3楼-- · 2018-12-31 20:28

It's a bad idea to change the behavior of the home key. This is why Google doesn't allow you to override the home key. I wouldn't mess with the home key generally speaking. You need to give the user a way to get out of your app if it goes off into the weeds for whatever reason.

I'd image any work around will have unwanted side effects.

查看更多
时光乱了年华
4楼-- · 2018-12-31 20:29

You might consider a solution by Andreas Shrade in his post on How-To Create a Working Kiosk Mode in Android. It's a bit hacky, but given the reasons that interception of the home button is prevented it has to be ;)

查看更多
琉璃瓶的回忆
5楼-- · 2018-12-31 20:32

Try to create a counter for each screen. If the user touch HOME, then the counter will be zero.

public void onStart() {
  super.onStart();
  counter++;
}

public void onStop() {
  super.onStop();
  counter--;    
  if (counter == 0) {
      // Do..
  }
}
查看更多
与风俱净
6楼-- · 2018-12-31 20:34

Following code works for me :)

HomeWatcher mHomeWatcher = new HomeWatcher(this);
mHomeWatcher.setOnHomePressedListener(new OnHomePressedListener() {
    @Override
    public void onHomePressed() {
        // do something here...
    }
    @Override
    public void onHomeLongPressed() {
    }
});
mHomeWatcher.startWatch();
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.util.Log;

public class HomeWatcher {

    static final String TAG = "hg";
    private Context mContext;
    private IntentFilter mFilter;
    private OnHomePressedListener mListener;
    private InnerReceiver mReceiver;

    public HomeWatcher(Context context) {
        mContext = context;
        mFilter = new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
    }

    public void setOnHomePressedListener(OnHomePressedListener listener) {
        mListener = listener;
        mReceiver = new InnerReceiver();
    }

    public void startWatch() {
        if (mReceiver != null) {
            mContext.registerReceiver(mReceiver, mFilter);
        }
    }

    public void stopWatch() {
        if (mReceiver != null) {
            mContext.unregisterReceiver(mReceiver);
        }
    }

    class InnerReceiver extends BroadcastReceiver {
        final String SYSTEM_DIALOG_REASON_KEY = "reason";
        final String SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS = "globalactions";
        final String SYSTEM_DIALOG_REASON_RECENT_APPS = "recentapps";
        final String SYSTEM_DIALOG_REASON_HOME_KEY = "homekey";

        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (action.equals(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)) {
                String reason = intent.getStringExtra(SYSTEM_DIALOG_REASON_KEY);
                if (reason != null) {
                    Log.e(TAG, "action:" + action + ",reason:" + reason);
                    if (mListener != null) {
                        if (reason.equals(SYSTEM_DIALOG_REASON_HOME_KEY)) {
                            mListener.onHomePressed();
                        } else if (reason.equals(SYSTEM_DIALOG_REASON_RECENT_APPS)) {
                            mListener.onHomeLongPressed();
                        }
                    }
                }
            }
        }
    }
}
public interface OnHomePressedListener {
    void onHomePressed();
    void onHomeLongPressed();
}
查看更多
呛了眼睛熬了心
7楼-- · 2018-12-31 20:39

It is impossible to detect and/or intercept the HOME button from within an Android app. This is built into the system to prevent malicious apps that cannot be exited.

查看更多
登录 后发表回答