Android开发小技巧-屏幕常亮与高亮的管理

2,301 阅读4分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第15天,点击查看活动详情

前言

在使用我们国民应用微信和支付宝的时候,打开付款码给别人扫码的时候,那个页面简直亮瞎我的眼,做为一个Android开发者,我就想这个功能是怎么实现的呢?

问题:如何实现屏幕的常量与亮度控制呢?又有哪些方式来实现呢?

一、WakeLock机制

说起应用程序App的耗电,其本质就是硬件的消耗电量,硬件耗电单元分为CPU、基带、GPU、WIFI、BT、GPS、LCD/OLED等等。

耗电量的层级 基带非通话时间的能耗基本上在 5mA 左右, 而CPU只要处于非休眠状态,能耗至少在 50mA 以上,GPU执行图形运算时会更高, 另外 LCD/OLED, GPS等硬件又更高。

一般手机待机时,CPU、LCD、WIFI均进入休眠状态,这时 Android 中应用程序的代码也会停止执行,只会有基带处理器的耗电。 这也就是为什么微信比短信相比更加的耗电,答案就是短信使用基带耗电小, 而微信使用CUP耗电大。

Android 为了确保应用程序中关键代码的正确执行,提供了 WakeLock 的API,使得应用程序有权限通过代码阻止CPU进入休眠状态。

WakeLock 阻止应用处理器 CPU 的挂起,确保关键代码的运行,通过中断唤起应用处理器 CPU,可以阻止屏幕变暗。所有的 WakeLock 被释放后,系统会挂起。

例如以下音乐播放器,我们申请了 WakeLock 的情况下,就算按下电源键锁屏了,我们的音乐还是会播放。CPU不会休眠照样会处理我们的应用。

但是如果我们不释放 WakeLock,或者滥用 WakeLock 就会导致电池续航尿崩,用户查看电池消耗查看你的 App 耗电量高就会卸载了。

除了阻止 CPU 休眠,WakeLock 还可以让屏幕常亮,通过设置对应的 levelAndFlags 即可实现,常用的几个levelAndFlags:

  • PARTIAL_WAKE_LOCK:保持CPU 运转,屏幕和键盘灯有可能是关闭的。
  • SCREEN_DIM_WAKE_LOCK:保持CPU 运转,允许保持屏幕显示但有可能是灰的,允许关闭键盘灯
  • SCREEN_BRIGHT_WAKE_LOCK:保持CPU 运转,保持屏幕高亮显示,允许关闭键盘灯
  • FULL_WAKE_LOCK:保持CPU 运转,保持屏幕高亮显示,键盘灯也保持亮度
  • ACQUIRE_CAUSES_WAKEUP:不会唤醒设备,强制屏幕马上高亮显示,键盘灯开启。有一个例外,如果有notification弹出的话,会唤醒设备。
  • ON_AFTER_RELEASE:WakeLock 被释放后,维持屏幕亮度一小段时间,减少 WakeLock 循环时的闪烁情况

怎么使用呢?先声明权限

    <uses-permission android:name="android.permission.WAKE_LOCK"/>

然后直接使用:

    override fun init() {
        val powerManager = commContext().getSystemService(Service.POWER_SERVICE) as PowerManager
        wakeLock = powerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK, "My Lock")

       //是否需计算锁的数量
        wakeLock.setReferenceCounted(false)

    }

    override fun onResume() {
        super.onResume()
        wakeLock.acquire()

    }

    override fun onStop() {
        super.onStop()
        wakeLock.release();
    }

这样就可以实现一个简单的屏幕常亮的控制了。

虽然是可以实现逻辑,但是按照上面说的,谷歌可能也是怕我们滥用,导致手机续航尿崩,然后甩锅到Android系列上,说Android系列辣椒续航不行什么什么的,谷歌老早就标记过时了,并提供了新的 Api 实现此功能 SCREEN_ON。

二、KEEP_SCREEN_ON

有两种方式设置,一种是xml内部设置,另一种是通过Activity的window添加flag来设置

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/white"
        android:keepScreenOn="true"
        android:orientation="vertical"/>
 

或者oncreate方法中添加flags

    override fun init() {
        window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
    }

两种方法都能实现,并且是和Activity生命周期绑定的,当我们退出这个页面就可以退出常量的状态,使用起来也是非常的方便。

那如果是这样一样场景,比如我们使用单Activity+多Fragment的方式,我们需要为其中一个Fragment设置为常亮,切换Fragment的时候动态的切换亮度,那怎么办?

我们需要动态的开关这个flag

window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

又或者找到跟视图动态设置keepScreenOn属性 setKeepScreenOn 也是可行的,下面我们会以window的方式做一个工具封装类。

二、最大亮度的设置

最大亮度可以通过当前 Activity 的 window 对象设置 windowLayoutParams ,设置对应的 screenBrightness 值即可实现。

我们可以实现一个工具类来控制常亮的开关和最大亮度的开关,特别适用于单Activity+多Fragment的使用场景。

public class ScreenUtils {

    /**
     * 获取屏幕宽度
     */
    public static int getScreenWidth(Context context) {
        WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        int width = wm.getDefaultDisplay().getWidth();
        return width;
    }


    /**
     * 获取屏幕高度
     */
    public static int getScreenHeith(Context context) {
        WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        int height = wm.getDefaultDisplay().getHeight();
        return height;
    }


    /**
     * 是否使屏幕常亮
     *
     * @param activity 当前的页面的Activity
     */
    public static void keepScreenLongLight(Activity activity, boolean isOpenLight, boolean maxBrightness) {

        Window window = activity.getWindow();
        if (isOpenLight) {
            window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        } else {
            window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        }

        WindowManager.LayoutParams windowLayoutParams = window.getAttributes();
        windowLayoutParams.screenBrightness = maxBrightness ?
                WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_FULL : WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_NONE;
        window.setAttributes(windowLayoutParams);
    }
}

使用的时候在页面显示的时候常亮且最大亮度即可,然后我们可以在任意地方关闭这些设置。

    override fun onResume() {
        super.onResume()

        ScreenUtils.keepScreenLongLight(this, true, true)
    }


    override fun onStop() {
        super.onStop()

        ScreenUtils.keepScreenLongLight(this, false, false)
    }

最大亮度打开页面简直亮瞎我的眼!

OK,完结!