请告诉我,我的活动如何检测用户按 HOME 键?
谢谢。
答案 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就像一个紧急逃生按钮。所以你不能覆盖它,但可以在某些方面检测它。
我试过的一些(包括上面的答案)和不起作用是:
以多种方式使用 keyCode==KeyEvent.KEYCODE_HOME
综上所述。现在,如果您阅读了文档
KeyEvent.KEYCODE_HOME,它说This key is handled by the
framework and is never delivered to applications
。所以它不再
现在有效。
我尝试使用 onUserLeaveHint()
。文档说:
当活动涉及时,被称为活动生命周期的一部分 作为用户选择的结果进入后台。例如, 当用户按下Home键时,onUserLeaveHint()将会出现 呼叫,但当来电时导致呼叫中的活动 自动带到前台。
问题在于,当您启动Activity
时也会调用该方法
在您呼叫onUserleaveLint()
的活动中,
就像我的情况一样。有关详情,请参阅Android onBackPressed/onUserLeaveHint问题。所以它不确定
只需按回车键即可拨打电话。
致电onStop()
。当活动出现在现有活动之上并完全覆盖它时,也可以调用它。所以这也行不通。
最后对我有用:
看到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的建议找到了这个解决方案。这个问题非常通用,请注意这个特定的解决方案:
此代码位于我的基础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.
}
});