How Android implements the global eye protection mode

        Recently, I received a request for an eye protection mode. The requirement is that it can be used globally in Android, that is, it can be used in any scene. After consulting the information, I thought about the method of covering it with a light yellow transparent mask. It is required that this mask does not affect the normal use of the application below it.

        If you directly open a mask activity in the application, then exit the activity or close the application, the eye protection mode will be turned off, obviously this does not meet our requirements, so we can open a service, and then add in this service this mask. It can be realized that all our global operations are under the eye protection mode.

The following is a service that turns on eye protection mode:

public class EyeCareService extends Service {
    private WindowManager windowManager;
    private FrameLayout coverLayout;

    @Override
    public void onCreate() {
        super.onCreate();
        windowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
        WindowManager.LayoutParams params = new WindowManager.LayoutParams();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            params.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY |
                    WindowManager.LayoutParams.TYPE_STATUS_BAR;
        } else {
            params.type = WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
        }
       params.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL |
                WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE |
                WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS |
                WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN |
                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
        params.format = PixelFormat.TRANSLUCENT;

        params.gravity = Gravity.START | Gravity.TOP;
        Point point = new Point();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
            windowManager.getDefaultDisplay().getRealSize(point);
        }
      params.width = point.x ;
        params.height = point.y ;
        coverLayout = new FrameLayout(this);
        coverLayout.setBackgroundColor(getFilterColor(30));
        windowManager.addView(coverLayout, params);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy() {
        windowManager.removeViewImmediate(coverLayout);

        super.onDestroy();
    }

    /**
     * 过滤蓝光
     *
     * @param blueFilterPercent 蓝光过滤比例[10-30-80]
     */
    public int getFilterColor(int blueFilterPercent) {
        int realFilter = blueFilterPercent;
        if (realFilter < 10) {
            realFilter = 10;
        } else if (realFilter > 80) {
            realFilter = 80;
        }
        int a = (int) (realFilter / 80f * 180);
        int r = (int) (200 - (realFilter / 80f) * 190);
        int g = (int) (180 - (realFilter / 80f) * 170);
        int b = (int) (60 - realFilter / 80f * 60);
        return Color.argb(a, r, g, b);
    }


    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
}

Parse:

1. Call setBackgroundColor to set the color for the mask

2. Define a method getFilterColor, pass in 30 to obtain the color temperature with a blue light filtering ratio of 30%                               

In the place where the eye protection mode needs to be turned on, call it as follows:

   /**
     * 打开护眼模式
     *
     * @return
     */
    public static void openEyeCareMode() {
        if (Build.VERSION.SDK_INT >= 23) {
            if (Settings.canDrawOverlays(mContext)) { //有悬浮窗权限开启服务绑定 绑定权限
                Intent intent = new Intent(mContext, EyeCareService.class);
                mContext.startService(intent);
            } else { //没有悬浮窗权限,去开启悬浮窗权限
                try {
                    Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
                    ((MainActivity) mContext).startActivityForResult(intent, 1234);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        } else {
            Intent intent = new Intent(mContext, EyeCareService.class);
            mContext.startService(intent);
        }

    }
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        Log.i(TAG, "openEyeCareMode onActivityResult: requestCode :" + requestCode);
        if (requestCode == 1234) {
            if (Build.VERSION.SDK_INT >= 23) {
                if (!Settings.canDrawOverlays(this)) {
                    Log.i(TAG, "openEyeCareMode: 失败");
                    //权限授予失败,无法开启悬浮窗
                    return;
                } else {
                    Log.i(TAG, "openEyeCareMode: 成功");
                    //权限授予成功
                }//有悬浮窗权限开启服务绑定 绑定权限
            }
            Intent intent = new Intent(this, EyeCareService.class);
            startService(intent);
        } else if (requestCode == 10) {
            if (Build.VERSION.SDK_INT >= 23) {
                if (!Settings.canDrawOverlays(this)) {
                    Toast.makeText(mContext, "not granted", Toast.LENGTH_SHORT);
                }
            }
        }
    }

Parse:

1. If the Android version is higher than 6.0, then you need to dynamically apply for the permission of the floating window, otherwise open it directly

2. Define a method getFilterColor, pass in 30 to obtain the color temperature with a blue light filtering ratio of 30% 

3. If you need to dynamically apply for permissions, enable the eye protection mode service in onActivityResult()

        The above is the idea and specific method of realizing the eye protection mode. The next step is to consider some methods of keeping the service alive to prevent the eye protection mode from hanging up during use. These keeping alive methods can be studied by yourself.

Complete demo code: GitHub - Aman121314/EyesCare

Guess you like

Origin blog.csdn.net/weixin_42433094/article/details/119137569