按下主页按钮时的调用方法
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
在Android N多窗口模式下按下主页按钮时未调用Activity onStop()