Android-悬浮窗口

发布于:2024-06-28 ⋅ 阅读:(50) ⋅ 点赞:(0)

在Android系统中,如果应用需要弹出一个悬浮窗口,就需要申请一项特殊权限

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

在Android O之前的系统中申请了该权限后,再给对应的window设置

WindowManager.LayoutParams params = new WindowManager.LayoutParams();
params.type = WindowManager.LayoutParams.TYPE_PHONE;

悬浮窗口就可以显示出来。

但是在Android O的系统中,google规定申请

android.permission.SYSTEM_ALERT_WINDOW
权限的应用需要给悬浮窗口设置如下type:

WindowManager.LayoutParams params = new WindowManager.LayoutParams();
params.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;

悬浮窗口才能显示出来,“TYPE_APPLICATION_OVERLAY”是重点。
如果不设置该TYPE,应用会Crash,报错如下(后面的2002表示设置的type为TYPE_PHONE):

AndroidRuntime: android.view.WindowManager$BadTokenException: Unable to add window android.view.ViewRootImpl$W@c8d1f1a -- permission denied for window type 2002

另外说一下:申请
android.permission.SYSTEM_ALERT_WINDOW
权限不能使用 requestPermissions 方法。
可以使用下面的方法:

Intent intent = new Intent(android.provider.Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
intent.setData(Uri.parse("package:" + getPackageName()));
startActivityForResult(intent, 100);

完整代码

1、添加权限

在AndroidManifest.xml中添加悬浮窗所需的权限:

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

2、请求权限(针对Android 6.0及以上)

  • 对于Android 6.0(API级别23)及以上的设备,需要运行时请求SYSTEM_ALERT_WINDOW权限。示例:
private static final int REQUEST_CODE_DRAW_OVER_OTHER_APPS_PERMISSION = 200;

// 在Activity或Fragment中请求权限
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !Settings.canDrawOverlays(this)) {
    Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
            Uri.parse("package:" + getPackageName()));
    startActivityForResult(intent, REQUEST_CODE_DRAW_OVER_OTHER_APPS_PERMISSION);
}
  • 处理权限请求的结果
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == REQUEST_CODE_DRAW_OVER_OTHER_APPS_PERMISSION) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !Settings.canDrawOverlays(this)) {
            // 权限被拒绝
            Toast.makeText(this, "Permission denied", Toast.LENGTH_SHORT).show();
        } else {
            // 权限已授予,可以显示悬浮窗
            showFloatingWindow();
        }
    }
}

3、实现悬浮窗

  • 定义悬浮窗的布局和显示逻辑:
public void showFloatingWindow() {
    // 布局参数
    WindowManager.LayoutParams params;
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        params = new WindowManager.LayoutParams(
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
                PixelFormat.TRANSLUCENT);
    } else {
        params = new WindowManager.LayoutParams(
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.TYPE_PHONE,
                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
                PixelFormat.TRANSLUCENT);
    }

    // 设置悬浮窗的位置
    params.gravity = Gravity.TOP | Gravity.START; // 例如,设置在屏幕左上角
    params.x = 100; // x坐标
    params.y = 100; // y坐标

    // 创建浮动窗口视图
    LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
    View floatingView = inflater.inflate(R.layout.floating_window_layout, null);

    // 获取WindowManager
    WindowManager windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);

    try {
        // 添加悬浮窗到WindowManager
        windowManager.addView(floatingView, params);
    } catch (Exception e) {
        e.printStackTrace();
    }
}
  • 关闭浮窗
public void removeFloatingWindow() {
    // 获取WindowManager实例
    WindowManager windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);

    // 确保floatingView是之前添加到WindowManager的那个View实例
    // 这里假设floatingView是在showFloatingWindow()方法中创建并添加的
    View floatingView = ...; // 你需要确保这指向正确的View实例

    if (floatingView != null && windowManager != null) {
        // 移除悬浮窗视图
        windowManager.removeView(floatingView);
    }
}

网站公告

今日签到

点亮在社区的每一天
去签到