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.
/**
* 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;
}
Ein Auszug aus Android docs:
Wie sendBroadcast(Intent) aber wenn es Empfänger gibt für Intent gibt, wird diese Funktion blockieren und sie sofort versenden. bevor sie zurückkehrt.
Stellen Sie sich diesen Hack als "Anpingen" der Service
. Da wir synchron senden können, können wir senden und ein Ergebnis erhalten synchron auf dem 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;
}
}
Der Gewinner in vielen Anwendungen ist natürlich ein statisches boolesches Feld des Dienstes, das auf true
en Service.onCreate()
und an false
en Service.onDestroy()
weil es viel einfacher ist.
Dies ist eine viel bessere Lösung als die akzeptierte, die fehlschlägt, wenn Android den Dienst beendet, da die globale Variablenmethode immer noch anzeigen würde, dass der Dienst läuft, obwohl er es in Wirklichkeit nicht mehr tut. Dieser synchrone Ping-Pong-Broadcast-Trick ist tatsächlich die EINZIGE verlässliche Methode, um zu prüfen, ob ein Dienst noch aktiv ist. Nur so können Sie den Dienst einfach fragen, ob er vorhanden ist. Wenn er antwortet, ist der Dienst aktiv und läuft, wenn nicht, wurde er entweder nicht gestartet oder heruntergefahren, entweder programmatisch oder vom System, um Speicherplatz zu gewinnen.
LocalBroadcastManager ist veraltet: developer.Android.com/reference/androidx/localbroadcastmanager/
Ein anderer Ansatz mit Kotlin. Inspiriert durch die Antworten anderer Benutzer
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 }
}
Als Kotlin-Erweiterung
fun Context.isMyServiceRunning(serviceClass: Class<*>): Boolean {
val manager = this.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
return manager.getRunningServices(Integer.MAX_VALUE)
.any { it.service.className == serviceClass.name }
}
Verwendung
context.isMyServiceRunning(MyService::class.java)
Der richtige Weg, um zu prüfen, ob ein Dienst läuft, ist, ihn einfach zu fragen. Implementieren Sie einen BroadcastReceiver in Ihrem Dienst, der auf Pings von Ihren Aktivitäten antwortet. Registrieren Sie den BroadcastReceiver, wenn der Dienst startet, und heben Sie die Registrierung auf, wenn der Dienst zerstört wird. Von Ihrer Aktivität (oder einer beliebigen Komponente), senden Sie eine lokale Übertragung und wenn er antwortet, wissen Sie, dass er läuft. Beachten Sie den feinen Unterschied zwischen ACTION_PING und ACTION_PONG im folgenden Code.
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;
}
}
};
}
Dieser Ansatz gefällt mir eigentlich. Es ist ein wenig schwer Code weise aber wird immer funktionieren. Ich sehe nicht, dass Broadcast-Intents in absehbarer Zeit veraltet sein werden :)
Und ... LocalBroadcastManager ist jetzt veraltet ... (Randnotiz). Es ist aber trotzdem eine gute Lösung.
Ich habe eine der oben vorgestellten Lösungen geringfügig geändert, indem ich die Klasse anstelle eines generischen Zeichenkettennamens übergeben habe, um sicher zu sein, dass die Zeichenketten, die aus der gleichen Methode kommen, verglichen werden 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;
}
}
und dann
Boolean isServiceRunning = ServiceTools.isServiceRunning(
MainActivity.this.getApplicationContext(),
BackgroundIntentService.class);
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