概述:
不少健康管理类的app都有护眼模式的功能,在以往做过的项目中也曾经做过护眼模式功能的开发,当时参考和总结了市面上部分护眼类app的实现,顺便利用自身OS厂商可给与系统权限的优势实现了护眼模式,现简单记录如下。
实现原理
android自7.0之后提供了一个夜间模式的功能,只是该功能不是所有设备都默认开启,需要依赖硬件条件,所以不是所有7.0以上的设备都支持该功能,如果当前设备支持夜间模式,那开启护眼模式就等同于开启夜间模式,如果在不支持夜间模式的设备上,开启护眼模式,则通过添加一层蒙版的方式来实现护眼模式。
实现过程
1.权限支持:
如果不支持夜间模式,则使用蒙版需要有浮窗权限支持,先检查是否拥有该权限,如果没有,则弹窗提示,点击跳转到开启浮窗权限的页面去。
//检查是否拥有浮窗权限
public static boolean checkAllowAlert(Context cn) {
try {
AppOpsManager appOpsManager = (AppOpsManager) cn.getSystemService(Context.APP_OPS_SERVICE);
PackageManager pm = cn.getPackageManager();
ApplicationInfo info = pm.getApplicationInfo(cn.getPackageName(),PackageManager.GET_UNINSTALLED_PACKAGES);
int uid = info.uid;
int alertMode = appOpsManager.checkOp(AppOpsManager.OPSTR_SYSTEM_ALERT_WINDOW,uid, cn.getPackageName());
LogUtil.d("EyeModeActivity:","alertMode:" + alertMode);
if(alertMode == AppOpsManager.MODE_ALLOWED || alertMode == AppOpsManager.MODE_DEFAULT) {
return true;
}
} catch (Exception e) {
LogUtil.d(TAG,"check alert permission fail:" + e.getMessage());
}
return false;
}
跳转到开启浮窗权限的页面
Intent intent = new Intent("android.settings.action.MANAGE_OVERLAY_PERMISSION");
intent.setData(Uri.parse("package:" + getPackageName()));
startActivity(intent);
因夜间模式的开启关闭涉及到系统数据库的操作所以还需要申请以下系统权限:
<!-- 开启夜间模式所需权限-->
<uses-permission android:name="android.permission.INTERACT_ACROSS_USERS"/>
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS"/>
<uses-permission android:name="android.permission.MANAGE_USERS"/>
2.支持夜间模式的情况
首先需要确认该设备是否支持夜间模式,这个可从系统配置文件中查找:
\frameworks\base\core\res\res\values\config.xml
<!-- Control whether Night display is available. This should only be enabled on devices
with HWC 2.0 or higher. -->
<bool name="config_nightDisplayAvailable">false</bool>
/**是否支持夜间模式
* 返回true支持,返回不支持
*/
private boolean isNightModeSupport() {
Resources res = getResources();
int allowId = res.getIdentifier("config_nightDisplayAvailable","bool","android");
return res.getBoolean(allowId);
}
开启或者关闭夜间模式,这里有点差异,主要是控制类在不同android版本上不同,参数open为true,则开启夜间模式,为false,则关闭夜间模式。
private void openOrCloseNightMode(boolean open) {
try {
Class cl;
if(Build.VERSION.SDK_INT > 27) {
cl = Class.forName("com.android.internal.app.ColorDisplayController");
} else {
cl = Class.forName("com.android.internal.app.NightDisplayController")