Hey everyone,
Haven’t posted in a while – sorry school has been busy. Any who, this little code snippet/example will be on how to deal with the Intent.ACTION_SCREEN_OFF and the Intent.ACTION_SCREEN_ON, which will come in nifty if you’re making an application that might need to save state or respond to the user’s screen going to sleep/waking up, etc.
First, unlike other broad casted intents, for Intent.ACTION_SCREEN_OFF and Intent.ACTION_SCREEN_ON you CANNOT declare them in your Android Manifest! I’m not sure exactly why, but they must be registered in an IntentFilter in your JAVA code. And so, for this example we are going to have a receiver called ScreenReceiver, and I’m going to walk you through the differences between implementing it in a Service vs. in an Activity.
So, the receiver will simply look like:
01 |
public class ScreenReceiver extends BroadcastReceiver { |
04 |
public static boolean wasScreenOn = true ; |
07 |
public void onReceive(Context context, Intent intent) { |
08 |
if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) { |
11 |
} else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) { |
Now, the first example will be for an Activity. Because of the life-cycle of an Activity, an Activity is actually easier to deal with as right before the screen turns off onPause() is called and right when the screen turns on onResume() is called, and so naturally we will handle the screen on/off events here:
01 |
public class ExampleActivity extends Activity { |
04 |
protected void onCreate() { |
06 |
IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON); |
07 |
filter.addAction(Intent.ACTION_SCREEN_OFF); |
08 |
BroadcastReceiver mReceiver = new ScreenReceiver(); |
09 |
registerReceiver(mReceiver, filter); |
14 |
protected void onPause() { |
16 |
if (ScreenReceiver.wasScreenOn) { |
18 |
System.out.println( "SCREEN TURNED OFF" ); |
26 |
protected void onResume() { |
28 |
if (!ScreenReceiver.wasScreenOn) { |
30 |
System.out.println( "SCREEN TURNED ON" ); |
Now, note that in my onPause() and onResume() methods I run a check to see that the method was called DUE TO A SCREEN STATE CHANGE. This is important as often onPause() or onResume() will get called because of other reasons – i.e. a new activity is being started on top of this one, or an incoming call might be coming in, etc – and you want to make sure that your screen change logic is only called when the screen has actually changed.
Now, something to keep in mind, is that the order of events before the system screen turns off is:
ExampleActivity.onPause() –> ScreenReceiver.onReceive()
Which is a little unintuitive as you’d think the receiver would get hit first – and so when you play around with setting booleans, etc, be aware of this little fact, and likewise when the screen turns on the order of events is:
ExampleActivity.onResume() –> ScreenReceiver.onReceive()
And so again the order of events seems a little “backwards”.
Now, for a Service, it’s a little bit different since there is no onResume() or onPause() that gets called as the Service is always “running” in the background, and so instead what you’re going to have to do is modify your receiver a little to look like:
01 |
public class ScreenReceiver extends BroadcastReceiver { |
03 |
private boolean screenOff; |
06 |
public void onReceive(Context context, Intent intent) { |
07 |
if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) { |
09 |
} else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) { |
12 |
Intent i = new Intent(context, UpdateService. class ); |
13 |
i.putExtra( "screen_state" , screenOff); |
14 |
context.startService(i); |
And your service will look like:
01 |
public static class UpdateService extends Service { |
04 |
public void onCreate() { |
07 |
IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON); |
08 |
filter.addAction(Intent.ACTION_SCREEN_OFF); |
09 |
BroadcastReceiver mReceiver = new ScreenReceiver(); |
10 |
registerReceiver(mReceiver, filter); |
14 |
public void onStart(Intent intent, int startId) { |
15 |
boolean screenOn = intent.getBooleanExtra( "screen_state" , false ); |
And so this is pretty self explanatory. When the screen state changes, it will notify your ScreenReceiver and from there you can set the state information into an Intent and send that data to your Service which can then handle it appropriately.
Hopefully this was useful. Let me know if you have questions.
Happy coding.
- jwei