如何检查Android上的服务是否正在运行?

发布于 2024-07-14 12:27:20 字数 91 浏览 7 评论 0原文

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

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

How do I check if a background service is running?

I want an Android activity that toggles the state of the service -- it lets me turn it on if it is off and off if it is on.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(30

一杆小烟枪 2024-07-21 12:27:20

我在活动内部使用以下内容:

private boolean isMyServiceRunning(Class<?> serviceClass) {
    ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
    for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
        if (serviceClass.getName().equals(service.service.getClassName())) {
            return true;
        }
    }
    return false;
}

我称之为使用:

isMyServiceRunning(MyService.class)

这工作可靠,因为它基于 Android 操作系统通过 ActivityManager#getRunningServices

所有使用 onDestroy 或 onSomething 事件或 Binder 或静态变量的方法都无法可靠地工作,因为作为开发人员,您永远不知道 Android 何时决定终止您的进程或哪个进程是否调用上述回调。 请注意生命周期事件表中的“killable”列Android 文档。

I use the following from inside an activity:

private boolean isMyServiceRunning(Class<?> serviceClass) {
    ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
    for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
        if (serviceClass.getName().equals(service.service.getClassName())) {
            return true;
        }
    }
    return false;
}

And I call it using:

isMyServiceRunning(MyService.class)

This works reliably, because it is based on the information about running services provided by the Android operating system through ActivityManager#getRunningServices.

All the approaches using onDestroy or onSomething events or Binders or static variables will not work reliably because as a developer you never know, when Android decides to kill your process or which of the mentioned callbacks are called or not. Please note the "killable" column in the lifecycle events table in the Android documentation.

伴我心暖 2024-07-21 12:27:20

不久前我也遇到了同样的问题。 由于我的服务是本地的,因此我最终只是使用服务类中的静态字段来切换状态,如 hackbod 此处

编辑(记录):

这是 hackbod 提出的解决方案:

如果您的客户端和服务器代码是同一个 .apk 的一部分,并且您是
绑定到具有具体 Intent 的服务(指定
确切的服务类别),那么您只需将您的服务设置为
客户端可以检查运行时的全局变量。

我们故意不提供 API 来检查服务是否可用
跑步是因为,几乎毫无失败,当你想做某事时
这样你的代码中就会出现竞争条件。

I had the same problem not long ago. Since my service was local, I ended up simply using a static field in the service class to toggle state, as described by hackbod here

EDIT (for the record):

Here is the solution proposed by hackbod:

If your client and server code is part of the same .apk and you are
binding to the service with a concrete Intent (one that specifies the
exact service class), then you can simply have your service set a
global variable when it is running that your client can check.

We deliberately don't have an API to check whether a service is
running because, nearly without fail, when you want to do something
like that you end up with race conditions in your code.

ぃ弥猫深巷。 2024-07-21 12:27:20

知道了!

必须调用startService()才能正确注册您的服务,并且传递BIND_AUTO_CREATE是不够的。

Intent bindIntent = new Intent(this,ServiceTask.class);
startService(bindIntent);
bindService(bindIntent,mConnection,0);

现在是 ServiceTools 类:

public class ServiceTools {
    private static String LOG_TAG = ServiceTools.class.getName();

    public static boolean isServiceRunning(String serviceClassName){
        final ActivityManager activityManager = (ActivityManager)Application.getContext().getSystemService(Context.ACTIVITY_SERVICE);
        final List<RunningServiceInfo> services = activityManager.getRunningServices(Integer.MAX_VALUE);

        for (RunningServiceInfo runningServiceInfo : services) {
            if (runningServiceInfo.service.getClassName().equals(serviceClassName)){
                return true;
            }
        }
        return false;
     }
}

Got it!

You MUST call startService() for your service to be properly registered and passing BIND_AUTO_CREATE will not suffice.

Intent bindIntent = new Intent(this,ServiceTask.class);
startService(bindIntent);
bindService(bindIntent,mConnection,0);

And now the ServiceTools class:

public class ServiceTools {
    private static String LOG_TAG = ServiceTools.class.getName();

    public static boolean isServiceRunning(String serviceClassName){
        final ActivityManager activityManager = (ActivityManager)Application.getContext().getSystemService(Context.ACTIVITY_SERVICE);
        final List<RunningServiceInfo> services = activityManager.getRunningServices(Integer.MAX_VALUE);

        for (RunningServiceInfo runningServiceInfo : services) {
            if (runningServiceInfo.service.getClassName().equals(serviceClassName)){
                return true;
            }
        }
        return false;
     }
}
女中豪杰 2024-07-21 12:27:20

一个小小的补充是:

我的目标是了解服务是否正在运行,而无需在服务未运行时实际运行它。

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

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

为了使其更加清晰,我建议使用非常非常懒惰的获取方式将服务转换为单例:也就是说,根本没有实例化 通过静态方法实现单例实例。 服务/单例的静态 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

这个解决方案很优雅,但只有当您有权访问服务类并且仅适用于服务的应用程序/包内的类时,它才相关。 如果您的类位于服务应用程序/包之外,那么您可以查询 ActivityManager,其限制由 Pieter-Jan Van Robays 强调。

