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

Posted

技术标签:

【中文标题】按下主页按钮时的调用方法【英文标题】:Call method when home button pressed 【发布时间】:2011-06-14 14:43:24 【问题描述】:

我的一个 android 活动中有这个方法:

@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 有效,日志方法也不会触发。这适用于后退按钮。有谁知道这是为什么以及如何让它发挥作用?

【问题讨论】:

***.com/a/8883447/439171 @Yvette 我同意。然而,仅出于原因。无论如何,它可能应该关闭,因为经过反思,尝试和检测并不是一件好事 - 因此对于未来的 SO 访问者来说也不是一件好事。有更好的方法来停止服务(这是我真正的问题),并且您不能覆盖主页按钮,因为下面的一些答案会讨论。 按照here 的建议使用 onTrimMemory() 【参考方案1】:

Home 按钮是一个非常危险的覆盖按钮,因此,Android 不会让你覆盖它的行为,就像你使用 BACK 按钮一样。

看看这个discussion.

您会注意到主页按钮似乎是作为意图调用实现的,因此您最终必须向您的活动添加一个意图类别。然后,任何时候用户回家,你的应用都会作为一个选项出现。您应该考虑使用主页按钮要完成的任务。如果它不替换设备的默认主屏幕,我会警惕超载 HOME 按钮,但这是可能的(根据上述线程中的讨论。)

【讨论】:

如果我想停止媒体播放器怎么办?如果我按 Home,它会继续播放... 我不需要覆盖主页按钮,我只需要在应用消失之前停止音乐! 只需检测您的活动是否进入后台。【参考方案2】:

我花了将近一个月的时间才完成这个。刚才我解决了这个问题。 在您的活动的 onPause() 中,您必须包含以下 if 条件:

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

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

希望对你有帮助!

【讨论】:

代码应该是 if (!this.isFiishing()) //home button pressed (只需添加一个“!”) iwind 的评论是正确的。更准确地说:如果按下 HOME 按钮或 TABS 按钮或 屏幕关闭isFinishing() 将是 false。 (如果按下BACK 按钮,则为true。)【参考方案3】:

主页按钮不能被应用程序截取。这是 Android 中的设计行为。原因是为了防止恶意应用程序控制您的手机(如果用户无法按返回或主页,他可能永远无法退出应用程序)。 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 btw 上的文档:“对于在其包中将 launchMode 设置为“singleTop”的活动,或者如果客户端在调用 startActivity 时使用了 Intent.FLAG_ACTIVITY_SINGLE_TOP 标志,则调用此选项。在任何一种情况下,当活动重新- 在 Activity 堆栈的顶部启动,而不是正在启动的 Activity 的新实例,onNewIntent() 将在现有实例上使用用于重新启动它的 Intent 调用"【参考方案4】:

我发现当我按下HOME按钮时,onStop()方法被调用了。你可以使用下面这段代码来监控它:

@Override
    protected void onStop() 
    
        super.onStop();
        Log.d(tag, "MYonStop is called");
        // insert here your instructions
    

【讨论】:

它可以工作,但是当你去另一个活动时它也会被调用。因此,它不会仅在您退出应用程序时调用。 说实话,这个答案是错误的。 onStop 在各种场合(如 italo 所述)被调用,不仅是在按下 Home 按钮时! 当我阅读该主题时,决定使用 onStop() 覆盖来回答。这是唯一可行的方法,无需添加所有类别和其他内容。 注意onStop即使在屏幕旋转时也会被调用 @italo 是的,这正是我的问题。你知道当用户离开我的应用程序时我应该使用什么方法让它执行吗?【参考方案5】:

我有一个处理主页按钮按下的简单解决方案。这是我的代码,它可能很有用:

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



总而言之,在活动中放置一个布尔值,当活动切换发生时(startactivity事件),设置变量并在onpause事件中检查这个变量..

【讨论】:

这不是一个坏主意。虽然它实际上并没有告诉您是否按下了主页按钮,但您可以假设。我猜这个方法在电话开始响铃时调用?【参考方案6】:

KeyEvent.KEYCODE_HOME 无法被拦截。

如果可能的话,那就太糟糕了。

(编辑):我只看到尼克斯的回答,非常完整;)

【讨论】:

【参考方案7】:

使用广播接收器

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
                
            
        
    

【讨论】:

【参考方案8】:

使用onPause() 方法在主页按钮上执行您想要执行的操作。

【讨论】:

onPause 也是在屏幕关闭时启动... onStop 更好。【参考方案9】:

我也为 HOME 按钮苦苦挣扎了一段时间。 当用户单击 HOME 按钮时,我想停止/跳过后台服务(轮询位置)。

这是我实施的“类黑客”解决方案;

使用布尔值在 SharedPreferences 上保持应用的状态

每个活动

onResume() -> 设置 appactive=true

onPause() -> 设置 appactive=false

后台服务在每个循环中检查appstate,跳过动作

如果 appactive=false

它对我来说很好用,至少不会再耗尽电池了, 希望这会有所帮助....

【讨论】:

同样,只有当您的应用程序只有一个活动时,这才是正确的。如果您切换到同一个应用程序中的另一个活动,您将把 appActive 变量设置为 true。【参考方案10】:

像这样在activity 中定义变量:

const val SYSTEM_DIALOG_REASON_KEY = "reason"
const val SYSTEM_DIALOG_REASON_RECENT_APPS = "recentapps"
const val SYSTEM_DIALOG_REASON_HOME_KEY = "homekey"

像这样定义你的广播接收器类:

class ServiceActionsReceiver: BroadcastReceiver()
        override fun onReceive(context: Context?, intent: Intent?) 
            
            val action = intent!!.action
            if (action == Intent.ACTION_CLOSE_SYSTEM_DIALOGS) 
                val reason = intent.getStringExtra(SYSTEM_DIALOG_REASON_KEY)
                if (reason != null) 
                    if (reason == SYSTEM_DIALOG_REASON_HOME_KEY) 
                        //do what you want to do when home pressed
                     else if (reason == SYSTEM_DIALOG_REASON_RECENT_APPS) 
                        //do what you want to do when recent apps pressed
                    
                
            
        
    

onCreate 方法或onResume 方法上注册接收器,如下所示:

val filter = IntentFilter()
filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)
registerReceiver(receiver, filter)

像这样在清单中添加接收者:

<receiver android:name=".ServiceActionsReceiver">
            <intent-filter >
                <actionandroid:name="android.intent.action.CLOSE_SYSTEM_DIALOGS"/>
            </intent-filter>
</receiver>

【讨论】:

以上是关于按下主页按钮时的调用方法的主要内容,如果未能解决你的问题,请参考以下文章

iOS 9:按下主页按钮时不调用 UIPresentationController::runTransitionForCurrentState

在 reactJS 中,如何通过按下按钮来调用链接点击?

在Android N多窗口模式下按下主页按钮时未调用Activity onStop()

即使按下主页按钮或手机进入待机状态,如何在 iOS 中继续进行 RESTKit 调用

按下锁定/主页按钮时的通知,单击返回选项卡片段时的通知

当我按下按钮时没有调用方法