如何检测用户在我的活动中按HOME键?

时间:2010-02-05 17:07:19

标签: android

请告诉我,我的活动如何检测用户按 HOME 键?

谢谢。

11 个答案:

答案 0 :(得分:42)

更新 [2015年8月]:根据JM Lord的评论,此答案可能无法满足设备Lollipop及更高版本的要求。见Alternative to getRunningTasks in Android L


虽然,这是一个老问题,但大多数答案在API级别17及以上版本中对我不起作用。我正在回答最终为我工作的事情。我尝试了很多方法,但没有一个像今天一样工作。我试过

的答案

Call method when home button pressed on android

Detect home button press in android

Overriding the Home button - how do I get rid of the choice?。要点是Home就像一个紧急逃生按钮。所以你不能覆盖它,但可以在某些方面检测它。

我试过的一些(包括上面的答案)和不起作用是:

  1. 以多种方式使用 keyCode==KeyEvent.KEYCODE_HOME 综上所述。现在,如果您阅读了文档 KeyEvent.KEYCODE_HOME,它说This key is handled by the framework and is never delivered to applications。所以它不再 现在有效。

  2. 我尝试使用 onUserLeaveHint() 。文档说:

      

    当活动涉及时,被称为活动生命周期的一部分   作为用户选择的结果进入后台。例如,   当用户按下Home键时,onUserLeaveHint()将会出现   呼叫,但当来电时导致呼叫中的活动   自动带到前台。

    问题在于,当您启动Activity时也会调用该方法 在您呼叫onUserleaveLint()的活动中, 就像我的情况一样。有关详情,请参阅Android onBackPressed/onUserLeaveHint问题。所以它不确定 只需按回车键即可拨打电话。

  3. 致电onStop()。当活动出现在现有活动之上并完全覆盖它时,也可以调用它。所以这也行不通。

  4. 最后对我有用

    看到How to check current running applications in Android?你可以说,如果你的是最近在长按主页按钮时显示的任务,那么它就会发送到后台。

    因此,在您尝试检测按下主页按钮的活动的onPause()中,您可以检查应用程序是否已发送到后台。

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

    检查您的应用是否是最近发送到后台的应用的功能:

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

    感谢@idish指出不要忘记在清单中包含以下权限:

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

    我不确定这是否有任何缺点,但它对我有用。希望有一天能帮助某人。

    PS:如果你在使用FLAG_ACTIVITY_NO_HISTORY标志启动的Activity中使用此方法,那么这将无用,因为它会检查最近的历史记录以确定是否单击了Home按钮。

答案 1 :(得分:12)

您可以通过Activity.onUserLeaveHint()检测HOME按钮按下。在两种情况下调用此方法;当用户按下HOME时以及启动新活动时。确保以某种方式区分两者。

答案 2 :(得分:9)

没有正式的方法可以通知“HOME”按键。但是有一个非常简单的工作,让你的应用程序区分“主页”按键和任何其他可能导致活动停止的动作。

对于需要对“HOME”键执行某些操作的每个类,按下它们将从包含此操作的活动扩展:

/**************************************** 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;
}

修改

您还需要从包含此内容的父类扩展Fragments。这是因为片段会以预期的而不是“HOME”的方式提供额外的路径来在应用程序中的活动之间切换。

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

编辑2

我已经接近认为这不是解决这个问题的最简单方法...您还需要为使​​用此方法的所有活动添加onConfigurationChange =“orientation”。然后你可以添加:

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

编辑3

Urgh

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

答案 3 :(得分:8)

您无法捕捉HOME事件并以任何方式拦截它。当用户按下主页键时,将始终将用户带到设备的主屏幕。

如果您需要知道何时将活动发送到后台,例如用户按下主页或后退键,我将实施onStop()方法。

答案 4 :(得分:7)

在Activity

中使用onUserLeaveHint()方法
@Override
protected void onUserLeaveHint()
{
   super.onUserLeaveHint();
}

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

答案 5 :(得分:4)

可以完成(至少2.3升)。测试Android版2.3.5非root用户HTC WildFire-S。用于捕获/禁用所有控制键的代码片段:

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

答案 6 :(得分:3)

您可以编写广播侦听器并将过滤器设置为

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

从广播接收器开始你的活动/通知活动。

答案 7 :(得分:2)

我根据@Springfeed的建议找到了这个解决方案。这个问题非常通用,请注意这个特定的解决方案:

  • 使用Lollipop以及较低的Android版本(基于ActivityManager的先前代码在Lollipop上失败)
  • 捕获主页和历史记录按钮
  • 如果活动本身被定义为Home - Always
  • ,则不会捕获Home
  • 如果活动是许多家庭选择中的一个,或者根本不回家,将捕获Home。

此代码位于我的基础Activity类中(所有活动都继承)

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

由于某些方法也可能使用应用程序上下文来启动意图,我定义了一个由我的Application类保存的ContextWrapper来切换布尔值(注意我通过该基类可以静态访问我自己的应用程序的最顶层活动) )。

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

}

如果需要,也可以想要覆盖startActivities(...)。

希望这会有所帮助:)

答案 8 :(得分:-1)

android.text.method.KeyListener.onKeyDown([view],[text],KEYCODE_HOME,[event])

我不确定其他参数是如何适应的,甚至不知道如何实现上述内容,但信息全部都在密钥列表documentation

但他们也在another page提到主页钥匙总是回家,你不能改变它。因此,如果您打算使用某种“你确定要退出”对话框,那就不行了。

答案 9 :(得分:-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..!");
    }
 }

答案 10 :(得分:-8)

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

    if(keyCode == KeyEvent.KEYCODE_HOME)
    {

       //The Code Want to Perform. 

    }
});