Android: проверьте, работает ли служба через. bindService

Как лучше всего проверить, запущена ли служба Android? Мне известен ActivityManager API, но похоже, что использование API не рекомендуется для сценариев, подобных моему (источник). Я также знаю о возможности использования глобальных / постоянных переменных для поддержания состояния службы.

Я попытался использовать bindService с флагами, установленными на 0, но у меня возникли те же проблемы, что и у человека по ссылке source (единственное исключение было, я пробовал bindService с локальной службой).

Следующий звонок

getApplicationContext().bindService(new Intent(getApplicationContext(),
        MyService.class), mServiceConnection, 0);

всегда возвращает истину, но не подключается. Это ожидаемое поведение? Мне кажется, что bindService должен возвращать false, если служба еще не запущена (это не так, я это проверил) или если флаг BIND_AUTO_CREATE не установлен (опять же, это не так).


person Igor    schedule 14.12.2010    source источник


Ответы (7)


У меня такая же проблема; кажется, наиболее известным решением является создание общедоступного статического логического значения в WhateverService, для которого установлено значение true во время onCreate (или onStartCommand, по вашему выбору) и false во время onDestroy. Затем вы можете получить к нему доступ из любого другого класса в том же apk. Хотя это может быть спорно. В Android нет API для проверки работы службы (без побочных эффектов): см. http://groups.google.com/group/android-developers/browse_thread/thread/8c4bd731681b8331/bf3ae8ef79cad75d

Я полагаю, что состояние гонки возникает из-за того, что ОС может убить удаленную службу (в другом процессе) в любое время. Проверка локальной службы (тот же процесс), как предложено выше, кажется мне без гонок - если ОС убивает службу, она убивает и все, что проверяло ее статус.

person bryanr    schedule 04.01.2011

Используйте общие настройки, чтобы сохранить флаг работы службы.

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    int res = super.onStartCommand(intent, flags, startId);
    setRunning(true);
    return res;
}

@Override
public void onDestroy() {
    super.onDestroy();
    setRunning(false);
}

private void setRunning(boolean running) {
    SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
    SharedPreferences.Editor editor = pref.edit();

    editor.putBoolean(PREF_IS_RUNNING, running);
    editor.apply();
}

public static boolean isRunning(Context ctx) {
    SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(ctx.getApplicationContext());
    return pref.getBoolean(PREF_IS_RUNNING, false);
}
person Андрей Москвичёв    schedule 28.01.2013
comment
Это не очень хорошая идея, SharedPreferences сохраняются в энергонезависимом хранилище, поэтому, если по какой-то причине устройство выйдет из строя или потеряет питание, ваш onDestroy не будет вызываться, и при следующем запуске ваше приложение будет думать, что служба работает, даже если оно не является. - person satur9nine; 26.06.2015
comment
Да, я согласен. SharedPreferences для этого не предназначены. Но служба, выполняющая pref, может быть удалена при запуске приложения. Другой способ: сохранить сервис, работающий с bool var, в объекте Application. - person Андрей Москвичёв; 27.06.2015
comment
onDestroy не всегда звонит - person AndroidGeek; 26.11.2016
comment
Лучше сохранить статическое логическое значение вместо него, потому что, если пользователь убьет приложение (например, очистит последние приложения) или устройство неожиданно выключится (например, низкий заряд батареи), общие предпочтения все равно останутся верными. - person Erick M. Sprengel; 06.06.2017

Другой способ:

public static boolean isServiceRunning(Context ctx, String serviceClassName) {
    ActivityManager manager = (ActivityManager) ctx.getSystemService(Context.ACTIVITY_SERVICE);
    for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
        if (TrackingService.class.getName().equals(serviceClassName)) {
            return true;
        }
    }
    return false;
}
person Андрей Москвичёв    schedule 15.02.2013
comment
Когда я использую приведенный выше код, он дает мне информацию только о запущенных в системе службах. Ищу все сервисы, включая ту, которую я создал - person user1810931; 13.03.2013

У меня была такая же потребность, и я обнаружил, что запуск .bindService с уже привязанным чем-то еще может вызвать ошибки. Я сделал это прямо перед запуском .bindService

try{
    context.unbindService(fetch_connection);
} catch (IllegalArgumentException e){
    System.out.println("Unbinding didn't work. little surprise");
}
person atraudes    schedule 14.12.2010
comment
Это просто проверяет, привязаны ли вы к услуге. Нет, запущено оно или нет. - person Falmarri; 14.12.2010

См. Ответ здесь:

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

person Kevin Parker    schedule 12.02.2011

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

  button.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {

            Intent intent=new Intent(MainActivity.this, MyService.class);
            //startService(intent);
            bindService(intent,serviceConnection,BIND_AUTO_CREATE);
            if (myService!=null)
            {
                myService.RecData(editText.getText().toString());
            }
        }
    });
}

ServiceConnection serviceConnection=new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
        Toast.makeText(MainActivity.this,"onServiceConnected called",Toast.LENGTH_SHORT).show();
        MyService.MyBinder myBinder= (MyService.MyBinder) iBinder;
        myService= myBinder.getServiceInstant();
        myService.SetActivity(MainActivity.this);
        myService.RecData(editText.getText().toString());
    }
person The Black Horse    schedule 14.09.2016

Что вы планируете делать, если служба работает / не работает? Почему бы просто не позвонить startService(). Это создаст его, если он не запущен, и если это так, он вызовет свой метод onStart ().

person Falmarri    schedule 14.12.2010
comment
Допустим, я хотел бы напечатать сообщение «Служба работает» или «Служба не запущена». Вот почему я должен получить информацию, работает служба или нет. Я не могу этого сделать с помощью startService. - person Igor; 14.12.2010
comment
Но зачем вам печатать это сообщение? Есть только 2 вещи, которые вы можете сделать, если служба не работает. Либо запускать, либо нет. - person Falmarri; 14.12.2010
comment
Потому что я хотел бы сообщить пользователю, запущена служба или нет. Пользователь должен запускать и останавливать службу вручную (с помощью нажатия кнопки). Когда пользователь закрывает действие (кнопка НАЗАД), служба должна продолжать работать. И активность должна знать, когда пользователь запустит ее в следующий раз, что служба уже запущена. - person Igor; 15.12.2010
comment
Я думаю, что сообщать пользователю об услугах - это вообще плохая идея. Вместо этого расскажите пользователю о функциях. Если вы не можете выполнить функцию, потому что не подключены к службе, аккуратно завершите работу и сообщите об этом пользователю. Если вы скажете пользователю, что служба запущена каждый раз, когда он запускает ваше приложение, это будет действительно раздражать. Их не волнует, запущена ли служба, все, что им нужно, - это функциональность. - person Falmarri; 15.12.2010
comment
Хорошо, я вижу, что я не дал здесь достаточно информации - я сказал, что действие будет печатать сообщение, чтобы указать, какой тип информации будет необходим (запущена служба или нет) в определенное время (при запуске активности). Я действительно не имел в виду сосредоточиться на аспекте удобства использования, поскольку другие приложения используют похожие шаблоны (например, музыкальный проигрыватель Android), а скорее на том, как это можно сделать. Итак, позвольте мне перефразировать свой вопрос - как музыкальный проигрыватель Android знает, когда показывать кнопку воспроизведения (музыкальный проигрыватель остановлен) при запуске активности, а когда показывать кнопку паузы (mp запущен)? - person Igor; 20.12.2010