Android 如何检测用户在我的活动中按下 HOME 键?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2208912/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can I detect user pressing HOME key in my activity?
提问by n179911
Can you please tell me how can my activity detect user pressing HOMEkey?
你能告诉我我的活动如何检测用户HOME按键吗?
Thank you.
谢谢你。
回答by Shobhit Puri
Update[August 2015]: As per the comment of JM Lord, this answer might not work as desired for devices Lollipop and above. See Alternative to getRunningTasks in Android L
更新[2015 年 8 月]:根据JM Lord的评论,对于 Lollipop 及以上设备,此答案可能无法正常工作。请参阅Android L 中 getRunningTasks 的替代方法
Although, its an old question but most of the answers didn't work for me in API level 17 and above. I am answering what finally worked for me. I've tried many method but none of them are working as today. I tried answers on
虽然,这是一个老问题,但大多数答案在 API 级别 17 及以上对我不起作用。我正在回答最终对我有用的内容。我尝试了很多方法,但没有一个像今天一样有效。我试过答案
Call method when home button pressed on android,
Detect home button press in androidand
Overriding the Home button - how do I get rid of the choice?. The gist was that Home is like an emergency escape button. So you can't override it but can detect it in some ways.
覆盖主页按钮 - 我如何摆脱选择?. 要点是 Home 就像一个紧急逃生按钮。所以你不能覆盖它,但可以通过某些方式检测它。
Some of the ones I tried( including above answers) and didn't workare:
我尝试过的一些(包括上述答案)但没有奏效的是:
Using
keyCode==KeyEvent.KEYCODE_HOME
in many ways as stated above. Now, if you read the documentation of KeyEvent.KEYCODE_HOME, it says thatThis key is handled by the framework and is never delivered to applications
. So its no more valid now.I tried using
onUserLeaveHint()
. The documentation says:Called as part of the activity lifecycle when an activity is about to go into the background as the result of user choice. For example, when the user presses the Home key, onUserLeaveHint() will be called, but when an incoming phone call causes the in-call Activity to be automatically brought to the foreground.
The issue with that is that the method also gets called when you start an
Activity
from within the activity where you are callingonUserleaveLint()
, as was my case. See Android onBackPressed/onUserLeaveHintquestion for more. So its not sure that it would be call ONLY by pressing home button.Calling
onStop()
. It can also be called when an activity comes on top of the existing activity and fully covers it. So this also wont work.
keyCode==KeyEvent.KEYCODE_HOME
如上所述以多种方式使用。现在,如果您阅读KeyEvent.KEYCODE_HOME的文档 ,它会说This key is handled by the framework and is never delivered to applications
. 所以它现在不再有效。我尝试使用
onUserLeaveHint()
. 文档说:当 Activity 由于用户选择而即将进入后台时,作为 Activity 生命周期的一部分调用。例如,当用户按下 Home 键时,onUserLeaveHint() 会被调用,但是当有来电时会导致通话中的 Activity 自动被带到前台。
问题在于,当您
Activity
从正在调用的活动中启动 an 时,该方法也会被调用onUserleaveLint()
,就像我的情况一样。有关更多信息,请参阅Android onBackPressed/onUserLeaveHint问题。所以它不确定它是否只能通过按下主页按钮来调用。打电话
onStop()
。当活动位于现有活动之上并完全覆盖它时,也可以调用它。所以这也行不通。
Finally the following workedfor me :
最后以下对我有用:
Seeing How to check current running applications in Android?you can say that if yours is the recent task that is shown on long pressing the home button, then it was send to background.
查看如何在 Android 中检查当前正在运行的应用程序?您可以说,如果您的任务是长按主页按钮时显示的最近任务,则它已发送到后台。
So, In your onPause()
of the activity where you are trying to detect the home button pressed, you can check whether the application has been sent to background.
因此,在您onPause()
尝试检测按下的主页按钮的活动中,您可以检查应用程序是否已发送到后台。
@Override
public void onPause() {
if (isApplicationSentToBackground(this)){
// Do what you want to do on detecting Home Key being Pressed
}
super.onPause();
}
Function to check whether yours is the app which has been most recently sent to the background:
检查您的应用程序是否是最近发送到后台的应用程序的功能:
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;
}
Thanks to @idish for pointing out that don't forget to include the following permission in your manifest:
感谢@idish 指出不要忘记在清单中包含以下权限:
<uses-permission android:name="android.permission.GET_TASKS" />
I am not sure whether there are any downsides of this, but it worked for me well. Hope it helps someone someday.
我不确定这是否有任何缺点,但它对我很有效。希望有一天它可以帮助某人。
P.S: If you use this method in an Activity which has been launched with FLAG_ACTIVITY_NO_HISTORY
flag, then this won't be useful as it checks the recent history for figuring out if Home
button was clicked.
PS:如果您在带有FLAG_ACTIVITY_NO_HISTORY
标志的 Activity 中使用此方法,那么这将没有用,因为它会检查最近的历史记录以确定是否Home
单击了按钮。
回答by Springfeed
You can detect a HOME button press via Activity.onUserLeaveHint(). This method is called in two situations; when the user presses HOME and when a new activity is started. Make sure to somehow differenciate between the two.
您可以通过 Activity.onUserLeaveHint() 检测按下 HOME 按钮。这个方法在两种情况下被调用;当用户按下 HOME 以及启动新活动时。确保以某种方式区分两者。
回答by Graeme
There is no formal way to be notified of a "HOME" key press. But there is a pretty simple work around to have your app distinguish between a "HOME" key press and any other action which would cause the Activity to stop.
没有正式的方法可以收到“HOME”键按下的通知。但是有一个非常简单的解决方法可以让您的应用程序区分“HOME”键按下和任何其他会导致 Activity 停止的操作。
For each class that need to perform some action on a "HOME" key press have them extend from an activity which contains this:
对于需要对“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;
}
EDIT
编辑
You will also need to extend your Fragments from a parent class which contains this. This is because fragments would otherwise provide an extra route to switch between activities in your app in an expected and not "HOME" way.
您还需要从包含它的父类扩展您的 Fragments。这是因为 Fragment 会提供额外的路径,以预期的方式而不是“HOME”方式在您的应用程序中的 Activity 之间切换。
@Override
public void startActivity(Intent intent) {
getActivity().startActivity(intent);
}
EDIT 2
编辑 2
I'm getting close to thinking this isn't the easiest way to deal with this... You need to also add onConfigurationChange="orientation" to all of your activities which use this method. Then you can add this:
我越来越接近于认为这不是处理这个问题的最简单方法......您还需要将 onConfigurationChange="orientation" 添加到使用此方法的所有活动中。然后你可以添加这个:
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
leaveCalled = true;
finish();
startActivity(getIntent());
}
EDIT 3
编辑 3
Urgh
乌尔
@Override
public void finish() {
leaveCalled = true;
super.finish();
}
回答by Mark B
You can't capture the HOME event and intercept it in any way. The user will always be taken to the home screen of their device when they press the home key.
您无法捕获 HOME 事件并以任何方式拦截它。当用户按下主页键时,他们将始终被带到其设备的主屏幕。
If you need to know when your Activity is being sent to the background, like from the user pressing the home or back keys, I'd implement the onStop() method.
如果您需要知道您的 Activity 何时被发送到后台,例如用户按下主页或后退键,我将实现 onStop() 方法。
回答by Sujewan
use onUserLeaveHint() method in your Activity
在您的活动中使用 onUserLeaveHint() 方法
@Override
protected void onUserLeaveHint()
{
super.onUserLeaveHint();
}
http://developer.android.com/reference/android/app/Activity.html#onUserLeaveHint()
http://developer.android.com/reference/android/app/Activity.html#onUserLeaveHint()
回答by Vikas Singh
It can be done(uptil 2.3 atleast). Tested on android version 2.3.5 non-rooted HTC WildFire-S. Code snippet to catch/disable all the control keys :
可以做到(至少到 2.3)。在 android 版本 2.3.5 无根 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;
}
回答by amiekuser
You can write a Broadcast listener and set the filter to
您可以编写一个广播侦听器并将过滤器设置为
<category android:name="android.intent.category.HOME" />
From the Broadcast receiver start ur activity/ notify the activity.
从广播接收器开始您的活动/通知活动。
回答by JM Lord
I found this solution based on the suggestion by @Springfeed. The question being quite generic, note that this particular solution will:
我根据@Springfeed 的建议找到了这个解决方案。这个问题很笼统,请注意,这个特定的解决方案将:
- Work on Lollipop as well as lower android versions (my precedent code based on the ActivityManager failed on Lollipop)
- Captures both the Home and History buttons
- Will not capture Home if the activity itself is defined as Home - Always
- Will capture Home if the activity is one out of many home options, or not Home at all.
- 在 Lollipop 以及较低的 android 版本上工作(我基于 ActivityManager 的先例代码在 Lollipop 上失败)
- 捕获主页和历史记录按钮
- 如果活动本身被定义为主页,则不会捕获主页 - 始终
- 如果活动是众多主页选项之一,或者根本不是主页,则将捕获主页。
This code is in my base Activity
class (of which all activities inherit)
这段代码在我的基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);
}
As some methods might also use the application context to launch intents, I defined a ContextWrapper held by my Application class to switch the boolean as well (note that I have static access to the topmost activity of my own application through that base class).
由于某些方法也可能使用应用程序上下文来启动意图,因此我定义了一个由我的 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);
}
}
One might want to override startActivities(...) as well, if necessary.
如有必要,您可能还想覆盖 startActivities(...)。
Hope this helps :)
希望这可以帮助 :)
回答by AJ0
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..!");
}
}
回答by Anthony
android.text.method.KeyListener.onKeyDown([view],[text],KEYCODE_HOME,[event])
I'm not sure how the other parameters fit in, or even how to implement the above, but the info is all at the keylistner documentation.
我不确定其他参数如何适应,甚至不确定如何实现上述内容,但信息都在 keylistner文档中。
But they also mention at another pagethat the home key ALWAYS goes home, you can't change that. So if you plan on having some kind of "are you sure you want to quit" dialog, that wouldn't work.
但他们也在另一个页面提到主页键总是回家,你不能改变它。因此,如果您打算进行某种“您确定要退出吗”对话框,那将行不通。