I’m an engineer through and through. I like tinkering. I like pulling stuff apart and seeing how it works. My business card clearly reads software engineer, but secretly I have a strong affinity for hardware. Hardware is where I started my career, and any chance I get to write software that manipulates the hardware in a more direct manner I relish the opportunity. So a couple weeks ago when I was asked how to adjust the LCD backlight on an Android tablet from within an application, well, I couldn’t wait to give it a go.
This tutorial will demonstrate how to read and write to the LCD backlight brightness control. The backlight technique demonstrated in this post is not persistent; in other words, in the rare instance where you might inadvertently “adjust” your display to a point where you could no longer read it, rebooting your device will restore it to its original state. If I haven’t scared you off yet, you can follow along with the step-by-step tutorial below, or download and import the entire project into Eclipse.
1. Start a new Android project in Eclipse. In order for the backlight technique we are using to work properly, you must target Android 2.2 (Froyo) or higher. Be sure to rename your startup file to Main.java, and the corresponding layout file to main.xml.
2. As we won’t be persisting any settings, we won’t need to modify the manifest. Let’s jump right into the /res/layout folder and define our main screen. The layout will consist of a couple text views, and two buttons for adjusting our backlight value. I’m using a table layout to space out the buttons and an empty view to simulate a horizontal rule.
main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:gravity="center"
android:background="#000000">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:textSize="20sp"
android:textColor="#00ff00"
android:text="LCD Brightness Control" />
<View
android:layout_width="fill_parent"
android:layout_height="3px"
android:background="#ffffff"
android:layout_marginLeft="30dip"
android:layout_marginRight="30dip"/>
<TableLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center"
android:stretchColumns="*"
android:layout_margin="30dip">
<TableRow >
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="-"
android:textStyle="bold"
android:textSize="20sp"
android:id="@+id/down_button"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:textColor="#ffffff"
android:text="100%"
android:id="@+id/text_display"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="+"
android:textStyle="bold"
android:textSize="20sp"
android:id="@+id/up_button"/>
</TableRow>
</TableLayout>
</LinearLayout>
3. Next comes our /src/Main.java file. We start by defining a default brightness value for our LCD, wiring our buttons, and initializing both the backlight control and our label.
package com.authorwjf.bright_idea;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.view.WindowManager;
import android.widget.TextView;
import android.app.Activity;
public class Main extends Activity implements OnClickListener{
private static int DEFAULT = 50;
private int brightness;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
brightness = DEFAULT;
setBrightness();
findViewById(R.id.down_button).setOnClickListener(this);
findViewById(R.id.up_button).setOnClickListener(this);
}
}
4. The on click listener is responsible for updating the class variable that holds our logical value, and calling the private function that will apply the logical value to the physical hardware.
@Override
public void onClick(View v) {
if (v.getId()==R.id.up_button) {
brightness+=10;
if (brightness > 100) brightness = 100;
} else {
brightness-=10;
if (brightness < 0) brightness=0;
}
setBrightness();
}
5. The set brightness function in turn is responsible for translating the brightness value from our familiar 0 to 100 scale into the internal 0 to 1 scale used by Android, applying the setting to the current window, and invoking the method that keeps our label current.
private void setBrightness() {
Window w = getWindow();
WindowManager.LayoutParams lp = w.getAttributes();
lp.screenBrightness = (float)brightness/100;
if (lp.screenBrightness<.01f) lp.screenBrightness=.01f;
w.setAttributes(lp);
updateTextLabel();
}
6. Last but not least the update text label method will display the brightness value to the world as an easy to read integer.
private void updateTextLabel() {
((TextView)findViewById(R.id.text_display)).setText(Integer.toString(brightness));
}
The app is ready to compile and execute (Figure A). It won’t have any effect on an emulator, so if you want to see the backlight change you will need to download it to an actual phone or tablet. If you noticed in the set brightness function I’ve put some safeguards in there to try and keep the display from going so dark it can’t be read, but as stated previously we aren’t actually persisting any LCD settings anyhow.
Figure A
If there ever were a case where you wanted your application to change the backlight value across the entire platform, the Android SDK allows this providing you request the “write settings” permission in your manifest. However I’d think long and hard on writing an app that changes the behavior of the device system wide. As a rule of thumb I want users to manage my application settings from within my app, and the system settings from within Android’s system menus.