使用系统警报窗口按下事件

时间:2015-06-16 07:15:03

标签: android back-button android-homebutton

我需要在back按下home按钮事件时关闭系统警报窗口。我已尝试使用onKeyEvent,但徒劳无功。由于我们无法捕获服务中的back按下事件,如何实现此目标?

10 个答案:

答案 0 :(得分:5)

由于它是托管覆盖窗口的服务,因此它有点棘手,但有可能。

您应该分别处理这两种情况(按住主页按钮,按下后退按钮)。

<强> 1。覆盖主页按钮:

创建此HomeWatcher类,其中包含将在按下主页按钮时通知的BroadcastReceiver。只有在窗口出现时才注册此接收器。

Android: associate a method to home button of smartphone

在您的服务onCreate方法中使用此:

HomeWatcher mHomeWatcher = new HomeWatcher(this);
mHomeWatcher.setOnHomePressedListener(new OnHomePressedListener() {
    @Override
    public void onHomePressed() {
        yourWindow.hide()  //means: windowManager.removeView(view);
    }
    @Override
    public void onHomeLongPressed() {
    }
});
mHomeWatcher.startWatch();

<强> 2。按下后退按钮:

这个想法是创建一个空布局作为窗口类的数据成员, 并将您的视图附加到它(即使它是一个膨胀的XML布局)。

例如,这将是你的窗口类:

public class MyWindow
{
    private WindowManager windowManager;
    private WindowManager.LayoutParams params;
    private View view;

    // Add this empty layout:
    private MyLayout myLayout;

    public MyWindow()
    {
        windowManager = (WindowManager) context.getSystemService(context.WINDOW_SERVICE);
        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        view = inflater.inflate(R.layout.your_original_window_layout, null);

        // Add your original view to the new empty layout:
        myLayout = new MyLayout(this);
        myLayout.addView(view, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
    }

    // And show this layout instead of your original view:
    public void show()
    {
        windowManager.addView(myLayout, params);
    }

    public void hide()
    {
        windowManager.removeView(myLayout);
    }
}

现在创建MyLayout类以覆盖后退按钮:

public class MyLayout extends LinearLayout
{
    private MyWindow myWindow;

    public MyLayout(MyWindow myWindow)
    {
        super(myWindow.context);

        this.myWindow = myWindow;
    }


    @Override public boolean dispatchKeyEvent(KeyEvent event)
    {
        if (event.getKeyCode() == KeyEvent.KEYCODE_BACK)
        {
            if (event.getAction() == KeyEvent.ACTION_DOWN  &&  event.getRepeatCount() == 0)
            {
                getKeyDispatcherState().startTracking(event, this);
                return true;

            }

            else if (event.getAction() == KeyEvent.ACTION_UP)
            {
                getKeyDispatcherState().handleUpEvent(event);

                if (event.isTracking() && !event.isCanceled())
                {
                    // dismiss your window:
                    myWindow.hide();

                    return true;
                }
            }
        }

        return super.dispatchKeyEvent(event);
    }
}

我知道它有点复杂,因为它是由服务托管的系统警报窗口,但它正在工作。我也有同样的问题,它已经完全解决了。 祝你好运。

答案 1 :(得分:1)

使用以下方法处理按下后退按钮。

and

答案 2 :(得分:1)

您需要覆盖onBackPressed方法。

@Override
public void onBackPressed() {

    super.onBackPressed(); // remove this if u want to handle this event
}

答案 3 :(得分:0)

使用以下代码

public boolean onKeyDown(int keyCode, KeyEvent event) {
    if (keyCode == KeyEvent.KEYCODE_BACK) {
        exitByBackKey();

        //moveTaskToBack(false);

        return true;
    }
    return super.onKeyDown(keyCode, event);
    }

    protected void exitByBackKey() {

    AlertDialog alertbox = new AlertDialog.Builder(this)
    .setMessage("Do you want to exit application?")
    .setPositiveButton("Yes", new DialogInterface.OnClickListener() {

        // do something when the button is clicked
        public void onClick(DialogInterface arg0, int arg1) {

            finish();
            //close();


        }
    })
    .setNegativeButton("No", new DialogInterface.OnClickListener() {

        // do something when the button is clicked
        public void onClick(DialogInterface arg0, int arg1) {
                       }
    })
      .show();

    }

答案 4 :(得分:0)

@Override
public void onBackPressed()
{
       super.onBackPressed();
}

在您的活动中声明此信息。 super.OnBackPressed在android中自动回调方法。它肯定会取消你的对话。

此外,您的对话框必须如下所示。

AlertDialog.Builder builder = new AlertDialog.Builder(this);
    builder1.setMessage("TEST DIALOG.\n");
    builder1.setPositiveButton("Ok",
            new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int id) {
                Toast.makeText(MainActivity.this, "This Is test Dialog", Toast.LENGTH_SHORT).show();
        }
    });
    AlertDialog alert11 = builder1.create();
    alert11.show();

或者您可以设置“否定”按钮..

希望这有帮助!

答案 5 :(得分:0)

定义自定义布局并覆盖dispatchKeyEvent,例如:

public class CustomSystemAlertWindow extends FrameLayout {

    public static final String TAG = "CustomSystemAlertWindow";

    private WeakReference<Context> mContext;

    public CustomSystemAlertWindow(Context context) {
        super(context);

        mContext = new WeakReference<Context>(context);

        // Set a background color to identify the view on the screen
        this.setBackgroundColor(getResources().getColor(android.R.color.holo_red_light));
    }

