链接:http://developer.android.com/reference/android/provider/Settings.System.html
最近在做的项目,需要使用亮度调节实现夜间模式,需求是进入 App之后,保持屏幕亮度不变,如果点下亮度切换按钮,就能在两种亮度值之间切换。此外,如果 App被切换到后台,或者锁屏,都需要还原回原始系统亮度。
一开始想的比较简单,以为用 Settings.System的设置就可以实现,动手写代码之后,才发现有以下几个问题需要处理:
1. 在 App入口不唯一的情况下(通过Widget、Notification,第一次进入的不是同一个界面),如何取到系统亮度的初始值,用于还原操作;
2. 怎么判断 App被切换到了后台;
3. 监听锁屏事件;
4. 光改变系统亮度值,不改变 Activity所占有的 Window亮度,是不会有作用的。
解决方法:
1. 使用单例模式,保证使用亮度调节之前,都对原始系统亮度值进行过保存,以下是获取系统亮度值的代码
private static void initBrightnessSetting() { int brightness = 200; int mode = 0; try { brightness = Settings.System.getInt(sContext.getContentResolver(), Settings.System.SCREEN_BRIGHTNESS); } catch (SettingNotFoundException e) { e.printStackTrace(); } try { mode = Settings.System.getInt(sContext.getContentResolver(), Settings.System.SCREEN_BRIGHTNESS_MODE); } catch (SettingNotFoundException e) { e.printStackTrace(); } sOriginalBrightness = brightness; sOriginalMode = mode; }
2. 有两种方法,第一种是在每个 Activity执行 onPause回调的时候获取当前的 Android任务列表,第二种是在 App中建立一个 Stack/List存储每个 Activity的状态(代码略,只需要在最后一个执行 onPause的 Activity中对标志位进行重置即可)。推荐后者。
public static boolean isBackground() { boolean isBackground = true; List<RunningTaskInfo> taskInfo = getRunningTaskInfos(1); if (taskInfo.size() > 0) { if (taskInfo.get(0).baseActivity.getPackageName().equals( SinaNewsApplication.getAppPackageName())) { isBackground = false; Logger.TEST.info(taskInfo.get(0).baseActivity.getClassName()); } } return isBackground; }
3. 原先我一直认为 Android没有一个好的监听锁屏方法,只能使用监听 Intent.ACTION_SCREEN_OFF的方法,这次做亮度调节的时候,才发现一个事实..锁屏 == 亮度为零。不知道为什么,采用静态注册的方法不能监听到 ACTION_SCREEN_OFF的广播,必须要在某个组件里动态注册监听器。怎么判断是哪个 Activity的 Window对象来改变亮度呢?就需要用到第二个问题中的 Activity Stack,把栈顶的 Activity拿出来就可以了。
4. 很多博客写到系统亮度调节,都会说这么做就可以了:
Settings.System.putInt(sContext.getContentResolver(),
Settings.System.SCREEN_BRIGHTNESS_MODE, systemMode);
Settings.System.putInt(sContext.getContentResolver(),
Settings.System.SCREEN_BRIGHTNESS, systemBrightness);
这么做确实能改变系统的亮度值,但是你会发现亮度值变了,屏幕还是原来的亮度,这是因为系统的亮度值并没有应用到当前 Activity的 Window对象,所以还需要:
Window window = activity.getWindow(); WindowManager.LayoutParams lp = window.getAttributes(); lp.screenBrightness = brightness; window.setAttributes(lp);
如果先启动了 Activity A设置了一次亮度200,然后跳转到 Activity B又做了一次同样的操作设置亮度50,退出 B之后,发现 A的亮度还是200。出现这种现象的原因就是,处于后台的 Activity的 Window的亮度值在设置后,并不会随着它之上的 Activity的 Window亮度所更改。所以还需要在每个 Activity的 onResume方法中进行判断。