A small complement is:

My goal is to know wether a service is running without actualy running it if it is not running.

Calling bindService or calling an intent that can be caught by the service is not a good idea then as it will start the service if it is not running.

So, as miracle2k suggested, the best is to have a static field in the service class to know whether the service has been started or not.

To make it even cleaner, I suggest to transform the service in a singleton with a very very lazy fetching: that is, there is no instantiation at all of the singleton instance through static methods. The static getInstance method of your service/singleton just returns the instance of the singleton if it has been created. But it doesn't actualy start or instanciate the singleton itself. The service is only started through normal service start methods.

It would then be even cleaner to modify the singleton design pattern to rename the confusing getInstance method into something like the isInstanceCreated() : boolean method.

The code will look like:

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

This solution is elegant, but it is only relevant if you have access to the service class and only for classes iside the app/package of the service. If your classes are outside of the service app/package then you could query the ActivityManager with limitations underlined by Pieter-Jan Van Robays.

望她远 2024-07-21 12:27:20

您可以使用这个(我还没有尝试过,但我希望它有效):

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 (意向服务)

我认为这不像检查,因为它正在启动服务,因此您可以在代码下添加 stopService(someIntent);

You can use this (I didn't try this yet, but I hope this works):

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

The startService method returns a ComponentName object if there is an already running service. If not, null will be returned.

See public abstract ComponentName startService (Intent service).

This is not like checking I think, because it's starting the service, so you can add stopService(someIntent); under the code.

亢潮 2024-07-21 12:27:20
/**
 * Check if the service is Running 
 * @param serviceClass the class of the Service
 *
 * @return true if the service is running otherwise false
 */
public boolean checkServiceRunning(Class<?> serviceClass){
    ActivityManager manager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
    for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE))
    {
        if (serviceClass.getName().equals(service.service.getClassName()))
        {
            return true;
        }
    }
    return false;
}
/**
 * Check if the service is Running 
 * @param serviceClass the class of the Service
 *
 * @return true if the service is running otherwise false
 */
public boolean checkServiceRunning(Class<?> serviceClass){
    ActivityManager manager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
    for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE))
    {
        if (serviceClass.getName().equals(service.service.getClassName()))
        {
            return true;
        }
    }
    return false;
}
不知所踪 2024-07-21 12:27:20

Android 文档摘录:

sendBroadcast(Intent) ),但是如果有任何接收者
该函数将阻止并立即分派它们的 Intent
返回之前。

将此黑客视为“ping”服务。 由于我们可以同步广播,因此我们可以在 UI 线程上同步广播并获取结果。

Service

@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"));
    }
}

Activity

    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 因为它简单得多。

An extract from Android docs:

Like sendBroadcast(Intent), but if there are any receivers for
the Intent this function will block and immediately dispatch them
before returning.

Think of this hack as "pinging" the Service. Since we can broadcast synchronously, we can broadcast and get a result synchronously, on the UI thread.

Service

@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"));
    }
}

Activity

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

The winner in many applications is of course a static boolean field on the service that is set to true in Service.onCreate() and to false in Service.onDestroy() because it's a lot simpler.

情话已封尘 2024-07-21 12:27:20

另一种使用 kotlin 的方法。 受到其他用户答案的​​启发

fun isMyServiceRunning(serviceClass: Class<*>): Boolean {
    val manager = getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
    return manager.getRunningServices(Integer.MAX_VALUE)
            .any { it.service.className == serviceClass.name }
}

作为 kotlin 扩展

fun Context.isMyServiceRunning(serviceClass: Class<out Service>) = try {
    (getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager)
        .getRunningServices(Int.MAX_VALUE)
        .any { it.service.className == serviceClass.name }
} catch (e: Exception) {
    false
}

用法

context.isMyServiceRunning(MyService::class.java)

Another approach using kotlin. Inspired in other users answers

fun isMyServiceRunning(serviceClass: Class<*>): Boolean {
    val manager = getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
    return manager.getRunningServices(Integer.MAX_VALUE)
            .any { it.service.className == serviceClass.name }
}

As kotlin extension

fun Context.isMyServiceRunning(serviceClass: Class<out Service>) = try {
    (getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager)
        .getRunningServices(Int.MAX_VALUE)
        .any { it.service.className == serviceClass.name }
} catch (e: Exception) {
    false
}

Usage

context.isMyServiceRunning(MyService::class.java)
み格子的夏天 2024-07-21 12:27:20

检查服务是否正在运行的正确方法是简单地询问它。 在您的服务中实现一个 BroadcastReceiver 来响应来自您的活动的 ping。 当服务启动时注册BroadcastReceiver,当服务销毁时取消注册。 从您的 Activity(或任何组件)发送 本地广播< /a> 意图服务,如果它响应,您就知道它正在运行。 请注意下面代码中 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;
            }
        }
    };
}

The proper way to check if a service is running is to simply ask it. Implement a BroadcastReceiver in your service that responds to pings from your activities. Register the BroadcastReceiver when the service starts, and unregister it when the service is destroyed. From your activity (or any component), send a local broadcast intent to the service and if it responds, you know it's running. Note the subtle difference between ACTION_PING and ACTION_PONG in the code below.

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;
            }
        }
    };
}
孤千羽 2024-07-21 12:27:20

