Wie kann ich überprüfen, ob ein Hintergrunddienst läuft?
Ich möchte eine Android-Aktivität, die den Status des Dienstes umschaltet - ich kann ihn einschalten, wenn er ausgeschaltet ist, und ausschalten, wenn er eingeschaltet ist.
Wie kann ich überprüfen, ob ein Hintergrunddienst läuft?
Ich möchte eine Android-Aktivität, die den Status des Dienstes umschaltet - ich kann ihn einschalten, wenn er ausgeschaltet ist, und ausschalten, wenn er eingeschaltet ist.
Ich verwende das Folgende innerhalb einer Aktivität:
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;
}
Und ich nenne es nutzen:
isMyServiceRunning(MyService.class)
Dies funktioniert zuverlässig, da es auf den Informationen über laufende Dienste basiert, die vom Android-Betriebssystem über ActivityManager#getRunningServices .
Alle Ansätze, die onDestroy- oder onSometing-Ereignisse oder Binder oder statische Variablen verwenden, werden nicht zuverlässig funktionieren, da man als Entwickler nie weiß, wann Android sich entscheidet, den Prozess zu beenden oder welche der genannten Callbacks aufgerufen werden oder nicht. Bitte beachten Sie die Spalte "killable" in der Tabelle der Lebenszyklusereignisse in der Android-Dokumentation.
Vermutlich ist dafür die Berechtigung erforderlich, laufende Anwendungen und Dienste anzuzeigen? Nicht ideal.
Vielen Dank für diese Lösung. Ich möchte hinzufügen: Statt "com.example.MyService" ist es eleganter, MyService.class.getName() zu verwenden.
Ich hatte vor nicht allzu langer Zeit das gleiche Problem. Da mein Dienst lokal war, endete ich einfach mit einem statischen Feld in der Serviceklasse, um den Zustand umzuschalten, wie von Hackbod beschrieben aquí
EDIT (für das Protokoll):
Hier ist die von hackbod vorgeschlagene Lösung:
Wenn Ihr Client- und Servercode Teil der gleichen .apk ist und Sie mit einem konkreten Intent an den Dienst binden (einer, der die Dienstklasse spezifiziert), dann können Sie einfach Ihren Dienst eine globale Variable setzen lassen, die Ihr Client überprüfen kann, wenn er läuft.
Wir haben absichtlich keine API, um zu prüfen, ob ein Dienst läuft, denn wenn man so etwas tun will, landet man fast immer wenn Sie so etwas tun wollen, enden Sie mit Race Conditions in Ihrem Code.
Dies wird schneller ausgeführt als die Antwort von @geekQ (jetzt die am höchsten bewertete), aber ich frage mich, ob der Verweis auf den Service dazu führt, dass diese Klasse in die Receiver-Komponente aufgenommen wird - die so klein wie möglich gehalten werden sollte.
@Pacerier, die Lösung, auf die Sie verweisen, erfordert den Start des Dienstes, und ich denke, die beste flexible Lösung sollte es Ihnen ermöglichen, zu überprüfen, ob ein Dienst läuft, ohne ihn zu starten.
+1 Diese Methode ist nachhaltiger. Die von @geekQ angebotene Methode funktioniert nicht unter Android KitKat.
Ich hab's!
Sie MUSS aufrufen startService()
damit Ihr Dienst ordnungsgemäß registriert und zugelassen wird BIND_AUTO_CREATE
reicht nicht aus.
Intent bindIntent = new Intent(this,ServiceTask.class);
startService(bindIntent);
bindService(bindIntent,mConnection,0);
Und nun die Klasse 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;
}
}
Hier werden doch nur die Systemdienste aufgelistet, oder?! Also ist mein lokaler Dienst von der Liste ausgeschlossen und ich bekomme false ;(
Das funktioniert bei externen Diensten, bei lokalen Diensten ist es ziemlich offensichtlich, wenn man sie laufen lässt.
Tut mir leid, aber ich muss sagen, dass das eine sehr dumme Antwort ist Warum ist das so offensichtlich?!
Eine kleine Ergänzung ist:
Mein Ziel ist es, zu wissen, ob ein Dienst läuft, ohne ihn tatsächlich zu starten, wenn er nicht läuft.
Der Aufruf von bindService oder der Aufruf eines Intents, der vom Dienst abgefangen werden kann, ist keine gute Idee, da der Dienst gestartet wird, wenn er nicht läuft.
Wie miracle2k vorschlug, ist es daher am besten, ein statisches Feld in der Dienstklasse zu haben, um zu wissen, ob der Dienst gestartet wurde oder nicht.
Um es noch sauberer zu machen, schlage ich vor, den Dienst in ein Singleton mit einem sehr trägen Abruf umzuwandeln: Das heißt, es gibt überhaupt keine Instanziierung der Einzelperson Instanz durch statische Methoden. Die statische getInstance-Methode Ihres Dienstes/Singletons gibt nur die Instanz des Singletons zurück, wenn es erstellt wurde. Aber sie startet oder instanziiert das Singleton selbst nicht. Der Dienst wird nur über die normalen Startmethoden des Dienstes gestartet.
Es wäre dann noch sauberer, das Singleton-Entwurfsmuster zu ändern und die verwirrende getInstance-Methode in etwas wie isInstanceCreated() : boolean
Methode.
Der Code wird wie folgt aussehen:
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
Diese Lösung ist elegant, aber sie ist nur relevant, wenn Sie Zugriff auf die Dienstklasse haben, und nur für Klassen außerhalb der Anwendung/des Pakets des Dienstes. Wenn Ihre Klassen außerhalb der Dienstanwendung/des Dienstpakets liegen, können Sie den ActivityManager mit den von Pieter-Jan Van Robays hervorgehobenen Einschränkungen abfragen.
Warum nicht, jemand muss immer noch stop aufrufen, um einen Dienst zu stoppen, und das führt dazu, dass onDestroy aufgerufen wird.
Wenn das System auf Speicher niedrig ist, wird Ihr Dienst automatisch ohne einen Aufruf Ihrer onDestroy beendet werden, weshalb ich sage, dass dies fehlerhaft ist.
Sie können dies verwenden (ich habe es noch nicht ausprobiert, aber ich hoffe, es funktioniert):
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();
}
Die startService-Methode gibt ein ComponentName-Objekt zurück, wenn es bereits einen laufenden Dienst gibt. Wenn nicht, wird null zurückgegeben.
参照 public abstract ComponentName startService (Intent service) .
Dies ist nicht wie eine Überprüfung, denn es startet den Dienst, so dass Sie die stopService(someIntent);
unter dem Kodex.
Das ist nicht ganz das, was in den Unterlagen steht. Laut Ihrem Link: "Rückgabe Wenn der Dienst gestartet wird oder bereits läuft, wird der Komponentenname des tatsächlich gestarteten Dienstes zurückgegeben; andernfalls, wenn der Dienst nicht existiert, wird null zurückgegeben."
Das ist nicht der richtige Weg, denn wenn die IDE auslöst if(startService(someIntent) != null)
die prüft, ob IsserviceRunning
aber das wird auch neue Dienste spielen.
CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.
2 Stimmen
Überprüfen Sie dieser deutsche Leitfaden .
23 Stimmen
Die richtige Antwort steht unten und nicht die markierte: stackoverflow.com/a/5921190/2369122
2 Stimmen
@toidiu Wenn das nicht schon nerfed worden ist wie
getRunningTasks()
dann wird es wahrscheinlich so sein.0 Stimmen
Mit der Funktion getSystemService() können Sie alle laufenden Dienste abrufen. Gehen Sie die Liste in einer Schleife durch und prüfen Sie, ob Ihr Dienst in der Liste vorhanden ist. wiki.workassis.com/Android-check-the-service-is-running