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

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


当前回答

我的kotlin转换ActivityManager::getRunningServices基于答案。把这个函数放在一个活动中-

private fun isMyServiceRunning(serviceClass: Class<out Service>) =
    (getSystemService(ACTIVITY_SERVICE) as ActivityManager)
        .getRunningServices(Int.MAX_VALUE)
        ?.map { it.service.className }
        ?.contains(serviceClass.name) ?: false

其他回答

对于这里给出的用例,我们可以简单地使用stopService()方法的返回值。如果存在指定的服务并且该服务被终止,则返回true。否则返回false。因此,如果结果为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,因为它要简单得多。

一个小补语是:

我的目标是知道一个服务是否在运行,如果它没有运行。

调用bindService或调用一个可以被服务捕获的意图不是一个好主意,因为它会在服务未运行时启动服务。

因此,正如miracle2k所建议的,最好是在服务类中有一个静态字段,以知道服务是否已经启动。

为了使它更简洁,我建议用非常非常懒惰的抓取来转换单例中的服务:也就是说,通过静态方法完全没有实例化单例实例。service/singleton的静态getInstance方法只返回已经创建的单例实例。但它并不实际启动或实例化单例本身。服务只能通过正常的服务启动方法启动。

然后,修改单例设计模式,将令人困惑的getInstance方法重命名为类似isInstanceCreated(): boolean方法的方法会更加清晰。

代码如下所示:

public class MyService extends Service
{
   private static MyService instance = null;

   public static boolean isInstanceCreated() {
      return instance != null;
   }//met

   @Override
   public void onCreate()
   {
      instance = this;
      ....
   }//met

   @Override
   public void onDestroy()
   {
      instance = null;
      ...
   }//met
}//class

这个解决方案很优雅,但只有当你可以访问服务类时才有意义,而且只适用于服务的应用程序/包旁边的类。如果你的类在服务应用程序/包之外,那么你可以用Pieter-Jan Van Robays强调的限制来查询ActivityManager。

onDestroy并不总是在服务中调用,所以这是无用的!

例如:只需要对Eclipse做一点更改就可以再次运行应用程序。使用SIG: 9强制退出应用程序。

你可以使用这个(我还没有尝试过,但我希望它能工作):

if(startService(someIntent) != null) {
    Toast.makeText(getBaseContext(), "Service is already running", Toast.LENGTH_SHORT).show();
}
else {
    Toast.makeText(getBaseContext(), "There is no service running, starting service..", Toast.LENGTH_SHORT).show();
}

如果已经有一个正在运行的服务,startService方法将返回ComponentName对象。如果不是,则返回null。

参见公共抽象ComponentName startService (Intent服务)。

这和检查不一样,因为它正在启动服务,所以你可以添加stopService(someIntent);按照规定。