我稍微修改了上面提出的解决方案之一,但传递了类而不是通用字符串名称,以便确保比较来自同一方法 class.getName() 的字符串

public class ServiceTools {
    private static String LOG_TAG = ServiceTools.class.getName();

    public static boolean isServiceRunning(Context context,Class<?> serviceClass){
        final ActivityManager activityManager = (ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE);
        final List<RunningServiceInfo> services = activityManager.getRunningServices(Integer.MAX_VALUE);

        for (RunningServiceInfo runningServiceInfo : services) {
            Log.d(Constants.TAG, String.format("Service:%s", runningServiceInfo.service.getClassName()));
            if (runningServiceInfo.service.getClassName().equals(serviceClass.getName())){
                return true;
            }
        }
        return false;
    }
}

,然后

Boolean isServiceRunning = ServiceTools.isServiceRunning(
                    MainActivity.this.getApplicationContext(),
                    BackgroundIntentService.class);

I have slightly modified one of the solutions presented above, but passing the class instead of a generic string name, in order to be sure to compare strings coming out from the same method class.getName()

public class ServiceTools {
    private static String LOG_TAG = ServiceTools.class.getName();

    public static boolean isServiceRunning(Context context,Class<?> serviceClass){
        final ActivityManager activityManager = (ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE);
        final List<RunningServiceInfo> services = activityManager.getRunningServices(Integer.MAX_VALUE);

        for (RunningServiceInfo runningServiceInfo : services) {
            Log.d(Constants.TAG, String.format("Service:%s", runningServiceInfo.service.getClassName()));
            if (runningServiceInfo.service.getClassName().equals(serviceClass.getName())){
                return true;
            }
        }
        return false;
    }
}

and then

Boolean isServiceRunning = ServiceTools.isServiceRunning(
                    MainActivity.this.getApplicationContext(),
                    BackgroundIntentService.class);
み格子的夏天 2024-07-21 12:27:20

我只想在@Snicolas 的答案中添加一条注释。 以下步骤可用于在调用/不调用 onDestroy() 的情况下检查停止服务。

  1. onDestroy() 调用:转到“设置”->“ 应用-> 运行服务 -> 选择并停止您的服务。

  2. onDestroy() 未调用:转到“设置”->“ 应用-> 管理应用程序 -> 选择并“强制停止”正在运行服务的应用程序。 但是,由于您的应用程序在这里停止,因此服务实例肯定也会停止。

最后,我想提一下,其中提到的在单例类中使用静态变量的方法对我有用。

I just want to add a note to the answer by @Snicolas. The following steps can be used to check stop service with/without calling onDestroy().

  1. onDestroy() called: Go to Settings -> Application -> Running Services -> Select and stop your service.

  2. onDestroy() not Called: Go to Settings -> Application -> Manage Applications -> Select and "Force Stop" your application in which your service is running. However, as your application is stopped here, so definitely the service instances will also be stopped.

Finally, I would like to mention that the approach mentioned there using a static variable in singleton class is working for me.

无戏配角 2024-07-21 12:27:20

