【问题标题】:How can I detect user pressing HOME key in my activity? [duplicate]如何检测用户在我的活动中按下 HOME 键? [复制]
【发布时间】:2011-01-13 14:44:19
【问题描述】:

你能告诉我我的活动如何检测到用户按下 HOME 键吗?

谢谢。

【问题讨论】:

    标签: android


    【解决方案1】:
    android.text.method.KeyListener.onKeyDown([view],[text],KEYCODE_HOME,[event])
    

    我不确定其他参数如何适应,甚至如何实现上述参数,但信息都在 keylistner documentation

    但他们在another page 也提到主页键总是回家,你不能改变它。因此,如果您打算使用某种“您确定要退出”对话框,那是行不通的。

    【讨论】:

      【解决方案2】:

      您无法捕获 HOME 事件并以任何方式拦截它。当用户按下主屏幕键时,他们将始终被带到他们设备的主屏幕。

      如果您需要知道您的 Activity 何时被发送到后台,例如用户按下主页或返回键,我会实现 onStop() 方法。

      【讨论】:

      • 不,那不是真的。即使您的意思是 onPause(),这个答案也不会正确 - 请记住,根本不能保证调用 onStop。这些小小的“Android-specifics”让我大吃一惊。 :-/
      【解决方案3】:

      您可以编写一个广播监听器并将过滤器设置为

      <category android:name="android.intent.category.HOME" />
      

      从广播接收器开始你的活动/通知活动。

      【讨论】:

      • 这是不可能的,因为它不是广播意图...
      【解决方案4】:

      您可以通过 Activity.onUserLeaveHint() 检测到按下 HOME 按钮。该方法在两种情况下被调用;当用户按下 HOME 并启动新活动时。确保以某种方式区分两者。

      【讨论】:

      • 如果当前Activity是当前默认的Launcher,则当用户按下Home时不会调用它:)
      • activity启动其他activity时也会调用。
      • 我同意@Blackhex。 stackoverflow.com/questions/6612058/… question 也这么说。所以,它现在不能在所有条件下工作。
      • onUserLeaveHint() 在你按下任务键时也会被调用
      【解决方案5】:

      没有正式的方式来通知“HOME”键按下。但是有一个非常简单的解决方法可以让您的应用区分“HOME”按键和任何其他会导致 Activity 停止的操作。

      对于需要在“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。这是因为 Fragment 会提供额外的路径,以预期的方式而不是“HOME”方式在应用中的 Activity 之间切换。

      @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

      @Override
      public void finish() {
          leaveCalled = true;
          super.finish();
      }
      

      【讨论】:

      • 这些不好。 Activity的onStop() leaveCalled = false的情况太多了,比如电话、Activity从服务中启动等等……
      • 同意 - 但这与所有其他“解决方法”以捕捉主页按钮所面临的问题相同。它不是 API 中包含的东西。
      【解决方案6】:

      可以做到(至少到 2.3)。在 android 版本 2.3.5 无根 HTC WildFire-S 上测试。代码 sn-p 捕获/禁用所有控制键:

      @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;
      }
      

      【讨论】:

        【解决方案7】:
        @Override
        public boolean onKeyDown(int keyCode, KeyEvent event) {     
        
            if(keyCode == KeyEvent.KEYCODE_HOME)
            {
        
               //The Code Want to Perform. 
        
            }
        });
        

        【讨论】:

        • 不适用于 android 4.0 或更高版本
        • 不错的答案 - 就像一个魅力! :D NOOOOOOT :)
        【解决方案8】:

        更新 [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 就像一个紧急逃生按钮。所以你不能覆盖它,但可以通过某些方式检测到它。

        我尝试过的一些(包括上面的答案)并且不起作用是:

        1. 以多种方式使用 keyCode==KeyEvent.KEYCODE_HOME 综上所述。现在,如果您阅读 KeyEvent.KEYCODE_HOME,上面写着This key is handled by the framework and is never delivered to applications。所以它不再 现在有效。

        2. 我尝试使用 onUserLeaveHint()。文档说:

          在活动即将开始时作为活动生命周期的一部分调用 作为用户选择的结果进入后台。例如, 当用户按下 Home 键时,onUserLeaveHint() 将 通话,但当来电导致通话中活动 被自动带到前台。

          问题在于,当您启动 Activity 时,该方法也会被调用 在您调用onUserleaveLint() 的活动中, 就像我的情况一样。有关更多信息,请参阅Android onBackPressed/onUserLeaveHint 问题。所以它不确定 只有按主页按钮才能调用它。

        3. 呼叫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" />
        

        我不确定这是否有任何缺点,但它对我很有效。希望有一天它可以帮助某人。

        P.S:如果您在使用 FLAG_ACTIVITY_NO_HISTORY 标志启动的 Activity 中使用此方法,那么这将没有用,因为它会检查最近的历史记录以确定是否单击了 Home 按钮。

        【讨论】:

        • 今天帮助了我 :) 这是一个很好的解决方案。非常感谢。注意:不要忘记在清单中包含以下权限:
        • 很高兴它有帮助。感谢您指出了这一点。我编辑了答案。
        • 完美!谢谢肖比特!
        • 如何区分这个和多任务按钮?
        • 其实,如果你的目标是 Lollipop,这个方法已经被明确弃用了:stackoverflow.com/questions/26400469/…
        【解决方案9】:

        在你的 Activity 中使用 onUserLeaveHint() 方法

        @Override
        protected void onUserLeaveHint()
        {
           super.onUserLeaveHint();
        }
        

        http://developer.android.com/reference/android/app/Activity.html#onUserLeaveHint()

        【讨论】:

        • 迄今为止我找到的最佳答案 :)
        • 但是当我们移动到另一个活动时,这个方法会回调。如何区分按下 HOME 按钮。谢谢
        【解决方案10】:
        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..!");
            }
         }
        

        【讨论】:

        • topActivity 未找到!
        【解决方案11】:

        我根据@Springfeed 的建议找到了这个解决方案。这个问题很笼统,请注意这个特定的解决方案将:

        • 在 Lollipop 和较低的 android 版本上工作(我基于 ActivityManager 的先例代码在 Lollipop 上失败)
        • 捕获主页和历史按钮
        • 如果 Activity 本身被定义为 Home - Always,则不会捕获 Home
        • 如果活动是许多家庭选项之一,或者根本不是家庭,则将捕获家庭。

        这段代码在我的基础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(...)。

        希望这会有所帮助:)

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-10-06
          • 2021-07-21
          • 1970-01-01
          • 1970-01-01
          • 2022-10-04
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多