Android: проверьте, работает ли служба. bindService
Каким будет лучший способ проверить, работает ли Android-сервис? Я знаю API ActivityManager
, но похоже, что использование API не рекомендуется для сценариев, подобных моим (source), Я также знаю о возможности использования глобальных/постоянных переменных для поддержания состояния службы.
Я попытался использовать bindService
с флагами, установленными на 0
, но у меня были те же проблемы, что и у человека в исходной ссылке (единственное исключение было, я пытался использовать bindService
с локальной службой).
Следующий вызов
getApplicationContext().bindService(new Intent(getApplicationContext(),
MyService.class), mServiceConnection, 0);
всегда возвращает true, но не подключается. Это ожидаемое поведение? Мне кажется, что bindService
должен возвращать false, если служба еще не запущена (это не так, я это проверил) или если флаг BIND_AUTO_CREATE
не установлен (опять же это не так).
Ответы
Ответ 1
У меня такая же проблема; кажется, наиболее известным решением является создание публичного статического булева в WhateverService, установленного в true во время onCreate (или onStartCommand, ваш выбор) и false во время onDestroy. Затем вы можете получить доступ к нему из любого другого класса в одном и том же apk. Однако это может быть расовым. В Android нет API для проверки работоспособности службы (без побочных эффектов): см. http://groups.google.com/group/android-developers/browse_thread/thread/8c4bd731681b8331/bf3ae8ef79cad75d
Я полагаю, что состояние гонки связано с тем, что ОС может в любой момент убить удаленную службу (в другом процессе). Проверка локальной службы (такой же процесс), как было предложено выше, кажется безгорной для меня - если ОС убивает службу, она убивает все, что проверяет ее статус.
Ответ 2
Использовать общую привилегию для сохранения флага службы.
@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);
}
Ответ 3
Другой метод:
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;
}
Ответ 4
У меня была такая же потребность, и я обнаружил, что работает .bindService с еще что-то уже связанным, что это вызовет ошибки. Я сделал это прямо перед запуском .bindService
try{
context.unbindService(fetch_connection);
} catch (IllegalArgumentException e){
System.out.println("Unbinding didn't work. little surprise");
}
Ответ 5
Что вы планируете делать, если служба работает/не работает? Почему бы просто не позвонить startService()
. Это создаст его, если он не будет запущен, и если он будет вызван его методом onStart().
Ответ 6
См. ответ здесь:
Как проверить, работает ли служба на Android?
Ответ 7
в вашей деятельности вы можете просто проверить его, используя экземпляр вашего сервиса
в моем случае я сделал это с помощью
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());
}