同样,如果人们使用挂起的意图,他们可能会发现另一种更干净的选择(例如使用 AlarmManager

public static boolean isRunning(Class<? extends Service> serviceClass) {
    final Intent intent = new Intent(context, serviceClass);
    return (PendingIntent.getService(context, CODE, intent, PendingIntent.FLAG_NO_CREATE) != null);
}

其中 CODE 是您在类中私有定义的常量,用于标识与您的服务相关的待处理意图。

Again, another alternative that people might find cleaner if they use pending intents (for instance with the AlarmManager:

public static boolean isRunning(Class<? extends Service> serviceClass) {
    final Intent intent = new Intent(context, serviceClass);
    return (PendingIntent.getService(context, CODE, intent, PendingIntent.FLAG_NO_CREATE) != null);
}

Where CODE is a constant that you define privately in your class to identify the pending intents associated to your service.

国际总奸 2024-07-21 12:27:20

首先,您不应该使用 ActivityManager。 (此处讨论

服务可以自行运行,绑定到一个 Activity 或两者。 检查 Activity 是否正在运行的方法是创建一个接口(扩展 Binder),在其中声明 ActivityService 的方法, 理解。 您可以通过创建自己的接口来实现此目的,例如在其中声明“isServiceRunning()”。
然后,您可以将您的 Activity 绑定到您的 Service,运行 isServiceRunning() 方法,Service 将检查自身是否正在运行,并向您的 Activity 返回一个布尔值。

您还可以使用此方法来停止您的服务或以其他方式与其交互。

First of all you shouldn't reach the service by using the ActivityManager. (Discussed here)

Services can run on their own, be bound to an Activity or both. The way to check in an Activity if your Service is running or not is by making an interface (that extends Binder) where you declare methods that both, the Activity and the Service, understand. You can do this by making your own Interface where you declare for example "isServiceRunning()".
You can then bind your Activity to your Service, run the method isServiceRunning(), the Service will check for itself if it is running or not and returns a boolean to your Activity.

You can also use this method to stop your Service or interact with it in another way.

却一份温柔 2024-07-21 12:27:20

onDestroy 并不总是在服务中调用,因此这是没有用的!

例如:只需从 Eclipse 进行一项更改即可再次运行该应用程序。 使用 SIG: 9 强制退出应用程序。

onDestroy isn't always called in the service so this is useless!

For example: Just run the app again with one change from Eclipse. The application is forcefully exited using SIG: 9.

强者自强 2024-07-21 12:27:20

下面是一个涵盖所有 If 的优雅技巧。 这仅适用于本地服务。

    public final class AService extends Service {

        private static AService mInstance = null;

        public static boolean isServiceCreated() {
            try {
                // If instance was not cleared but the service was destroyed an Exception will be thrown
                return mInstance != null && mInstance.ping();
            } catch (NullPointerException e) {
                // destroyed/not-started
                return false;
            }
        }

        /**
         * Simply returns true. If the service is still active, this method will be accessible.
         * @return
         */
        private boolean ping() {
            return true;
        }

        @Override
        public void onCreate() {
            mInstance = this;
        }

        @Override
        public void onDestroy() {
            mInstance = null;
        }
    }

然后后来:

    if(AService.isServiceCreated()){
        ...
    }else{
        startService(...);
    }

Below is an elegant hack that covers all the Ifs. This is for local services only.

    public final class AService extends Service {

        private static AService mInstance = null;

        public static boolean isServiceCreated() {
            try {
                // If instance was not cleared but the service was destroyed an Exception will be thrown
                return mInstance != null && mInstance.ping();
            } catch (NullPointerException e) {
                // destroyed/not-started
                return false;
            }
        }

        /**
         * Simply returns true. If the service is still active, this method will be accessible.
         * @return
         */
        private boolean ping() {
            return true;
        }

        @Override
        public void onCreate() {
            mInstance = this;
        }

        @Override
        public void onDestroy() {
            mInstance = null;
        }
    }

And then later on:

    if(AService.isServiceCreated()){
        ...
    }else{
        startService(...);
    }
狼亦尘 2024-07-21 12:27:20

Xamarin C# 版本:

private bool isMyServiceRunning(System.Type cls)
{
    ActivityManager manager = (ActivityManager)GetSystemService(Context.ActivityService);

    foreach (var service in manager.GetRunningServices(int.MaxValue)) {
        if (service.Service.ClassName.Equals(Java.Lang.Class.FromType(cls).CanonicalName)) {
            return true;
        }
    }
    return false;
}

Xamarin C# version:

private bool isMyServiceRunning(System.Type cls)
{
    ActivityManager manager = (ActivityManager)GetSystemService(Context.ActivityService);

    foreach (var service in manager.GetRunningServices(int.MaxValue)) {
        if (service.Service.ClassName.Equals(Java.Lang.Class.FromType(cls).CanonicalName)) {
            return true;
        }
    }
    return false;
}
葵雨 2024-07-21 12:27:20

对于此处给出的用例,我们可以简单地使用 stopService() 方法的返回值。 如果指定的服务存在并且被杀死,则返回true。 否则返回false。 因此,如果结果为false,则可以重新启动服务,否则可以确定当前服务已停止。 :) 如果你看看 这个

For the use-case given here we may simply make use of the stopService() method's return value. It returns true if there exists the specified service and it is killed. Else it returns false. So you may restart the service if the result is false else it is assured that the current service has been stopped. :) It would be better if you have a look at this.

彡翼 2024-07-21 12:27:20

geekQ 的响应,但是在 Kotlin 类中。 谢谢极客Q

fun isMyServiceRunning(serviceClass : Class<*> ) : Boolean{
    var manager = getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
    for (service in manager.getRunningServices(Integer.MAX_VALUE)) {
        if (serviceClass.name.equals(service.service.className)) {
            return true
        }
    }
    return false
}

来电

isMyServiceRunning(NewService::class.java)

The response of geekQ but in Kotlin class. Thanks geekQ

fun isMyServiceRunning(serviceClass : Class<*> ) : Boolean{
    var manager = getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
    for (service in manager.getRunningServices(Integer.MAX_VALUE)) {
        if (serviceClass.name.equals(service.service.className)) {
            return true
        }
    }
    return false
}

The call

isMyServiceRunning(NewService::class.java)
自在安然 2024-07-21 12:27:20

在您的服务子类中,使用静态布尔值来获取服务的状态,如下所示。

MyService.kt

class MyService : Service() {
    override fun onCreate() {
        super.onCreate()
        isServiceStarted = true
    }
    override fun onDestroy() {
        super.onDestroy()
        isServiceStarted = false
    }
    companion object {
        var isServiceStarted = false
    }
}

MainActivity.kt

class MainActivity : AppCompatActivity(){
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val serviceStarted = FileObserverService.isServiceStarted
        if (!serviceStarted) {
            val startFileObserverService = Intent(this, FileObserverService::class.java)
            ContextCompat.startForegroundService(this, startFileObserverService)
        }
    }
}

In your Service Sub-Class Use a Static Boolean to get the state of the Service as demonstrated below.

MyService.kt

class MyService : Service() {
    override fun onCreate() {
        super.onCreate()
        isServiceStarted = true
    }
    override fun onDestroy() {
        super.onDestroy()
        isServiceStarted = false
    }
    companion object {
        var isServiceStarted = false
    }
}

MainActivity.kt

class MainActivity : AppCompatActivity(){
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val serviceStarted = FileObserverService.isServiceStarted
        if (!serviceStarted) {
            val startFileObserverService = Intent(this, FileObserverService::class.java)
            ContextCompat.startForegroundService(this, startFileObserverService)
        }
    }
}
风筝有风,海豚有海 2024-07-21 12:27:20

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

