Get preferred screen brightness in Android

hpique picture hpique · Dec 28, 2010 · Viewed 9.2k times · Source

How do you get the preferred screen brightness in Android?

To change the screen brightness I use WindowManager.LayoutParams.screenBrightness. According to the documentation:

This can be used to override the user's preferred brightness of the screen. A value of less than 0, the default, means to use the preferred screen brightness. 0 to 1 adjusts the brightness from dark to full bright.

When screenBrightness is less than 0 I would like to start with the preferred screen brightness. How can I get this value?

Answer

davidcesarino picture davidcesarino · Nov 13, 2011

I'll try to answer because I already searched for this some time ago. My short answer is: I've never found a way to get current brightness level when on auto mode, after extensive research.

I will break this into multiple answers. I won't skip premises, so as to googlers can find this helpful. Skip what you don't need.

1- Get brightness setting value

When screenBrightness is less than 0 I would like to start with the preferred screen brightness. How can I get this value?

For a person who has that amount of reputation, I'm sure you already know the drill about searching. There are tons of answers about this here on SO. Just check the right panel with similar questions... that said, I won't detail much.

int oldBrightness = Settings.System.getInt(getContext().getContentResolver(), 
             Settings.System.SCREEN_BRIGHTNESS);

This is how Android's BrightnessPreference.java do it in 2.3.5 (see line 68). It's also the same (for practical reasons) of what lfor posted.

It's not named old Brightness for nothing. This is a setting stored somewhere, not the current value. You can only be sure that it's the same of what the user is experiencing if you're into manual brightness mode. Otherwise, you just don't know. You should check:

int mode = Settings.System.getInt(getContext().getContentResolver(),
                     Settings.System.SCREEN_BRIGHTNESS_MODE);

2- Listen to screen brightness changes

As we know, generally, when we want to listen to changes in Android, we can try listening to Intent actions, registering BroadcastReceivers and all that. However, AFAIK, there is no ACTION_ for brightness changes, like SCREEN_[ON|OFF], for example. Maybe there is one hidden in the system, but I've never seen it, and if it's not publicly available, you have all the possible pitfalls of dealing with that.

There is a message, dated Dec 2010, from Dianne Hackborn, where she says that "there is no broadcast for screen brightness changes".

So, I don't believe there is a way to hook up into something like that. Of course, you can change the setting itself:

Settings.System.putInt(getContext().getContentResolver(),
    SCREEN_BRIGHTNESS_MODE, SCREEN_BRIGHTNESS_MODE_AUTOMATIC);

3- Listen to ambient light changes

You can, however, aprox. detect the amount of light. You need to implements SensorEventListener and:

// class definition:
private SensorManager sensorManager;

@Override
public void onSensorChanged(SensorEvent event) {
    float values = event.values[0]; // Ambient LUX
}
// onCreate:
sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);   
sensorManager.registerListener(this,
    sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT),
    SensorManager.SENSOR_DELAY_UI);

4- Guess the brightness change

After all that said, I must also repeat Hackborn's question: "what are you trying to accomplish?" (this is for the bounty owner). I'd be happy to see how Android maps ambient lux to screen brightness. I'm quite sure it's not a linear thing (map Sensor.getMaximumRange() linearly to the 0..1 float interval). I've seen that generally this is mapped logarithmic (provide finer adjustments into the lower brightness range), but I have no idea about the parameters. Perhaps there is a suggested default way that everyone uses, but I'm no expert.

If you could find how Android does it by looking into the place in the sources where it does that, that would be great. But anyway, I didn't come all this long to leave you with the same question. What I've found is that Sensor.getMaximumRange() is not consistent with what you get from the SensorEvent values[0]. Here, I have a Sharp sensor (Nexus S), and although the report max is 3,000, I've seen values of up to 10,240.

So, getting the sensor is not reliable (?). I'm guessing, by the behavior I've seen using Android, that somehow it maps getMaximumValue() to the max brightness, and any value above it just doesn't make a difference.

5- Where to go from here

I'd look more into Android sources. Somewhere, probably in a lower level, hardware managing stuff, you could see how they map. Still, I wonder if that's reliable, considering what Dianne Hackborn said (they seem to not want you to do that). I'd guess they had a reason to not expose that. Perhaps need: why does the app must know the system setting? It either needs to provide his own, app-wide level, or, in extreme cases, provide its own "autobrightness change method" (as in point 4 above) for a system-wide replacement or the manager. Perhaps that's what the original developers thought.

Anyway, if anyone find other details, I'd be extremely happy to know.