功能:启动service,默认显示全屏透明的视图,整个屏幕的触摸事件全部可被全屏视图拦截,点击全屏视图后,隐藏全屏视图,显示一个像素大小的视图,屏幕触摸不受影响。
1、service中弹窗需要的权限:
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
2、service类。
// package name
import android.app.Service;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.PixelFormat;
import android.os.IBinder;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.view.WindowManager;
import android.widget.TextView;
public class BgTouchService extends Service {
private static final String TAG = BgTouchService.class.getSimpleName();
TextView touchView;
@Override
public void onCreate() {
super.onCreate();
Log.i(TAG, "onCreate");
try {
showTouchView(true);
Log.i(TAG, "showTouchView not full screen finished");
} catch (Exception e) {
Log.e(TAG, "showBgCameraWindow error=" + e.getMessage(), e);
}
}
@Override
public int onStartCommand(Intent intent, int i, int i1) {
return START_STICKY;
}
private void showTouchView(boolean needFullScreen) {
// 取得系统窗体
WindowManager windowManager = (WindowManager) getApplicationContext().getSystemService(WINDOW_SERVICE);
var isInit = false
// window no alert view
if (touchView == null) {
touchView = new TextView(getApplicationContext());
touchView.setOnClickListener(touchViewClickListener);
isInit = true
}
// 防止Navigation Bar在覆盖view的情况下上弹 | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
// hide navigation
touchView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
// touchView.setBackgroundColor(Color.BLUE);
// transparent
touchView.setAlpha(0);
// 窗体的布局样式
WindowManager.LayoutParams touchViewLayoutParams = new WindowManager.LayoutParams();
// 设置对齐的方法
touchViewLayoutParams.gravity = Gravity.TOP | Gravity.START;
if (!needFullScreen) {
// 设置显示的模式
touchViewLayoutParams.format = PixelFormat.RGBA_8888;
// 设置窗体显示类型――TYPE_SECURE_SYSTEM_OVERLAY,不可让view 监听到触摸和点击事件,可触摸布局其他区域,不影响触摸操作。
// 其他类型影响触摸传递到下层和隐藏导航栏
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
touchViewLayoutParams.type =
WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
} else {
touchViewLayoutParams.type = WindowManager.LayoutParams.TYPE_PHONE
}
// 设置窗体焦点及触摸:
// FLAG_NOT_FOCUSABLE(不能获得按键输入焦点)
touchViewLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
touchViewLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
touchViewLayoutParams.alpha = 0;
// 设置窗体宽度和高度
touchViewLayoutParams.width = 1;
touchViewLayoutParams.height = 1;
// 设置窗体显示的位置,否则在屏幕中心显示
touchViewLayoutParams.x = 1;
touchViewLayoutParams.y = 1;
} else {
// 设置显示的模式
touchViewLayoutParams.format = PixelFormat.TRANSLUCENT;
// TYPE_SYSTEM_ALERT 可让window中的view监听到触摸和点击事件,但是导航栏返回键会影响,当时无法屏蔽导航栏的触摸。
// TYPE_SYSTEM_ERROR可以盖在导航栏之上
// 所以只能在全屏时使用,点击后会退出全屏,类型改变就不会影响返回键了。
// see https://www.jianshu.com/p/ae45c84ccf79
//touchViewLayoutParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
touchViewLayoutParams.type =
WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
} else {
touchViewLayoutParams.type = WindowManager.LayoutParams.TYPE_PHONE
}
//让window占满整个手机屏幕,不留任何边界(border)
touchViewLayoutParams.flags = WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
touchViewLayoutParams.width = windowManager.getDefaultDisplay().getWidth();
touchViewLayoutParams.height = windowManager.getDefaultDisplay().getHeight();
touchViewLayoutParams.x = 0;
touchViewLayoutParams.y = 0;
}
if (isInit)
windowManager.addView(touchView, touchViewLayoutParams)
else
windowManager.updateViewLayout(touchView, touchViewLayoutParams)
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
private View.OnClickListener touchViewClickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.i(TAG, "touchViewClickListener clicked");
// make screen can touch
showTouchView(false);
//TODO do others operations
}
};
}
2021.4.19补充-------------------------------------------------------------
3、调用方法,在activity中调用:
private void startBgTouchService() {
//当AndroidSDK>=23及Android版本6.0及以上时,需要获取OVERLAY_PERMISSION.
//使用canDrawOverlays用于检查,下面为其源码。其中也提醒了需要在manifest文件中添加权限.
if (Build.VERSION.SDK_INT >= 23) {
if (Settings.canDrawOverlays(this)) {
Intent intent = new Intent(this, BgTouchService.class);
// Toast.makeText(this,"已开启悬浮窗权限", Toast.LENGTH_SHORT).show()
startService(intent);
} else {
//若没有权限,提示获取.
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
Toast.makeText(this, "需要取得权限以使用悬浮窗", Toast.LENGTH_SHORT).show();
startActivity(intent);
}
} else {
//SDK在23以下,不用管.
Intent intent = new Intent(this, BgTouchService.class);
startService(intent);
}
}