? ? ? ? 最近接到一个做护眼模式的需求,要求是在Android全局,即在任何场景都可使用,查阅资料,思考到可以用一个淡黄色的透明遮罩盖在上面的方法。要求这个遮罩不影响其下面的应用等正常的使用。
? ? ? ? 如果直接在应用中开启一个蒙层activity,那么退出这个activity或者关闭应用,护眼模式就会被关闭,显然这是不符合我们的要求的,所以我们可以开启一个服务,然后在这个服务中添加这个遮罩。即可实现我们的所有全局操作都在护眼模式之下了。
以下是开启护眼模式的一个服务:
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;
}
}
解析:
1.调用setBackgroundColor给遮罩设置颜色
2.定义一个方法getFilterColor,传入30获取蓝光过滤比例为百分之30的色温? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
在需要开启护眼模式的地方如下调用:
/**
* 打开护眼模式
*
* @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);
}
}
}
}
解析:
1.如果Android版本高于6.0,那么需要动态申请悬浮窗权限,否则直接开启
2.定义一个方法getFilterColor,传入30获取蓝光过滤比例为百分之30的色温?
3.如果需要动态申请权限,则在onActivityResult()中将该护眼模式服务开启
? ? ? ? 以上就是实现护眼模式的思路和实现具体方法,接下来就是要考虑一些服务保活的方法,避免护眼模式在使用过程中挂掉了,这些保活方法可自行研究。
|