安卓service启动全屏View或不可点击的1像素大小View。

功能:启动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);
        }
    }

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值