companion object{
     var isRuning = false

}

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

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

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

In kotlin you can add boolean variable in companion object and check its value from any class you want:

companion object{
     var isRuning = false

}

Change it value when service is created and destroyed

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

override fun onDestroy() {
    super.onDestroy()
    isRuning = false
    }
浸婚纱 2024-07-21 12:27:20

对于 kotlin,您可以使用以下代码。

fun isMyServiceRunning(calssObj: Class<SERVICE_CALL_NAME>): Boolean {
    val manager = requireActivity().getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
    for (service in manager.getRunningServices(Integer.MAX_VALUE)) {
        if (calssObj.getName().equals(service.service.getClassName())) {
            return true
        }
    }
    return false
}

For kotlin, you can use the below code.

fun isMyServiceRunning(calssObj: Class<SERVICE_CALL_NAME>): Boolean {
    val manager = requireActivity().getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
    for (service in manager.getRunningServices(Integer.MAX_VALUE)) {
        if (calssObj.getName().equals(service.service.getClassName())) {
            return true
        }
    }
    return false
}
红衣飘飘貌似仙 2024-07-21 12:27:20

在 TheServiceClass 内部定义:

 public static Boolean serviceRunning = false;

然后在 onStartCommand(...) 中

 public int onStartCommand(Intent intent, int flags, int startId) {

    serviceRunning = true;
    ...
}

 @Override
public void onDestroy()
{
    serviceRunning = false;

} 

,然后从任何类调用 if(TheServiceClass.serviceRunning == true)

Inside TheServiceClass define:

 public static Boolean serviceRunning = false;

Then In onStartCommand(...)

 public int onStartCommand(Intent intent, int flags, int startId) {

    serviceRunning = true;
    ...
}

 @Override
public void onDestroy()
{
    serviceRunning = false;

} 

Then, call if(TheServiceClass.serviceRunning == true) from any class.

居里长安 2024-07-21 12:27:20

简单地使用绑定而不创建自动 - 请参阅 ps。 并更新...

public abstract class Context {

 ... 

  /*
  * @return {true} If you have successfully bound to the service, 
  *  {false} is returned if the connection is not made 
  *  so you will not receive the service object.
  */
  public abstract boolean bindService(@RequiresPermission Intent service,
        @NonNull ServiceConnection conn, @BindServiceFlags int flags);

示例:

    Intent bindIntent = new Intent(context, Class<Service>);
    boolean bindResult = context.bindService(bindIntent, ServiceConnection, 0);

为什么不使用? getRunningServices()

List<ActivityManager.RunningServiceInfo> getRunningServices (int maxNum)
Return a list of the services that are currently running.

注意:此方法仅用于调试或实现服务管理类型用户界面。


ps。 android 文档具有误导性,我在 google tracker 上提出了一个问题,以消除任何疑虑:

https:/ /issuetracker.google.com/issues/68908332

我们可以看到绑定服务实际上通过 Service 缓存绑定器通过 ActivityManager 绑定器调用事务 - 我不跟踪哪个服务负责绑定,但我们可以看到绑定的结果is:

int res = ActivityManagerNative.getDefault().bindService(...);
return res != 0;

事务是通过binder进行的:

ServiceManager.getService("activity");

next:

