如何在安卓设备上检测屏幕亮度范围?

12

我正在使用以下代码设置屏幕亮度,在大多数手机上都可以正常工作:

    protected fun setBrightness(value: Float) {
        //Set the system brightness using the brightness variable value
        Settings.System.putInt(contentResolver, Settings.System
            .SCREEN_BRIGHTNESS, (value * 255).toInt())
        //Get the current window attributes
        val layoutpars = window.getAttributes()
        //Set the brightness of this window
        layoutpars.screenBrightness = value
        //Apply attribute changes to this window
        window.setAttributes(layoutpars)
    }

当我传递一个值为1,表示最大值时,它会被转换为255,据说这是设置屏幕亮度的最大值。然而,在小米Mi8上将该值设置为255并不能将亮度设置到完整的范围,如下图所示:

enter image description here

经过输出一些调试数值并进行实验,看起来在小米Mi8上最大亮度值实际上是1024(或者至少,将1乘以该值会设置完整的亮度条)。

似乎不同的安卓设备可能有不同的亮度比例尺。是否有一些API可以获取亮度的最大值,这样我就不需要硬编码不同的常量了?


你找到了可用的解决方案吗?最终你实现了哪个解决方案? - prom85
2
我添加了一个文本框,让用户手动指定最大值。 - Grzegorz Adam Hankiewicz
谢谢,这也是我所做的(但使用了预定义值的旋转器)。您是否有任何关于存在哪些值的经验?据我所知,255、1023和3999(基于答案)确实存在。 - prom85
不清楚,但在一些小米手机上插入较高的值会抛出异常,因此我让用户输入任何值并捕获错误。 - Grzegorz Adam Hankiewicz
好的,谢谢您的反馈。 - prom85
小米Note 5 Pro的最大值为4095((2^12)-1)。 - h8pathak
4个回答

7
使用此方法获取最大亮度值。
public int getMaxBrightness(Context context, int defaultValue){

    PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
    if(powerManager != null) {
        Field[] fields = powerManager.getClass().getDeclaredFields();
        for (Field field: fields) {

            //https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/core/java/android/os/PowerManager.java

            if(field.getName().equals("BRIGHTNESS_ON")) {
                field.setAccessible(true);
                try {
                    return (int) field.get(powerManager);
                } catch (IllegalAccessException e) {
                    return defaultValue;
                }
            }
        }
    }
    return defaultValue;
}

我已经在几个设备上测试过了(大多数是安卓9、10设备,包括一些小米设备,这些设备通常将亮度设置高于通常的255),看起来这个方法可行。
Google不提倡使用反射访问隐藏的字段/方法。任何安卓更新都有可能破坏这个解决方案。
另一个可能的解决方案是使用反射访问PowerManager类中的getMaximumScreenBrightnessSetting()方法。但我还没有测试过,因此不能确认结果。
注意:如果您使用此值来设置亮度百分比,请记住:从安卓9开始,亮度是按对数 设置的。因此,设置亮度百分比可能看起来不像亮度滑块中显示的百分比(较低的百分比可能比亮度滑块上设置的值更高),但实际亮度将被正确设置。

感谢您的发现,它在POCO F2 Pro上运行得非常好!最大值为2047。 - 3c71

5

这仅适用于某些小米设备。例如,小米红米Note 7的亮度调节范围为0-4000。

官方文档将SCREEN_BRIGHTNESS范围定义为0-255。因此,我认为没有API可以获取最大亮度值。

在某些(而非所有)设备上,存在一个文件“/sys/class/leds/lcd-backlight/max_brightness”,其中包含最大值。


“/sys/class/leds/lcd-backlight/max_brightness” 这个文件在每个设备上都有吗?还是只有小米手机才有?我在我的设备上找不到它。我需要以 root 权限访问它吗? - Ton
一些设备。它没有文档,因此不可靠。它不是小米专用的。 - Smak
至少影响了一加和小米。覆盖范围不同!Aswin的答案似乎解决了问题。 - 3c71
我遇到了类似的情况。在华为、小米设备上的Android 10系统中,亮度表现不正常。 - Halil Ozel

1

我更喜欢使用这种方式将亮度设置为最大值,而不是将255设为最大值。只需将1F传递给screenBrightness。

WindowManager.LayoutParams layout = getWindow().getAttributes();
layout.screenBrightness = 1F;
getWindow().setAttributes(layout);

在不同的安卓设备上运行良好。


不适用于OnePlus(需要设置为4F),也不适用于POCO F2 Pro,需要将其设置为8F。 - 3c71

