Android悬浮窗来电

引言

在Android应用开发中,悬浮窗(Floating Window)是一种常见的用户界面设计模式。它可以在应用界面之上显示一个可移动的窗口,提供额外的功能或信息展示。本文将介绍如何使用Android悬浮窗来实现来电提醒功能,并提供相应的代码示例。

悬浮窗来电的实现

悬浮窗来电的实现主要分为以下几个步骤:

  1. 获取来电信息
  2. 创建悬浮窗布局
  3. 显示悬浮窗
  4. 悬浮窗交互处理
  5. 权限处理

1. 获取来电信息

首先,我们需要获取来电的电话号码。在Android中,可以使用TelephonyManager类来实现。下面是获取来电号码的代码示例:

TelephonyManager telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
telephonyManager.listen(new PhoneStateListener() {
    @Override
    public void onCallStateChanged(int state, String phoneNumber) {
        super.onCallStateChanged(state, phoneNumber);
        if (state == TelephonyManager.CALL_STATE_RINGING) {
            // 来电号码
            Log.d("IncomingCall", phoneNumber);
            // 显示悬浮窗
            showFloatingWindow(phoneNumber);
        }
    }
}, PhoneStateListener.LISTEN_CALL_STATE);

2. 创建悬浮窗布局

悬浮窗的布局可以使用WindowManager.LayoutParams来设置悬浮窗的参数,包括位置、大小、类型等。通常,我们可以使用FrameLayout作为悬浮窗的根布局,然后在其中添加需要显示的视图。下面是创建悬浮窗布局的代码示例:

private void createFloatingWindow(String phoneNumber) {
    WindowManager windowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
    WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams();
    layoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
    layoutParams.format = PixelFormat.TRANSLUCENT;
    layoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
            WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
    layoutParams.gravity = Gravity.TOP | Gravity.LEFT;
    layoutParams.x = 0;
    layoutParams.y = 0;
    layoutParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
    layoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT;

    LayoutInflater layoutInflater = LayoutInflater.from(this);
    View floatingWindowView = layoutInflater.inflate(R.layout.floating_window_layout, null);
    TextView phoneNumberTextView = floatingWindowView.findViewById(R.id.phone_number_text_view);
    phoneNumberTextView.setText(phoneNumber);

    windowManager.addView(floatingWindowView, layoutParams);
}

3. 显示悬浮窗

在获取到来电号码后,我们可以调用上述代码中的showFloatingWindow()方法来显示悬浮窗。在悬浮窗显示后,用户可以通过拖动、点击等操作进行交互。在悬浮窗外部点击时,我们可以通过监听MotionEvent.ACTION_OUTSIDE来关闭悬浮窗。下面是显示悬浮窗的代码示例:

private void showFloatingWindow(String phoneNumber) {
    createFloatingWindow(phoneNumber);
}

private void hideFloatingWindow() {
    WindowManager windowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
    if (floatingWindowView != null) {
        windowManager.removeView(floatingWindowView);
        floatingWindowView = null;
    }
}

4. 悬浮窗交互处理

在悬浮窗显示后,用户可以通过拖动、点击等操作进行交互。我们可以通过监听触摸事件来实现相应的交互处理。下面是拖动悬浮窗的代码示例:

private float lastX, lastY;
private int originalX, originalY;

floatingWindowView.setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                lastX = event.getRawX();
                lastY = event.getRawY();
                originalX = layoutParams.x;
                originalY = layoutParams.y;
                break;
            case MotionEvent.ACTION_MOVE:
                float offsetX = event.getRawX() - lastX;
                float offsetY = event.getRawY() - lastY;
                layoutParams.x = (int) (originalX + offsetX);
                layoutParams.y = (int) (originalY + offsetY);
                windowManager.updateViewLayout(floatingWindowView, layoutParams);
                break;
            case MotionEvent.ACTION