  public static IBinder getService(String name) {
    try {
        IBinder service = sCache.get(name);
        if (service != null) {
            return service;
        } else {
            return getIServiceManager().getService(name);

这是在ActivityThread中设置的 via:

 public final void bindApplication(...) {

        if (services != null) {
            // Setup the service cache in the ServiceManager
            ServiceManager.initServiceCache(services);
        }

这是在ActivityManagerService中调用的方法:

 private final boolean attachApplicationLocked(IApplicationThread thread,
            int pid) {
    ...
    thread.bindApplication(... , getCommonServicesLocked(),...)

then:

 private HashMap<String, IBinder> getCommonServicesLocked() {

但是没有“活动”,只有窗口包和警报..

所以我们需要返回调用:

 return getIServiceManager().getService(name);

    sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());

this通过:进行调用

    mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);

:这会导致:

BinderInternal.getContextObject()

这是本机方法....

  /**
     * Return the global "context object" of the system.  This is usually
     * an implementation of IServiceManager, which you can use to find
     * other services.
     */
    public static final native IBinder getContextObject();

我现在没有时间深入研究c,所以在我剖析休息调用之前我会暂停我的回答。

但检查服务是否正在运行的最佳方法是创建绑定(如果未创建绑定,则服务不存在) - 并通过绑定查询服务的状态(使用其状态上存储的内部标志) 。

更新 23.06.2018

我发现这些很有趣:

/**
 * Provide a binder to an already-bound service.  This method is synchronous
 * and will not start the target service if it is not present, so it is safe
 * to call from {@link #onReceive}.
 *
 * For peekService() to return a non null {@link android.os.IBinder} interface
 * the service must have published it before. In other words some component
 * must have called {@link android.content.Context#bindService(Intent, ServiceConnection, int)} on it.
 *
 * @param myContext The Context that had been passed to {@link #onReceive(Context, Intent)}
 * @param service Identifies the already-bound service you wish to use. See
 * {@link android.content.Context#bindService(Intent, ServiceConnection, int)}
 * for more information.
 */
public IBinder peekService(Context myContext, Intent service) {
    IActivityManager am = ActivityManager.getService();
    IBinder binder = null;
    try {
        service.prepareToLeaveProcess(myContext);
        binder = am.peekService(service, service.resolveTypeIfNeeded(
                myContext.getContentResolver()), myContext.getOpPackageName());
    } catch (RemoteException e) {
    }
    return binder;
}

简而言之:)

“为已绑定的服务提供绑定器。此方法是同步的,如果目标服务不存在,则不会启动它。”

public IBinder peekService(意图服务,字符串解析类型,
String CallingPackage) 抛出 RemoteException;

*

public static IBinder peekService(IBinder remote, Intent service, String resolvedType)
             throws RemoteException {
    Parcel data = Parcel.obtain();
    Parcel reply = Parcel.obtain();
    data.writeInterfaceToken("android.app.IActivityManager");
    service.writeToParcel(data, 0);
    data.writeString(resolvedType);
    remote.transact(android.os.IBinder.FIRST_CALL_TRANSACTION+84, data, reply, 0);
    reply.readException();
    IBinder binder = reply.readStrongBinder();
    reply.recycle();
    data.recycle();
    return binder;
}

*

simple use bind with don't create auto - see ps. and update...

public abstract class Context {

 ... 

  /*
  * @return {true} If you have successfully bound to the service, 
  *  {false} is returned if the connection is not made 
  *  so you will not receive the service object.
  */
  public abstract boolean bindService(@RequiresPermission Intent service,
        @NonNull ServiceConnection conn, @BindServiceFlags int flags);

example :

    Intent bindIntent = new Intent(context, Class<Service>);
    boolean bindResult = context.bindService(bindIntent, ServiceConnection, 0);

why not using? getRunningServices()

List<ActivityManager.RunningServiceInfo> getRunningServices (int maxNum)
Return a list of the services that are currently running.

Note: this method is only intended for debugging or implementing service management type user interfaces.


ps. android documentation is misleading i have opened an issue on google tracker to eliminate any doubts:

https://issuetracker.google.com/issues/68908332

as we can see bind service actually invokes a transaction via ActivityManager binder through Service cache binders - i dint track which service is responsible for binding but as we can see the result for bind is:

int res = ActivityManagerNative.getDefault().bindService(...);
return res != 0;

transaction is made through binder:

ServiceManager.getService("activity");

next:

  public static IBinder getService(String name) {
    try {
        IBinder service = sCache.get(name);
        if (service != null) {
            return service;
        } else {
            return getIServiceManager().getService(name);

this is set in ActivityThread via:

 public final void bindApplication(...) {

        if (services != null) {
            // Setup the service cache in the ServiceManager
            ServiceManager.initServiceCache(services);
        }

this is called in ActivityManagerService in method:

 private final boolean attachApplicationLocked(IApplicationThread thread,
            int pid) {
    ...
    thread.bindApplication(... , getCommonServicesLocked(),...)

then:

 private HashMap<String, IBinder> getCommonServicesLocked() {

but there is no "activity" only window package and alarm..

so we need get back to call:

 return getIServiceManager().getService(name);

    sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());

this makes call through:

    mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);

which leads to :

BinderInternal.getContextObject()

and this is native method....

  /**
     * Return the global "context object" of the system.  This is usually
     * an implementation of IServiceManager, which you can use to find
     * other services.
     */
    public static final native IBinder getContextObject();

i don't have time now to dug in c so until i dissect rest call i suspend my answer.

but best way for check if service is running is to create bind (if bind is not created service not exist) - and query the service about its state through the bind (using stored internal flag on it state).

update 23.06.2018

i found those interesting:

/**
 * Provide a binder to an already-bound service.  This method is synchronous
 * and will not start the target service if it is not present, so it is safe
 * to call from {@link #onReceive}.
 *
 * For peekService() to return a non null {@link android.os.IBinder} interface
 * the service must have published it before. In other words some component
 * must have called {@link android.content.Context#bindService(Intent, ServiceConnection, int)} on it.
 *
 * @param myContext The Context that had been passed to {@link #onReceive(Context, Intent)}
 * @param service Identifies the already-bound service you wish to use. See
 * {@link android.content.Context#bindService(Intent, ServiceConnection, int)}
 * for more information.
 */
public IBinder peekService(Context myContext, Intent service) {
    IActivityManager am = ActivityManager.getService();
    IBinder binder = null;
    try {
        service.prepareToLeaveProcess(myContext);
        binder = am.peekService(service, service.resolveTypeIfNeeded(
                myContext.getContentResolver()), myContext.getOpPackageName());
    } catch (RemoteException e) {
    }
    return binder;
}

in short :)

"Provide a binder to an already-bound service. This method is synchronous and will not start the target service if it is not present."

public IBinder peekService(Intent service, String resolvedType,
String callingPackage) throws RemoteException;

*

public static IBinder peekService(IBinder remote, Intent service, String resolvedType)
             throws RemoteException {
    Parcel data = Parcel.obtain();
    Parcel reply = Parcel.obtain();
    data.writeInterfaceToken("android.app.IActivityManager");
    service.writeToParcel(data, 0);
    data.writeString(resolvedType);
    remote.transact(android.os.IBinder.FIRST_CALL_TRANSACTION+84, data, reply, 0);
    reply.readException();
    IBinder binder = reply.readStrongBinder();
    reply.recycle();
    data.recycle();
    return binder;
}

*

箹锭⒈辈孓 2024-07-21 12:27:20

请使用此代码。

if (isMyServiceRunning(MainActivity.this, xyzService.class)) { // Service class name
    // Service running
} else {
    // Service Stop
}


public static boolean isMyServiceRunning(Activity activity, Class<?> serviceClass) {
        ActivityManager manager = (ActivityManager) activity.getSystemService(Context.ACTIVITY_SERVICE);
        for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
            if (serviceClass.getName().equals(service.service.getClassName())) {
                return true;
            }
        }
        return false;
    }

Please use this code.

if (isMyServiceRunning(MainActivity.this, xyzService.class)) { // Service class name
    // Service running
} else {
    // Service Stop
}


public static boolean isMyServiceRunning(Activity activity, Class<?> serviceClass) {
        ActivityManager manager = (ActivityManager) activity.getSystemService(Context.ACTIVITY_SERVICE);
        for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
            if (serviceClass.getName().equals(service.service.getClassName())) {
                return true;
            }
        }
        return false;
    }
物价感观 2024-07-21 12:27:20

这是我提出的很好的解决方案,但它仅适用于在单独进程中运行的服务。 这可以通过在清单中添加 android:process 属性来实现,例如

<service
        android:name=".ExampleService"
        android:process="com.example.service"
        ...

现在您的服务将在具有给定名称的单独进程中运行。 在您的应用中,您可以调用

val activityManager = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
activityManager.runningAppProcesses.any { it.processName == "com.example.service" }

Which 将在服务正在运行时返回 true ,否则返回 false

重要:请注意,它会显示您的服务何时启动,但是当您禁用它时(即系统与其解除绑定后),该进程仍然可以活动。 因此,您可以简单地强制将其删除:

override fun onUnbind(intent: Intent?): Boolean {
    stopSelf()
    return super.onUnbind(intent)
}

override fun onDestroy() {
    super.onDestroy()
    killProcess(Process.myPid())
}

然后它就可以正常工作了。

Here's good solution I've come up with, but it works only for the Services running in separate processes. This can be achieved by adding an android:process attribute in the manifest, e.g.

<service
        android:name=".ExampleService"
        android:process="com.example.service"
        ...

Now your service will be running in a separate process with the given name. From your app you can call

val activityManager = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
activityManager.runningAppProcesses.any { it.processName == "com.example.service" }

Which will return true if the service is running and false otherwise.

IMPORTANT: note that it will show you when your service was started, but when you disable it (meaning, after system unbinds from it) the process can still be alive. So you can simply force it's removal:

override fun onUnbind(intent: Intent?): Boolean {
    stopSelf()
    return super.onUnbind(intent)
}

override fun onDestroy() {
    super.onDestroy()
    killProcess(Process.myPid())
}

Then it works perfectly.

饮惑 2024-07-21 12:27:20

可以有多个具有相同类名的服务。

我刚刚创建了两个应用程序。 第一个应用程序的包名称是com.example.mock。 我在应用程序中创建了一个名为 lorem 的子包和一个名为 Mock2Service 的服务。 所以它的完全限定名称是com.example.mock.lorem.Mock2Service

然后我创建了第二个应用程序和一个名为 Mock2Service 的服务。 第二个应用程序的包名称是com.example.mock.lorem。 该服务的完全限定名称也是com.example.mock.lorem.Mock2Service

这是我的 logcat 输出。

03-27 12:02:19.985: D/TAG(32155): Mock-01: com.example.mock.lorem.Mock2Service
03-27 12:02:33.755: D/TAG(32277): Mock-02: com.example.mock.lorem.Mock2Service

更好的想法是比较 ComponentName 实例,因为 ComponentNameequals() 会比较包名称和类名称。 并且设备上不能安装两个具有相同包名的应用程序。

ComponentName 的 equals() 方法。

@Override
public boolean equals(Object obj) {
    try {
        if (obj != null) {
            ComponentName other = (ComponentName)obj;
            // Note: no null checks, because mPackage and mClass can
            // never be null.
            return mPackage.equals(other.mPackage)
                    && mClass.equals(other.mClass);
        }
    } catch (ClassCastException e) {
    }
    return false;
}

组件名称

There can be several services with the same class name.

I've just created two apps. The package name of the first app is com.example.mock. I created a subpackage called lorem in the app and a service called Mock2Service. So its fully qualified name is com.example.mock.lorem.Mock2Service.

Then I created the second app and a service called Mock2Service. The package name of the second app is com.example.mock.lorem. The fully qualified name of the service is com.example.mock.lorem.Mock2Service, too.

Here is my logcat output.

03-27 12:02:19.985: D/TAG(32155): Mock-01: com.example.mock.lorem.Mock2Service
03-27 12:02:33.755: D/TAG(32277): Mock-02: com.example.mock.lorem.Mock2Service

A better idea is to compare ComponentName instances because equals() of ComponentName compares both package names and class names. And there can't be two apps with the same package name installed on a device.

The equals() method of ComponentName.

@Override
public boolean equals(Object obj) {
    try {
        if (obj != null) {
            ComponentName other = (ComponentName)obj;
            // Note: no null checks, because mPackage and mClass can
            // never be null.
            return mPackage.equals(other.mPackage)
                    && mClass.equals(other.mClass);
        }
    } catch (ClassCastException e) {
    }
    return false;
}

ComponentName

似狗非友 2024-07-21 12:27:20

如果您有一个多模块应用程序,并且您想知道某个模块中的服务是否正在运行,而该模块不依赖于包含该服务的模块,则可以使用此函数:

fun isServiceRunning(context: Context, serviceClassName: String): Boolean {

    val manager = ContextCompat.getSystemService(
        context,
        ActivityManager::class.java
    ) ?: return false

    return manager.getRunningServices(Integer.MAX_VALUE).any { serviceInfo ->
        serviceInfo.service.shortClassName.contains(vpnServiceClassName)
    }
}

Usage for MyService服务:

isServiceRunning(context, "MyService")

如果服务类名发生变化而调用函数没有相应变化,则该函数可能无法正常工作。

If you have a multi-module application and you want to know that service is running or not from a module that is not depends on the module that contains the service, you can use this function:

fun isServiceRunning(context: Context, serviceClassName: String): Boolean {

    val manager = ContextCompat.getSystemService(
        context,
        ActivityManager::class.java
    ) ?: return false

    return manager.getRunningServices(Integer.MAX_VALUE).any { serviceInfo ->
        serviceInfo.service.shortClassName.contains(vpnServiceClassName)
    }
}

Usage for MyService service:

isServiceRunning(context, "MyService")

This function may not work correctly if the service class name changes and the calling function does not change accordingly.

攒一口袋星星 2024-07-21 12:27:20

这更适用于意图服务调试,因为它们生成线程,但也可能适用于常规服务。 感谢 Binging,我找到了这个线程。

在我的例子中,我使用调试器并找到了线程视图。 它看起来有点像 MS Word 中的项目符号图标。 无论如何,您不必处于调试器模式即可使用它。 单击该进程,然后单击该按钮。 任何意图服务都会在运行时显示,至少在模拟器上。

This applies more towards Intent Service debugging since they spawn a thread, but may work for regular services as well. I found this thread thanks to Binging

In my case, I played around with the debugger and found the thread view. It kind of looks like the bullet point icon in MS Word. Anyways, you don't have to be in debugger mode to use it. Click on the process and click on that button. Any Intent Services will show up while they are running, at least on the emulator.

比忠 2024-07-21 12:27:20

如果服务属于另一个进程或APK,请使用基于ActivityManager的解决方案。

如果您有权访问其源代码,则只需使用基于静态字段的解决方案即可。 但我建议使用 Date 对象来代替布尔值。 当服务运行时,只需将其值更新为“now”,完成后将其设置为 null。 从活动中,您可以检查其是否为空或日期是否太旧,这意味着它没有运行。

您还可以从您的服务发送广播通知,指示该服务正在运行进一步的信息(例如进度)。

If the service belongs to another process or APK use the solution based on the ActivityManager.

If you have access to its source, just use the solution based on a static field. But instead using a boolean I would suggest using a Date object. While the service is running, just update its value to 'now' and when it finishes set it to null. From the activity you can check if its null or the date is too old which will mean that it is not running.

You can also send broadcast notification from your service indicating that is running along further info like progress.

檐上三寸雪 2024-07-21 12:27:20

我对基于 ActivityManager::getRunningServices 的答案进行了 kotlin 转换。 将此功能放入活动中-

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

My kotlin conversion of the ActivityManager::getRunningServices based answers. Put this function in an activity-

private fun isMyServiceRunning(serviceClass: Class<out Service>) =
    (getSystemService(ACTIVITY_SERVICE) as ActivityManager)
        .getRunningServices(Int.MAX_VALUE)
        ?.map { it.service.className }
        ?.contains(serviceClass.name) ?: false
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文