1
我还尝试过获取亮度(Android P,API 28的对数变体)。这是我所做的(请参见下面的代码):
- 从Google的公开可用API进行了逆向工程(链接:https://cs.android.com/), - 使用反射获取最小和最大亮度值, - 从MathUtils中获取所需的数学方法。
只需调用getCurrentBrightness来获取百分比亮度值。不幸的是,即使使用了这个设置,我仍然无法确定与Android显示设置中显示的相同亮度值...
我还尝试过使用brightnessIntToFloat(PowerManager / BrightnessSynchronizer;代码也包含在下面),但没有成功。
你有任何想法还可能出了什么问题吗?
public class BrightnessUtils {
        public static double getCurrentBrightness(Context mContext) {
            float screenBrightness = 0;
            try {
                screenBrightness = Settings.System.getFloat(mContext.getContentResolver(), "screen_brightness");
                //float test = brightnessIntToFloat(screenBrightness);
            } catch (Exception e){
                Log.d("Exception", e.toString());
            }
    
            return getPercentage((double) (screenBrightness != 0 ? convertLinearToGammaFloat(screenBrightness, getMinimumScreenBrightnessSetting(mContext), getMaximumScreenBrightnessSetting(mContext)) : 0), 0, 65535);
        }
    
        public static float norm(float start, float stop, float value) {
            return (value - start) / (stop - start);
        }
    
        public static float sqrt(float a) {
            return (float) Math.sqrt(a);
        }
    
        public static float log(float a) {
            return (float) Math.log(a);
        }
    
        public static float lerp(int start, int stop, float amount) {
            return lerp((float) start, (float) stop, amount);
        }
    
        public static float lerp(float start, float stop, float amount) {
            return start + (stop - start) * amount;
        }
    
        public static float constrainedMap(
                float rangeMin, float rangeMax, float valueMin, float valueMax, float value) {
            return lerp(rangeMin, rangeMax, lerpInvSat(valueMin, valueMax, value));
        }
    
        public static float lerpInvSat(float a, float b, float value) {
            return saturate(lerpInv(a, b, value));
        }
    
        public static float lerpInv(float a, float b, float value) {
            return a != b ? ((value - a) / (b - a)) : 0.0f;
        }
    
        public static float saturate(float value) {
            return constrain(value, 0.0f, 1.0f);
        }
    
        public static float constrain(float amount, float low, float high) {
            return amount < low ? low : (amount > high ? high : amount);
        }
    
        public static float brightnessIntToFloat(int brightnessInt) {
            final float minFloat = 0.0f;
            final float maxFloat = 1.0f;
            final float minInt = 1;
            final float maxInt = 255;
            return constrainedMap(minFloat, maxFloat, minInt, maxInt, brightnessInt);
        }
    
        public static int convertLinearToGammaFloat(float val, float min, float max) {
            final int GAMMA_SPACE_MIN = 0;
            final int GAMMA_SPACE_MAX = 65535;
    
            // Hybrid Log Gamma constant values
            final float R = 0.5f;
            final float A = 0.17883277f;
            final float B = 0.28466892f;
            final float C = 0.55991073f;
            // For some reason, HLG normalizes to the range [0, 12] rather than [0, 1]
            final float normalizedVal = norm(min, max, val) * 12.0f;
            final float ret;
            if (normalizedVal <= 1f) {
                ret = sqrt(normalizedVal) * R;
            } else {
                ret = A * log(normalizedVal - B) + C;
            }
    
            return Math.round(lerp(GAMMA_SPACE_MIN, GAMMA_SPACE_MAX, ret));
        }
    
        private static double getPercentage(double d, int i, int i2) {
            if (d > ((double) i2)) {
                return 1.0d;
            }
            double d2 = (double) i;
            if (d < d2) {
                return 0.0d;
            }
            return (d - d2) / ((double) (i2 - i));
        }
    
        public static float getMinimumScreenBrightnessSetting (Context context) {
            final android.content.res.Resources res = android.content.res.Resources.getSystem();
            int id = res.getIdentifier("config_screenBrightnessSettingMinimum", "integer", "android");
            if (id != 0) {
                try {
                    return res.getInteger(id);
                }
                catch (android.content.res.Resources.NotFoundException e) {
                    // ignore
                }
            }
            return 0;
        }
    
        public static float getMaximumScreenBrightnessSetting (Context context) {
            final android.content.res.Resources res = android.content.res.Resources.getSystem();
            final int id = res.getIdentifier("config_screenBrightnessSettingMaximum", "integer", "android");
            if (id != 0) {
                try {
                    return res.getInteger(id);
                }
                catch (android.content.res.Resources.NotFoundException e) {
                    // ignore
                }
            }
            return 255;
        }
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接