【问题标题】:Service with Overlay - catch back button press覆盖服务 - 按下返回按钮
【发布时间】:2015-07-16 18:43:50
【问题描述】:

我该怎么做?

当前解决方案

我启动了一个透明的活动,它会捕捉到背后的新闻,将其转发给我的服务,然后自行关闭。但是这个activity会在当前正在运行的activity中可见,因此它不是一个非常漂亮的解决方案。

看到的解决方案

我看到一个应用程序确实在服务中捕获了后按 - 没有捕获后按的活动。如果我显示当前正在运行的活动,则此应用程序没有任何内容。

问题

如何做到这一点?我读过很多帖子说,这是不可能的,但我可以看到,有些应用程序以某种方式实现了这一点......

【问题讨论】:

    标签: android service overlay back


    【解决方案1】:

    如果您在服务的 WindowManager 中附加了覆盖窗口,请将您的视图设置为属性 setFocusableInTouchMode(true),并设置一个键侦听器。您将收到关键事件,如下例所示:

    view.setFocusableInTouchMode(true);
    view.setOnKeyListener(new View.OnKeyListener() {
        @Override
        public boolean onKey(View v, int keyCode, KeyEvent event) {
            if(keyCode == KeyEvent.KEYCODE_BACK) {
                stopSelf();
                return true;
            }
            return false;
        }
    });
    

    已编辑,我没有使用好的 stackoverflow 帐户

    【讨论】:

    • 这对我有用,但前提是我添加 view.requestFocus();也是。
    【解决方案2】:

    我想我知道它是如何工作的...不要在您的叠加视图中使用WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE + 覆盖您视图的dispatchKeyEvent

     @Override
    public boolean dispatchKeyEvent(KeyEvent event)
    {
        if (event.getKeyCode() == KeyEvent.KEYCODE_BACK)
        {
            // handle back press
            // if (event.getAction() == KeyEvent.ACTION_DOWN)
            return true;
        }
        return super.dispatchKeyEvent(event);
    }
    

    【讨论】:

    • 如何在服务类中做到这一点
    • 服务类不要覆盖这样的方法
    • 用什么标志代替FLAG_NOT_FOCUSABLE
    • 取决于你想要什么...我使用WindowManager.LayoutParams.TYPE_SYSTEM_ERROR 作为我的覆盖类型和WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH 作为标志...这对于像应用程序这样的侧边栏很有用...
    • @prom85 您不应使用 TYPE_SYSTEM_ERROR,因为这可能会被误解为恶意软件。 developer.android.com/reference/android/view/… 通常是最佳选择,因为它允许关注视图,但不会阻止外部触摸事件,而 FLAG_WATCH_OUTSIDE_TOUCH 要求您指定传递哪些外部触摸。
    【解决方案3】:

    我找到了解决这个问题的方法,效果很好。

    public class MyFooterService extends Service{
    View myview;
    WindowManager wm;
    FrameLayout wrapper;
    public MyFooterService() {
    
    }
     @Override
    public void onCreate() {
        Log.d(TAG, "onCreate called");
        LayoutInflater li = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
        wm = (WindowManager) getSystemService(WINDOW_SERVICE);
        final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
                WindowManager.LayoutParams.MATCH_PARENT,
                90,  //height of ur layout
                WindowManager.LayoutParams.TYPE_PHONE,
                0,
                PixelFormat.TRANSLUCENT);
    
        params.gravity = Gravity.BOTTOM ;
        params.x = 0;
        params.y = 0;
       wrapper = new FrameLayout(this) {
            @Override
            public boolean dispatchKeyEvent(KeyEvent event) {
                if (event.getKeyCode()==KeyEvent.KEYCODE_BACK) {
                  // handle the back button code;
                 return true;
                }
              return super.dispatchKeyEvent(event);
            }
           //if pressed home key,
          public void onCloseSystemDialogs(String reason) {
                //The Code Want to Perform.
                System.out.println("System dialog " + reason);
                if (reason.equals("homekey")) {
                    // handle home button 
                }
            }
    
         };
       myview = li.inflate(R.layout.my_footer, wrapper);   // here set into your own layout
       wm.addView(myview, params);
    
    }
    }
    

    【讨论】:

    • 如果需要关闭窗口,只需检查包装器的可见性(FrameLayout)
    • 对我有用。只需删除 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
    【解决方案4】:

    您可以捕获后退按钮单击事件。为此,您需要创建 OverlayView 的容器类。例如:创建类 Overlay,它将扩展一些 ViewGroup 类。然后,在课堂上,扩充您的 xml 布局并将其添加到您的 Overlay.class ViewGroup。比在 Overlay.class 覆盖方法 dispatchKeyEvent(KeyEvent event) 中。就是这样!

    class Overlay extends FrameLayout{
      
      public Overlay(@NonNull Context context) {
            super(new ContextThemeWrapper(context, R.style.AppTheme));
    
            initView();
        }
        
        private void initView() {
          //inflate your xml here
          //than do: this.addView(<inflated view>);
          //And in the end add your Overlay to WindowManager (in Service class of course).
        }
        
         @Override
        public boolean dispatchKeyEvent(KeyEvent event) {
            if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
                //do staff here
                // and return True!
                return true;
            }
            return super.dispatchKeyEvent(event);
        }
    }

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-05
      • 1970-01-01
      • 1970-01-01
      • 2018-08-27
      相关资源
      最近更新 更多