简体   繁体   中英

How to stop service when ACTION_SCREEN_OFF

I am trying to make my UpdateService for my digital clock widget stop when the screen is turned off to conserve battery, and then back on when the screen is activated. I currently have it in my onReceive() in my AppWidgetProvider, but I have also tried it in a BroadcastReciever.

My current code is:

public static boolean wasScreenOn = true;

public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
    Log.d("Screen switched on. ", "Starting DigiClock UpdateService.");
    context.startService(new Intent(UpdateService2by2.ACTION_UPDATE));
    wasScreenOn = false;
} else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
    Log.d("Screen switched off. ", "Stopping DigiClock UpdateService.");
    context.stopService(new Intent(context, UpdateService2by2.class));
    wasScreenOn = true;
}

Can anyone help me out here? I am stumped.

I'm fairly sure that you have to register your receiver in code for ACTION_SCREEN_OFF/ON . I don't think registering them in the manifest will work.

It seems you cannot register for the ACTION_SCREEN_ON/OFF intents with a filter in the manifest. You have to register your BroadcastReceiver in code. See here for an examples for an activity and a service.

You'll only receive the intent if your service or activity is running. In contrast to other broadcast events, the system will not start your process to handle the SCREEN_ON intent. It is similar to ACTION_BATTERY_CHANGED in this regard.

To handle this intent with a widget, I think you have to start a service that listens for the intent and then notifies your widget.

The article linked from Jens' answer to this same question provides a great presentation on this topic. I used it to implement a solution that worked for me.

The key insight is that your BroadcastReceiver can only be registered in code; you neither want nor need an entry in your manifest.

I recommend the article, but for those in a hurry, the simplest possible functioning approach would be to just paste something like this into your activity's onCreate() method:

IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SCREEN_OFF);
BroadcastReceiver screenoffReceiver = new BroadcastReceiver() {
  @Override
  public void onReceive(Context context, Intent intent) {
    if(intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
      Log.v("screenoffReceiver", "SCREEN OFF");
    }
    else if(intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
      Log.v("screenoffReceiver", "SCREEN ON");
    }
    return;
  }
};      
registerReceiver(screenoffReceiver, filter);

As the article points out, for a running activity, onPause() / onResume() are always called when the power button is used to blank/unblank the display, so if you have something that you don't mind doing even in those cases for which the power button was not the reason for the onPause() or onResume() call, you can do it in those methods and thereby catch every instance of the power button being used to blank or unblank the screen (along with calls due to other causes), without the overhead of creating a BroadcastReceiver.

That was the case for me; I had a button that made my activity's main view invisible when pressed and visible when released, and if the user held the button down and then tapped the power button while the app was hidden, it would stay hidden permanently when the screen was unblanked by another tap of the power button. So in my case I only had to put a setVisibility(VISIBLE) call for my main view in my activity's onResume() override.

In fact, as the article shows, even if you only want to respond to the power button events, the proper way to do that is to set a flag in the BroadcastReceiver and then test that flag in onPause() and/or onResume() to see if the power button was the specific cause of the call to those methods.

Maybe you should use

public class MyReceiver extends BroadcastReceiver {..}

And then use this classname in the manifest

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM