Monday, September 14, 2009

Tutorial : how to use the LED with Android phone

Some android phones have a nice LED ( but not all of them: I don't think the Galaxy has one ).

This LED can show lots of different colors, and adding this feature in your application is a nice little "plus" !
And it's really easy...


So how to do it ?

You just have to get the notification manager, and use it to send a flash Light notification.
The notification contains the color light, the duration with the LED On, and the duration with the LED off.

Here's the code :

private void RedFlashLight()
{
NotificationManager nm = ( NotificationManager ) getSystemService( NOTIFICATION_SERVICE );
Notification notif = new Notification();
notif.ledARGB = 0xFFff0000;
notif.flags = Notification.FLAG_SHOW_LIGHTS;
notif.ledOnMS = 100;
notif.ledOffMS = 100;
nm.notify(LED_NOTIFICATION_ID, notif);
}

LED_NOTIFICATION_ID is just a value to register this allocation. In my case, it is just 0.
Here, the LED will flash with the color given by the parameter ledARGB, in this case 0xFFff0000 (red ). It will be ON for 100 milliseconds, then OFF for 100 milliseconds, and then loop back ON, etc...

This is nice, but wait... How do I STOP it ?
This code will let the LED flash for ever !

To stop it, we have two solutions :
1) decide to only have the LED flash once, so in this case, you have to add the FLAG_ONLY_ALERT_ONCE flag :
notif.flags = Notification.FLAG_SHOW_LIGHTS | Notification.FLAG_ONLY_ALERT_ONCE;
2) Let the LED flash for as long as you want, then cancel the notification. In my case, I stop it after a certain amount of time by posting a message with a delay.
Here is the full code for this :

private void ClearLED()
{
NotificationManager nm = ( NotificationManager ) getSystemService( NOTIFICATION_SERVICE );
nm.cancel( LED_NOTIFICATION_ID );
}
private Runnable mClearLED_Task = new Runnable()
{
public void run()
{
synchronized( LetterGame.this)
{
ClearLED();
}
}
};

private void RedFlashLight()
{
NotificationManager nm = ( NotificationManager ) getSystemService( NOTIFICATION_SERVICE );
Notification notif = new Notification();
notif.ledARGB = 0xFFff0000;
notif.flags = Notification.FLAG_SHOW_LIGHTS;
notif.ledOnMS = 100;
notif.ledOffMS = 100;
nm.notify(LED_NOTIFICATION_ID, notif);
// Program the end of the light :
mCleanLedHandler.postDelayed(mClearLED_Task, LED_TIME_ON );
}


With mCleanLedHandler being just a handler, and LED_TIME_ON the flash duration.

Some notes :
1) Don't let a handler alive when changing activity ! On the OnPause of your activity, clear the handler :
mCleanLedHandler.removeCallbacks( mClearLED_Task );
2) programming the LED suffers one issue : the emulator does not emulate the LED at all... So you have to use a real device to see what it looks like ( but anyway, you always use real device at some point, don't you ? :) )
3) programming the LED then suffers a Second issue : when the real device is connected to your PC in order for you to develop / test / debug, the device is also charging the battery. And in this case, the LED is orange. Whatever notification you send ! So you have to test without your device plugged !


That's all !
With all that, you can code some nice LED flashes !!!

15 comments:

Rob G said...

Neat, thanks.

For people that might be interested, instead of using ARGB value as the example show, you can use int property inside android.graphics.Color class to get the color as well.

I couldn't get the Handler's postDelayed to work though. Keep throwing NullPointerException for some reason. Maybe it's the Class.this?

I've been unsuccessfully trying to parse a String of "0xFF0000FF"(which is blue btw) into it using Integer.parseInt. Maybe I need to use something else :(

AndroidBlogger said...

Thanks for your comment...

I'm at work here, so I don't have my code, but for your handler issue, are you sure you created fully before using it ?
You should have somewhere in your activity creation a line like :
mCleanLedHandler = new Handler();

As for your parsing issue, I'm not sure, but I think you can specify the base number system as the second argument of ParseInt.
So :
string toto = "0xFF0000FF";
int totoVal = Integer.parseInt( toto, 16 );

should work...

At least I hope :)

Rob G said...

Spot on, I really did forget to create the Handler object.

However, trying to parse "0xFF0000FF" throw NumberFormatException stills.

Here's mine:
String sel = "0xFF0000FF";
result = Integer.parseInt(sel, 16);

* Exception was thrown from the Integer.parseInt(374) > Integer.parse(385).

I think I will try to take a look at how people made the color picker, that should help me out.

Thanks a lot again for your great tutorial :D.

Frédéric Menou said...

Exactly what I was looking for! Thanx a lot!!

I don't know how I'll use it, but for sure I will ! (I love clear synthetic status systems)

AndroidBlogger said...

Merci !
J'espere que tu feras de belles choses avec !!!

lZr said...

Simple and nice code, but there is no time stamp and the led will flash when the system can do it.
Froyo Nexus One flashes after exiting the app forever

AndroidBlogger said...

You mean this code is working on Nexus One ???
I'm very surprised, because this is some real code from my game 'WordProspector'. And it's doing great on the G1, but ... nothing on the nexus one ( before and after Froyo ).
So I'm very surprised.

As for the fact that it never stop flashing, this is weird.
Are you sure the "ClearLED" method is called ( you can put a log in it to check if it is called ).
Because the very role of this function is to stop the flash.

Hope it helps,

Android said...

The actual Nexus One's OS interface feels a little less responsive and slides a little less smoothly than the iPhone. But when I got into my app, it performed better. Overall I'm still just getting used to the device. I've had it less than 48 hours.

Anonymous said...

How do you determine what the status of the LED is? What I mean is how do you know if the LED is already on? Is there any way to get such status? I mean if you can make a write change to this property where can you check what the current status of the LED is?

LED Mini Lights said...

Hello,

Thank you very much for sharing this. It helps me a lot :)

led tubes said...

Thanks for this code, it helped me in my university project! :)

tuncowsky said...
This comment has been removed by the author.
tuncowsky said...
This comment has been removed by the author.
Sim Bhattacharya said...

Great example ,
A question , when I modify the notif.ledOnMS to 5000 (5 seconds ) and test it does not work , i.e the LED still turns on for a very short duration of time only and not for 5 seconds as desired. Is there a way for me to set the value such that the LED is turned on for a very long duration ?

Vicki said...

Is there any simple way to do this, say from the Android CLI with a shell script or Perl?

I'm not a Java programmer...