如何查看后台服务是否正在运行?

我想要一个切换服务状态的Android活动——它让我打开它,如果它是关闭的,如果它是关闭的。


当前回答

摘自Android文档:

比如sendBroadcast(Intent),但是如果有任何接收器 这个函数将阻塞并立即分发它们 返回之前。

你可以把这次入侵看成是"ping "服务。因为我们可以同步广播,所以我们可以在UI线程上同步广播并获得结果。

服务

@Override
public void onCreate() {
   LocalBroadcastManager
     .getInstance(this)
     .registerReceiver(new ServiceEchoReceiver(), new IntentFilter("ping"));
     //do not forget to deregister the receiver when the service is destroyed to avoid
     //any potential memory leaks 
}

private class ServiceEchoReceiver extends BroadcastReceiver {
    public void onReceive (Context context, Intent intent) {
      LocalBroadcastManager
         .getInstance(this)
         .sendBroadcastSync(new Intent("pong"));
    }
}

活动

    bool serviceRunning = false;

    protected void onCreate (Bundle savedInstanceState){
        LocalBroadcastManager.getInstance(this).registerReceiver(pong, new IntentFilter("pong"));
        LocalBroadcastManager.getInstance(this).sendBroadcastSync(new Intent("ping"));
        if(!serviceRunning){
           //run the service
        }
    }

    private BroadcastReceiver pong = new BroadcastReceiver(){
        public void onReceive (Context context, Intent intent) {
          serviceRunning = true;   
        }
    }

当然,在许多应用程序中,赢家是服务上的静态布尔字段,在service . oncreate()中设置为true,在service . ondestroy()中设置为false,因为它要简单得多。

其他回答

不久前我也遇到了同样的问题。由于我的服务是本地的,我最终只是在服务类中使用一个静态字段来切换状态,正如hackbod在这里描述的那样

编辑(供记录):

下面是hackbod提出的解决方案:

如果你的客户端和服务器代码是同一个.apk的一部分,而你是 绑定到服务的具体意图(一个指定 确切的服务类别),然后您可以简单地将您的服务设置为a 全局变量,当它正在运行时,您的客户端可以检查。 我们故意没有API来检查服务是否正确 跑步是因为,当你想做某事时,几乎没有失败 这样,代码中就会出现竞争条件。

在kotlin中,你可以在伴侣对象中添加布尔变量,并从任何你想要的类中检查它的值:

companion object{
     var isRuning = false

}

在创建和销毁服务时更改它的值

 override fun onCreate() {
        super.onCreate()
        isRuning = true
    }

override fun onDestroy() {
    super.onDestroy()
    isRuning = false
    }

摘自Android文档:

比如sendBroadcast(Intent),但是如果有任何接收器 这个函数将阻塞并立即分发它们 返回之前。

你可以把这次入侵看成是"ping "服务。因为我们可以同步广播,所以我们可以在UI线程上同步广播并获得结果。

服务

@Override
public void onCreate() {
   LocalBroadcastManager
     .getInstance(this)
     .registerReceiver(new ServiceEchoReceiver(), new IntentFilter("ping"));
     //do not forget to deregister the receiver when the service is destroyed to avoid
     //any potential memory leaks 
}

private class ServiceEchoReceiver extends BroadcastReceiver {
    public void onReceive (Context context, Intent intent) {
      LocalBroadcastManager
         .getInstance(this)
         .sendBroadcastSync(new Intent("pong"));
    }
}

活动

    bool serviceRunning = false;

    protected void onCreate (Bundle savedInstanceState){
        LocalBroadcastManager.getInstance(this).registerReceiver(pong, new IntentFilter("pong"));
        LocalBroadcastManager.getInstance(this).sendBroadcastSync(new Intent("ping"));
        if(!serviceRunning){
           //run the service
        }
    }

    private BroadcastReceiver pong = new BroadcastReceiver(){
        public void onReceive (Context context, Intent intent) {
          serviceRunning = true;   
        }
    }

当然,在许多应用程序中,赢家是服务上的静态布尔字段,在service . oncreate()中设置为true,在service . ondestroy()中设置为false,因为它要简单得多。

这更适用于Intent Service调试,因为它们会生成一个线程,但也适用于常规服务。我找到这个线程感谢宾

在我的例子中,我摆弄了调试器并找到了线程视图。它看起来有点像微软Word里的项目符号图标。无论如何,您不必在调试器模式下使用它。单击该流程并单击该按钮。任何Intent服务都会在运行时显示出来,至少在模拟器上是这样。

检查服务是否正在运行的正确方法是简单地询问它。在您的服务中实现一个BroadcastReceiver来响应来自活动的ping。在服务启动时注册BroadcastReceiver,在服务被销毁时注销它。从您的活动(或任何组件)发送一个本地广播意图到服务,如果它响应,您就知道它正在运行。注意下面代码中ACTION_PING和ACTION_PONG之间的细微差别。

public class PingableService extends Service {
    public static final String ACTION_PING = PingableService.class.getName() + ".PING";
    public static final String ACTION_PONG = PingableService.class.getName() + ".PONG";

    public int onStartCommand (Intent intent, int flags, int startId) {
        LocalBroadcastManager.getInstance(this).registerReceiver(mReceiver, new IntentFilter(ACTION_PING));
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy () {
        LocalBroadcastManager.getInstance(this).unregisterReceiver(mReceiver);
        super.onDestroy();
    }

    private BroadcastReceiver mReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive (Context context, Intent intent) {
            if (intent.getAction().equals(ACTION_PING)) {
                LocalBroadcastManager manager = LocalBroadcastManager.getInstance(getApplicationContext());
                manager.sendBroadcast(new Intent(ACTION_PONG));
            }
        }
    };
}

public class MyActivity extends Activity {
    private boolean isSvcRunning = false;

    @Override
    protected void onStart() {
        LocalBroadcastManager manager = LocalBroadcastManager.getInstance(getApplicationContext());
        manager.registerReceiver(mReceiver, new IntentFilter(PingableService.ACTION_PONG));
        // the service will respond to this broadcast only if it's running
        manager.sendBroadcast(new Intent(PingableService.ACTION_PING));
        super.onStart();
    }

    @Override
    protected void onStop() {
        LocalBroadcastManager.getInstance(this).unregisterReceiver(mReceiver);
        super.onStop();
    }

    protected BroadcastReceiver mReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive (Context context, Intent intent) {
            // here you receive the response from the service
            if (intent.getAction().equals(PingableService.ACTION_PONG)) {
                isSvcRunning = true;
            }
        }
    };
}