记得之前看小说,下了一个夜间模式用用,居然一大堆的广告,用的太不爽了,于是自己写一个用。其实原理很简单,就是添加一个带有黑色透明的悬浮窗而已。
说下实现步骤:
1、添加悬浮窗,需要用到WindowManager对象
2、如果要保证我们退出程序,也要保证夜间模式还是启动的状态,那么就需要用到Service
3、为了保证Service不被系统杀死,所以准备使用前台服务
看下服务类的代码
public class NightModeService extends Service {
private LinearLayout mNightView;
private LocalBinder mBind = new LocalBinder();
public boolean isRunning = true;
@Override
public void onCreate() {
super.onCreate();
// 保护眼睛模式的核心代码
WindowManager localWindowManager = (WindowManager) getApplication().getSystemService("window");
WindowManager.LayoutParams localLayoutParams = new WindowManager.LayoutParams();
this.mNightView = new LinearLayout(getApplicationContext());
//不让悬浮窗获取焦点
this.mNightView.setFocusable(false);
this.mNightView.setFocusableInTouchMode(false);
// this.mNightView.setBackgroundColor(Color.argb(153, 0, 8, 13));
localLayoutParams.type = LayoutParams.TYPE_SYSTEM_OVERLAY;
localLayoutParams.flags = LayoutParams.FLAG_LAYOUT_IN_SCREEN;
//支持透明度
localLayoutParams.format = PixelFormat.RGBA_8888;
localLayoutParams.gravity = Gravity.CENTER;
localLayoutParams.x = 0;
localLayoutParams.y = 0;
localLayoutParams.width = LayoutParams.MATCH_PARENT;
localLayoutParams.height = LayoutParams.MATCH_PARENT;
localWindowManager.addView(this.mNightView, localLayoutParams);
// 将service作为前台服务
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
Notification notification = new Notification(R.drawable.ic_launcher, "夜间模式", System.currentTimeMillis());
Intent intent = new Intent(this, MainActivity.class);
PendingIntent pIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
notification.setLatestEventInfo(this, "夜间模式", "开启", pIntent);
notification.flags = Notification.FLAG_ONGOING_EVENT;// 常驻状态栏
startForeground(1, notification);
}
@Override
public IBinder onBind(Intent intent) {
return mBind;
}
public class LocalBinder extends Binder {
public NightModeService getService() {
return NightModeService.this;
}
}
public void setWindowColor(int color) {
this.mNightView.setBackgroundColor(color);
}
@Override
public void onDestroy() {
super.onDestroy();
WindowManager localWindowManager = (WindowManager) getApplication().getSystemService("window");
localWindowManager.removeView(mNightView);
}
}
首先我们通过Context.getSystemService()方法获取WindowManager对象,
然后我们创建mNightView,别切设置他的焦点和LayoutParams属性,再通过WindowManager的addView()方法将我们创建的mNightView,添加进去,最后将Service通过startForeground()设为前台,保证不被系统杀死。
Activity中没有什么特别的方法,只是我继承了PreferenceActivity,可能这个Activity大家不是很熟悉,其实也没什么,很简单,找点资料就能解决,那就挑重点的说下吧。
判断当前的夜间模式有没有开启
public static boolean isServiceRunning(Context mContext, String className) {
boolean isRunning = false;
ActivityManager activityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningServiceInfo> serviceList = activityManager.getRunningServices(30);
if (!(serviceList.size() > 0)) {
return false;
}
for (int i = 0; i < serviceList.size(); i++) {
if (serviceList.get(i).service.getClassName().equals(className) == true) {
isRunning = true;
break;
}
}
return isRunning;
}
这个其实是判断当前的Service是不是已经开启了,Service开启的话,那么这个夜间模式就是开启状态,后来想了一下,当时让我想复杂了,其实在只要在Service添加一个标记值就搞定了,不过我们可以学下一下这个方法,说不定以后还有用处。
这个方法也是获取到系统的服务ActivityManager,获取里面所有的服务,进行比对,就可以知道当前的服务是否在运行。
最后添加了一个颜色选择器,[ColorPickerPreference]] (https://github.com/attenzione/android-ColorPickerPreference)
看效果图:
对了,小米手机许设置允许悬浮窗的权限,要不然看不到效果。