【问题标题】:How to stop service when ACTION_SCREEN_OFFACTION_SCREEN_OFF 时如何停止服务
【发布时间】:2010-12-23 22:24:43
【问题描述】:

我试图让我的数字时钟小部件的 UpdateService 在屏幕关闭时停止以节省电池,然后在屏幕激活时重新打开。我目前在 AppWidgetProvider 的 onReceive() 中有它,但我也在 BroadcastReciever 中尝试过。

我当前的代码是:

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;
}

有人可以帮我吗?我被难住了。

【问题讨论】:

  • 您面临的问题是什么?
  • 您的代码不是在屏幕关闭时启动服务,并在屏幕打开时停止服务 - 与您所说的想要做的相反吗?

标签: android service


【解决方案1】:

我很确定您必须在ACTION_SCREEN_OFF/ON 的代码中注册您的接收器。我不认为在清单中注册它们会起作用。

【讨论】:

    【解决方案2】:

    您似乎无法使用清单中的过滤器注册 ACTION_SCREEN_ON/OFF 意图。您必须在代码中注册您的 BroadcastReceiver。有关活动和服务的示例,请参阅 here

    只有当您的服务或活动正在运行时,您才会收到意图。与其他广播事件相比,系统不会启动您的进程来处理 SCREEN_ON 意图。在这方面它类似于 ACTION_BATTERY_CHANGED。

    要使用小部件处理此意图,我认为您必须启动一个服务来侦听该意图,然后通知您的小部件。

    【讨论】:

    • 此答案中引用的文章(从上面的“此处”一词链接)对这个问题的各个方面提供了极好的解释。这种方法对我来说非常有效。
    【解决方案3】:

    从 Jens 对同一问题的回答链接而来的文章提供了有关该主题的精彩演示。我用它来实现一个对我有用的解决方案。

    关键的一点是您的 BroadcastReceiver 只能在代码中注册;您既不需要也不需要清单中的条目。

    我推荐这篇文章,但对于那些赶时间的人,最简单的可行方法是将类似这样的内容粘贴到您的活动的 onCreate() 方法中:

    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);
    

    正如文章指出的那样,对于正在运行的活动,onPause() / onResume() 总是在电源按钮用于空白/取消空白显示时被调用,所以如果你有一些你不介意做的事情在电源按钮不是 调用 onPause() 或 onResume() 的原因的情况下,您可以在这些方法中执行此操作,从而捕获用于空白的电源按钮的每个实例或取消空白屏幕(以及由于其他原因导致的调用),而无需创建广播接收器的开销。

    对我来说就是这样;我有一个按钮,它使我的活动的主视图在按下时不可见,在释放时可见,如果用户按住按钮,然后在隐藏应用程序时点击电源按钮,当屏幕被另一个取消时,它将永久隐藏点击电源按钮。所以在我的情况下,我只需要在我的活动的 onResume() 覆盖中为我的主视图设置一个 setVisibility(VISIBLE) 调用。

    事实上,正如文章所示,即使您只想响应电源按钮事件,正确的方法是在 BroadcastReceiver 中设置一个标志,然后在 onPause() 和/或测试该标志onResume() 查看电源按钮是否是调用这些方法的具体原因。

    【讨论】:

    • 正确。这就是我要解决的问题。
    【解决方案4】:

    也许你应该使用

    public class MyReceiver extends BroadcastReceiver {..}
    

    然后在清单中使用这个类名

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-01-02
      • 2017-03-17
      • 2015-08-13
      • 1970-01-01
      • 2021-05-16
      • 1970-01-01
      相关资源
      最近更新 更多