当按下主页按钮时调用方法

52
我在我的Android Activity中有这个方法:
@Override
public boolean onKeyDown(int keyCode, KeyEvent event)
{
    if(keyCode == KeyEvent.KEYCODE_BACK)
    {
        Log.d("Test", "Back button pressed!");
    }
    else if(keyCode == KeyEvent.KEYCODE_HOME)
    {
        Log.d("Test", "Home button pressed!");
    }
    return super.onKeyDown(keyCode, event);
}

但是,即使KEYCODE_HOME有效,log方法也从未触发。对于返回按钮可以正常工作。有人知道为什么会这样,以及如何让它工作吗?


1
http://stackoverflow.com/a/8883447/439171 - Italo Borssatto
@Yvette 我同意。然而只是出于一个原因。它可能应该被关闭,因为反思后,这不是一个很好的尝试去检测 - 因此对于未来的 SO 访问者来说也不是很好。有更好的方法来停止服务(这才是我真正的问题所在),并且你不能像一些答案下面所讨论的那样覆盖主页按钮。 - ingh.am
请按照此处建议使用**onTrimMemory()**函数。链接 - scr
11个回答

35

主页按钮是一个非常危险的按钮,因此Android不会像处理“返回”按钮那样让你覆盖它的行为。

看一下这个讨论

你会发现主页按钮似乎是作为意图调用实现的,因此你需要将意图类别添加到你的活动中。然后,每当用户点击主页时,你的应用程序会出现作为选项。你应该考虑一下你想要通过主页按钮实现什么功能。如果你不打算替换设备的默认主屏幕,我建议你谨慎使用主页按钮,但据上述讨论,这是可能的。


3
如果我想停止媒体播放器怎么办?如果我按主页键它还在播放... - ingh.am
3
我不需要覆盖主页按钮,我只需在应用程序消失之前停止音乐! - ingh.am
仅检测您的活动是否进入后台。 - RRTW

22

我差不多花了一个月才解决这个问题。现在我终于解决了。 在你的活动(Activity)的onPause()方法中,你必须加入以下if条件语句:

    if (this.isFinishing()){
        //Insert your finishing code here
    }

函数isFinishing()返回一个布尔值。如果您的应用程序正在关闭,则为True,如果您的应用程序仍在运行但例如屏幕关闭,则为False。

希望这可以帮到你!


代码应该是 if (!this.isFishing()) { //点击了主页按钮 } (只需添加“!”) - iwind
1
iwind的评论是正确的。更确切地说,如果按下HOME按钮或TABS按钮或屏幕关闭,则isFinishing()将为false。(如果按下BACK按钮,则为true。) - Mir-Ismaili

13

主屏幕按钮在Android中无法被应用程序拦截。这是一种按设计行为。原因是为了防止恶意应用程序控制您的手机(如果用户无法按back或home键,则可能永远无法退出应用程序)。

Home键被认为是用户的“安全区”,并且始终会启动用户配置的主屏幕应用程序。

上述唯一的例外是任何配置为主屏幕替代的应用程序。这意味着在其AndroidManifest.xml文件的相关活动中声明了以下内容:

<intent-filter>
   <action android:name="android.intent.action.MAIN" />
   <category android:name="android.intent.category.HOME" />
   <category android:name="android.intent.category.DEFAULT" />
</intent-filter>
当按下主页按钮时,当前主屏幕应用程序的活动的onNewIntent方法将被调用。

不起作用。顺便提一下,关于onNewIntent的文档:“对于将launchMode设置为“singleTop”的活动,或者如果客户端在调用startActivity时使用了Intent.FLAG_ACTIVITY_SINGLE_TOP标志,将调用此方法。在任何一种情况下,当活动在活动堆栈的顶部重新启动而不是启动活动的新实例时,将在现有实例上调用onNewIntent(),并使用用于重新启动它的Intent。” - m0skit0
当我在开发中使用自定义桌面应用(即自定义启动器)时,这对我很有帮助。 - dazed

8
我发现当我按下HOME按钮时,onStop()方法会被调用。你可以使用以下代码来监测它:
@Override
    protected void onStop() 
    {
        super.onStop();
        Log.d(tag, "MYonStop is called");
        // insert here your instructions
    }

15
它是有效的,但当你转到另一个活动时也会被调用。因此,它不仅在退出应用程序时被调用。 - Italo Borssatto
53
说实话,这个答案是错误的。就像Italo所说的那样,onStop在各种场合下都会被调用,而不仅仅是在按下Home按钮时! - s.krueger
3
请注意,即使屏幕旋转,在大多数情况下也会调用onStop方法。 - Denys Kniazhev-Support Ukraine
@italo 是的,那正是我的问题。您知道我应该使用什么方法,以便只在用户离开我的应用程序时执行它吗? - Ruchir Baronia
答案错误。Activity的onStop方法会因为多种原因被调用,而不仅仅是因为按下Home键。 - Abc.Xyz
显示剩余2条评论

3

使用广播接收器

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // something
    // for home listen
    InnerRecevier innerReceiver = new InnerRecevier();
    IntentFilter intentFilter = new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
    registerReceiver(innerReceiver, intentFilter);

}



// for home listen
class InnerRecevier extends BroadcastReceiver {

    final String SYSTEM_DIALOG_REASON_KEY = "reason";
    final String SYSTEM_DIALOG_REASON_HOME_KEY = "homekey";

    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(action)) {
            String reason = intent.getStringExtra(SYSTEM_DIALOG_REASON_KEY);
            if (reason != null) {
                if (reason.equals(SYSTEM_DIALOG_REASON_HOME_KEY)) {
                    // home is Pressed
                }
            }
        }
    }
}

3

我有一个简单的解决方案来处理首页按钮的按压事件。以下是我的代码,它可能会很有用:

public class LifeCycleActivity extends Activity {


boolean activitySwitchFlag = false;

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) 
{
    if(keyCode == KeyEvent.KEYCODE_BACK)
    {
        activitySwitchFlag = true;
        // activity switch stuff..
        return true;
    }
    return false;
}

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
}

@Override 
public void onPause(){
    super.onPause();
    Log.v("TAG", "onPause" );
    if(activitySwitchFlag)
        Log.v("TAG", "activity switch");
    else
        Log.v("TAG", "home button");
    activitySwitchFlag = false;
}

public void gotoNext(View view){
    activitySwitchFlag = true;
    startActivity(new Intent(LifeCycleActivity.this, NextActivity.class));
}

}

作为总结,在activity中放置一个布尔变量,当activity转换发生(startactivity事件)时,设置该变量,并在onpause事件中检查此变量。

1
这不是一个坏主意。虽然它实际上并没有告诉你Home键是否被按下,但你可以假设。我猜这个方法在手机响铃时调用? - ingh.am

3

KeyEvent.KEYCODE_HOME 无法被拦截。

如果可以拦截,那将是非常糟糕的。

(编辑): 我刚看到了Nick的答案,他的回答已经非常完整了 ;)


2

使用onPause()方法来处理你在按下Home键时想要做的事情。


3
当屏幕关闭时,onPause也会被启动... onStop更好。 (注:本翻译力求忠实原意,同时简洁清晰易懂,如有不妥之处还请指正。) - toto_tata

1

我也曾经为HOME按钮苦恼了一段时间。

当用户点击HOME按钮时,我想停止/跳过后台服务(轮询位置)。

以下是我实现的“hack-like”解决方案:

使用布尔值在SharedPreferences中保持应用程序状态

在每个活动中:

onResume() -> 设置appactive=true

onPause() -> 设置appactive=false

后台服务在每次循环中检查应用程序状态,并跳过操作:

IF appactive=false

这对我很有效,至少不再耗电,希望能帮到你们....


6
如果您的应用程序只有一个活动,那么这个说法才是正确的。如果您在同一应用程序中切换到另一个活动,则需要将appActive变量设置为true。请注意,以上仅适用于翻译内容,不包括解释或其他信息。 - Zoltán

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接