    @Override
    public boolean dispatchKeyEvent(KeyEvent event) {
        if (event != null && event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
            Log.d(TAG, "back button pressed");

            if (mContext != null && mContext.get() != null) {
                WindowManager wm = (WindowManager) mContext.get().getSystemService(Context.WINDOW_SERVICE);
                wm.removeView(this);
            }

            return true;
        }

        return super.dispatchKeyEvent(event);
    }
}

然后使用以下代码添加视图:

CustomSystemAlertWindow customSystemAlertWindow = new CustomSystemAlertWindow(context);

WindowManager.LayoutParams params = new WindowManager.LayoutParams(
        WindowManager.LayoutParams.MATCH_PARENT,
        WindowManager.LayoutParams.MATCH_PARENT,
        WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
        WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN,
        PixelFormat.TRANSLUCENT);

WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
wm.addView(customSystemAlertWindow, params);

当您按后退按钮时,视图将被解除。

答案 6 :(得分:0)

  1. 通过“活动”显示“提醒”窗口,以便您可以检测到它。
  2. 实施代码以轻松检测后退按钮或主页按钮。

    public class alertPopup extends Activity {
    
        Context context;
        final AlertDialog alertDialog;
        String TAG = "your Activity Name"
        boolean homePressed = false; // to detect the Homebutton pressed
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
         AlertDialog.Builder builder = newAlertDialog.Builder(YourActivity.this, R.style.AppCompatAlertDialogStyle);
         builder.setTitle("AlertDialog Title");
                ..........
                ....... // Build ur AlertDialog
    
         alertDialog= builder.create();
         alertDialog.show();
    
    
             //to detect Alert Dialog cancel when user touches outside the Dialog prompt
         alertDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
                @Override
                public void onCancel(DialogInterface dialog) {
                    Log.v(TAG,"Alert Dialog cancelled when user touches outside the Dialog prompt")
                }
            });
    
        }
    
    
        @Override
        public void onBackPressed()
        {
        Log.v(TAG,"Back Button Pressed");
         super.onBackPressed();
    
         alertDialog.dismiss();   //dismiss the alertDialog
         alertPopup.this.finish();  // Destroy the current activity
    
         homePressed = false;
        }
    
        @Override
        public void onResume() {
            super.onResume();
            homePressed = true; // default: other wise onBackPressed will set it to false
        }
    
    
        @Override
        public void onPause() {
            super.onPause();
            if(homePressed) { 
    
            alertDialog.dismiss();   //dismiss the alertDialog
            alertPopup.this.finish();  // Destroy the current activity
    
            Log.v(TAG, "Home Button Pressed"); }
        }
    
    
        public void onDestroy(){
    
            super.onDestroy();
        }
    
    
    }
    

    注意:

    在Android Manifest中添加此权限以显示警告窗口。

     <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
    

    快乐编码:)

答案 7 :(得分:0)

我了解您使用<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />权限来显示浮动视图。

使用浮动视图,您可以截取back按钮,但无法截取home按钮(由于安全原因,Android不会主要让您使用)。

要拦截back按钮,您需要在浮动视图时添加包装器。 您的包装器应如下所示:

    // Wrapper for intercepting System/Hardware key events
    ViewGroup wrapper = new FrameLayout(this) {
        @Override
        public boolean dispatchKeyEvent(KeyEvent event) {
            if (event.getKeyCode()==KeyEvent.KEYCODE_BACK) {
                hideAddNotesFloatingView();
                return true;
            }
            return super.dispatchKeyEvent(event);
        }
    };

然后将其作为根添加到浮动视图中:

        mAddNoteFloatingView = mInflater.inflate(R.layout.floating_add_note, wrapper);

我的完整代码如下所示:

private void addFloatingView() {
    final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
            WindowManager.LayoutParams.MATCH_PARENT,
            WindowManager.LayoutParams.MATCH_PARENT,
            WindowManager.LayoutParams.TYPE_PHONE,
            0,
            PixelFormat.TRANSLUCENT);

    params.gravity = Gravity.CENTER | Gravity.LEFT;
    params.x = 0;
    params.y = 0;

    // Wrapper for intercepting System/Hardware key events
    FrameLayout wrapper = new FrameLayout(this) {
        @Override
        public boolean dispatchKeyEvent(KeyEvent event) {
            if (event.getKeyCode()==KeyEvent.KEYCODE_BACK) {
                // Add your code for handling the back button press
                return true; // Return true means that the event was handled
            }
            return super.dispatchKeyEvent(event);
        }
    };

    mAddNoteFloatingView = mInflater.inflate(R.layout.floating_view, wrapper);

    mWindowManager.addView(mAddNoteFloatingView, params);
}

答案 8 :(得分:0)

很简单。请按照以下步骤操作:

  1. 动态创建相对布局,线性布局或框架布局等视图。 2.在创建视图时覆盖dispatchKeyEvent
  2. 使用addView()方法将原始视图添加到此动态创建的视图中。
  3. 将动态创建的视图添加到窗口管理器或警报对话框中,无论您想要哪个。

答案 9 :(得分:0)

除了@Eliran Kuta的解决方案之外,这是“返回”按钮的更简单答案。

val view = getAlertView()
val windowParam = WindowManager.LayoutParams(
    WindowManager.LayoutParams.WRAP_CONTENT, // whatever
    WindowManager.LayoutParams.WRAP_CONTENT, // whatever
    WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY, // use WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY before Oreo
    WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL, // whatever
    PixelFormat.TRANSLUCENT // whatever
)

view.isFocusableInTouchMode = true
view.setOnKeyListener { view, keyCode, event ->
    when (keyCode) {
        KeyEvent.KEYCODE_BACK -> {
            // do your work here
            true
        }
        else -> false
    }
}

val windowManager = getSystemService(Context.WINDOW_SERVICE) as WindowManager
windowManager.addView(view, windowParam)