技术小黑屋

Android 添加 Overlay View (覆盖视图)

在 Android 中,有一种黑科技,就是能够过在 Window 上添加一个视图,然后这个视图,会覆盖在所有的 应用视图的上面(包括桌面)。比如下面的视图。

https://asset.droidyue.com/image/2022/h1/android_overlay_view_sample.png

想要利用上面的黑科技,很简单。大概分为如下的步骤。

检测权限

  • Settings.canDrawOverlays(aContext) 可以检测 当前的 App 是否可以添加悬浮窗视图。
  • 如果返回为true,则表明已经获取了添加悬浮视图的权限。
  • 如果返回为false,则需要按照下方的内容获取权限。

获取权限

SYSTEM_ALERT_WINDOW,设置悬浮窗权限,是 Android 中一个比较特殊的权限。

关于获取权限,可以使用下面的代码处理。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

private static final int REQUEST_CODE = 1;
private  void requestAlertWindowPermission() {
    Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
    intent.setData(Uri.parse("package:" + getPackageName()));
    startActivityForResult(intent, REQUEST_CODE);
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == REQUEST_CODE) {
        if (Settings.canDrawOverlays(this)) {
          Log.i(LOGTAG, "onActivityResult granted");
        }
    }
}

添加悬浮窗视图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
fun addOverlay() {
    val windowManager = getSystemService(Context.WINDOW_SERVICE) as? WindowManager
    val params = WindowManager.LayoutParams()
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        //8.0新特性
        params.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
    } else {
        params.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
    }

    params.format = PixelFormat.RGBA_8888;
    //设置flags
    //设置flags
    params.flags =
        (WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL //设置flags.不可聚焦及不可使用按钮对悬浮窗进行操控.
                or WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                or WindowManager.LayoutParams.FLAG_FULLSCREEN //窗口被虚拟按键遮挡问题
                or WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION)
    //设置flags.不可聚焦及不可使用按钮对悬浮窗进行操控.
    //设置窗口坐标参考系
    //设置flags.不可聚焦及不可使用按钮对悬浮窗进行操控.
    //设置窗口坐标参考系
    params.gravity = Gravity.LEFT or Gravity.TOP
    params.x = 0
    params.y = 0
    params.width = 200
    params.height = 200
    val container = TextView(this)
    overlayContainer = container
    container.setBackgroundColor(Color.parseColor("#cce8cf"))
    windowManager?.addView(container, params)
}

完整的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
class MainActivity : AppCompatActivity() {
	var overlayContainer: TextView? = null

	@RequiresApi(Build.VERSION_CODES.M)
	override fun onCreate(savedInstanceState: Bundle?) {
    	super.onCreate(savedInstanceState)
    	setContentView(R.layout.activity_main)
    	if (Settings.canDrawOverlays(this)) {
        	addOverlay()
    	} else {
        	val intent = Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION)
        	intent.data = Uri.parse("package:$packageName")
        	startActivity(intent)
    	}
    	
    	findViewById<View>(R.id.textview_hello).setOnClickListener {
        	overlayContainer?.text = "${System.currentTimeMillis()}"
    	}
}

	fun addOverlay() {
    	val windowManager = getSystemService(Context.WINDOW_SERVICE) as? WindowManager
    	val params = WindowManager.LayoutParams()
    	if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        	//8.0新特性
        	params.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
    	} else {
        	params.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
    	}

    	params.format = PixelFormat.RGBA_8888;
    	//设置flags
    	//设置flags
    	params.flags =
        	(WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL //设置flags.不可聚焦及不可使用按钮对悬浮窗进行操控.
                or WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                or WindowManager.LayoutParams.FLAG_FULLSCREEN //窗口被虚拟按键遮挡问题
                or WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION)
	    //设置flags.不可聚焦及不可使用按钮对悬浮窗进行操控.
	    //设置窗口坐标参考系
	    //设置flags.不可聚焦及不可使用按钮对悬浮窗进行操控.
	    //设置窗口坐标参考系
	    params.gravity = Gravity.LEFT or Gravity.TOP
	    params.x = 0
	    params.y = 0
	    params.width = 200
	    params.height = 200
	    val container = TextView(this)
	    overlayContainer = container
	    container.setBackgroundColor(Color.parseColor("#cce8cf"))
	    windowManager?.addView(container, params)
	}
}

以上。





快来解锁最新版 Typora,新用户券后仅需 84 元!
如何便宜的购买 office 365 ?
新版赤友 NTFS 助手来袭,正版超低价

Visit Vultr cloud hosting