Как проверить, работает ли сервис на Android? - PullRequest
873 голосов
/ 01 марта 2009

Как проверить, работает ли фоновая служба?

Я хочу, чтобы активность Android изменяла состояние службы - она ​​позволяет мне включать его, если он выключен, и выключен, если он включен.

Ответы [ 26 ]

6 голосов
/ 12 февраля 2011

onDestroy не всегда вызывается в сервисе, поэтому это бесполезно!

Например: просто запустите приложение еще раз с одним изменением из Eclipse. Приложение принудительно закрывается с помощью SIG: 9.

5 голосов
/ 13 июня 2016

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;
}
5 голосов
/ 30 марта 2011

Прежде всего, вы не должны пытаться связаться с сервисом с помощью ActivityManager. (Обсуждается здесь )

Сервисы могут работать самостоятельно, быть привязаны к Деятельности или к обоим. Чтобы проверить в Деятельности, работает ли ваша Служба или нет, нужно создать интерфейс (расширяющий Binder), в котором вы объявляете методы, понятные как Службе, так и Службе. Вы можете сделать это, создав свой собственный интерфейс, в котором вы объявляете, например, «isServiceRunning ()». Затем вы можете привязать свою активность к своей службе, запустить метод isServiceRunning (), служба сама проверит, запущена она или нет, и вернет логическое значение вашей активности.

Вы также можете использовать этот метод, чтобы остановить службу или взаимодействовать с ней другим способом.

Я использовал этот учебник , чтобы узнать, как реализовать этот сценарий в моем приложении.

4 голосов
/ 07 августа 2014

Опять же, еще одна альтернатива, которую люди могут найти чище, если они используют ожидающие намерения (например, с 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 - это константа, которую вы определяете в частном порядке в своем классе для определения ожидающих намерений, связанных с вашим сервисом.

4 голосов
/ 28 мая 2013

Для приведенного здесь варианта использования мы можем просто использовать возвращаемое значение метода stopService(). Возвращает true, если существует указанная служба и она уничтожена. Иначе он возвращает false. Таким образом, вы можете перезапустить службу, если результат false, в противном случае гарантируется, что текущая служба остановлена. :) Было бы лучше, если бы вы взглянули на this .

3 голосов
/ 19 января 2018

Ниже приведен элегантный хак, который охватывает все Ifs. Это только для местных услуг.

    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(...);
    }
2 голосов
/ 24 марта 2018

Ответ geekQ, но в классе Kotlin. Спасибо 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
}

Звонок

isMyServiceRunning(NewService::class.java)
1 голос
/ 27 марта 2014

Может быть несколько служб с одинаковым именем класса.

Я только что создал два приложения. Имя пакета первого приложения 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 экземпляров, поскольку equals() из ComponentName сравнивает как имена пакетов, так и имена классов. И на устройстве не может быть установлено два приложения с одинаковым именем пакета.

Метод equals () для 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

0 голосов
/ 09 апреля 2019

Пожалуйста, используйте этот код.

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;
    }
0 голосов
/ 15 марта 2019

Моя конверсия котлинов ответов 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...