web-dev-qa-db-ger.com

Wie überprüfe ich, ob ein Dienst unter Android läuft?

Wie überprüfe ich, ob ein Hintergrunddienst (unter Android) ausgeführt wird?

Ich möchte eine Android-Aktivität, die den Status des Dienstes umschaltet. Dadurch kann ich den Dienst aktivieren, wenn er ausgeschaltet ist.

836
Bee

Ich hatte vor kurzem das gleiche Problem. Da mein Dienst lokal war, benutzte ich einfach ein statisches Feld in der Dienstklasse, um den Status umzuschalten, wie von hackbod hier beschrieben.

EDIT (für den Datensatz):

Hier ist die von Hackbod vorgeschlagene Lösung:

Wenn Ihr Client- und Servercode Teil derselben .apk-Datei ist und Sie .__ sind. Bindung an den Dienst mit einer konkreten Absicht (eine, die die __. genaue Serviceklasse angibt), dann können Sie Ihren Dienst einfach mit einem. globale Variable, wenn sie ausgeführt wird, die Ihr Client überprüfen kann. 

Wir haben absichtlich keine API, um zu prüfen, ob ein Dienst .__ ist. Laufen, weil fast immer, wenn Sie etwas tun wollen so enden sie mit den rassenbedingungen in ihrem code. 

261
miracle2k

Ich benutze folgendes aus einer Aktivität heraus:

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 mit:

isMyServiceRunning(MyService.class)

Dies funktioniert zuverlässig, da es auf Informationen über das Ausführen von Diensten basiert, die vom Android-Betriebssystem über ActivityManager # getRunningServices bereitgestellt werden.

Alle Ansätze, die onDestroy- oder onSometing-Ereignisse oder Binders oder statische Variablen verwenden, funktionieren nicht zuverlässig, da Sie als Entwickler nie wissen, wann Android entscheidet, Ihren Prozess zu beenden oder welche der genannten Rückrufe aufgerufen werden oder nicht. Bitte beachten Sie die Spalte "killable" in der Tabelle " lifecycle events" in der Android-Dokumentation.

1577
geekQ

Ich habs! 

Sie M&UUML;SSEN rufen Sie startService() an, damit Ihr Dienst ordnungsgemäß registriert wird, und BIND_AUTO_CREATE reicht nicht aus.

Intent bindIntent = new Intent(this,ServiceTask.class);
startService(bindIntent);
bindService(bindIntent,mConnection,0);

Und jetzt die ServiceTools-Klasse:

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;
     }
}
72
Kevin Parker

Eine kleine Ergänzung ist:

Mein Ziel ist es zu wissen, ob ein Dienst ausgeführt wird, ohne dass er tatsächlich ausgeführt wird, wenn er nicht ausgeführt wird.

Das Aufrufen von bindService oder das Aufrufen einer Absicht, die vom Dienst abgefangen werden kann, ist keine gute Idee, da der Dienst gestartet wird, wenn er nicht ausgeführt wird.

Wie von miracle2k vorgeschlagen, ist es am besten, ein statisches Feld in der Serviceklasse zu haben, um zu wissen, ob der Service gestartet wurde oder nicht.

Um es noch sauberer zu machen, schlage ich vor, den Dienst in ein Singleton mit einem sehr faulen Abruf umzuwandeln: Das heißt, es gibt keine Instanziierung der Singleton - Instanz durch statische Methoden. Die statische getInstance-Methode Ihres Service/Singleton gibt nur die Instanz des Singleton zurück, wenn er erstellt wurde. Aber es startet oder instanziiert nicht den Singleton selbst. Der Dienst wird nur durch normale Dienststartmethoden gestartet.

Es wäre dann noch übersichtlicher, das Singleton-Entwurfsmuster so zu ändern, dass die verwirrende getInstance-Methode in etwas wie die isInstanceCreated() : boolean-Methode umbenannt wird.

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 Serviceklasse haben und nur für Klassen die App/das Paket des Services verfügbar ist. Wenn sich Ihre Klassen außerhalb der Service-App/des Service-Pakets befinden, können Sie den ActivityManager mit Einschränkungen abfragen, die von Pieter-Jan Van Robays hervorgehoben werden.

53
Snicolas

Sie können dies verwenden (ich habe es noch nicht ausprobiert, aber ich hoffe, dass 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 bereits ein Dienst ausgeführt wird. Wenn nicht, wird null zurückgegeben.

Siehe - public abstract ComponentName startService (Absichtsdienst).

Dies ist nicht wie eine Überprüfung, denke ich, da der Dienst gestartet wird. Sie können also stopService(someIntent); unter dem Code hinzufügen.

22
Keenan Gebze
    public boolean checkServiceRunning(){
         ActivityManager manager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
        for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) 
                {
                    if ("com.example.yourpackagename.YourServiceName"
                            .equals(service.service.getClassName())) 
                    {
                        return true;
                    }
                }
             return false;
    }
18
J.R

Ich habe eine der oben dargestellten Lösungen leicht modifiziert, aber die Klasse anstelle eines generischen Zeichenfolgennamens übergeben, um sicherzugehen, dass Zeichenfolgen verglichen werden, die von derselben Methode stammen. 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);
11
loretoparisi

Dies ist ein Auszug aus Android -Dokumenten:

Wie sendBroadcast (Intent) , aber wenn es Empfänger für .__ gibt. Die Absicht diese Funktion blockiert und sendet sie sofort aus Vor der Rückkehr.

Denken Sie an diesen Hack als "Ping" der Service, da wir synchron übertragen können, können wir Broadcasting durchführen und ein Ergebnis - synchron - auf dem UI-Thread erhalten.

Service

@Override
public void onCreate() {
   LocalBroadcastManager
     .getInstance(this)
     .registerReceiver(new ServiceEchoReceiver(), IntentFilter("ping");
}

private class ServiceEchoReceiver{
    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;   
        }
    }
9
peter

Ich möchte der Antwort von @Snicolas nur eine Anmerkung hinzufügen. Die folgenden Schritte können verwendet werden, um den Stoppservice mit/ohne Aufruf von onDestroy() zu überprüfen.

  1. onDestroy() aufgerufen: Gehen Sie zu Einstellungen -> Anwendung -> Laufende Dienste -> Wählen Sie Ihren Dienst aus und beenden Sie ihn.

  2. onDestroy() nicht aufgerufen: Gehen Sie zu Einstellungen -> Anwendung -> Anwendungen verwalten -> Wählen Sie Ihre Anwendung aus, in der Ihr Dienst ausgeführt wird, und wählen Sie "Erzwingen". Da jedoch Ihre Anwendung hier gestoppt wird, werden definitiv auch die Service-Instanzen gestoppt.

Abschließend möchte ich noch erwähnen, dass der dort erwähnte Ansatz, der eine statische Variable in der Singleton-Klasse verwendet, für mich funktioniert.

7
Paul

onDestroy wird im Dienst nicht immer aufgerufen, daher ist dies nutzlos! 

Zum Beispiel: Führen Sie die App einfach mit einer Änderung von Eclipse erneut aus. Die Anwendung wird mit SIG: 9 zwangsweise beendet.

6
Kevin Parker

Um zu überprüfen, ob ein Dienst ausgeführt wird, fragen Sie ihn einfach. Implementieren Sie einen BroadcastReceiver in Ihrem Dienst, der auf Pings Ihrer Aktivitäten reagiert. Registrieren Sie den BroadcastReceiver, wenn der Dienst gestartet wird, und heben Sie die Registrierung auf, wenn der Dienst zerstört wird. Senden Sie aus Ihrer Aktivität (oder einer anderen Komponente) eine local-Broadcast Absicht an den Dienst. Beachten Sie den subtilen 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;
            }
        }
    };
}
6
Ben H

Xamarin C # -Version:

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
Nima

Zunächst sollten Sie nicht versuchen, den Dienst über den ActivityManager zu erreichen. (Diskutiert hier )

Dienste können eigenständig ausgeführt, an eine Aktivität oder an beide gebunden sein. Sie können in einer Aktivität überprüfen, ob Ihr Dienst ausgeführt wird oder nicht, indem Sie eine Schnittstelle erstellen (die Binder erweitert), in der Sie Methoden deklarieren, die sowohl die Aktivität als auch der Dienst verstehen. Sie können dies tun, indem Sie eine eigene Schnittstelle erstellen, in der Sie beispielsweise "isServiceRunning ()" ..__ deklarieren. Sie können Ihre Activity dann an Ihren Service binden, die Methode isServiceRunning () ausführen. Der Service prüft, ob er ausgeführt wird oder nicht und kehrt zu Ihrer Aktivität zurück.

Sie können diese Methode auch verwenden, um Ihren Dienst zu stoppen oder auf andere Weise damit zu interagieren.

Ich habe dieses Tutorial verwendet, um zu lernen, wie Sie dieses Szenario in meiner Anwendung implementieren.

Für den hier angegebenen Anwendungsfall können wir einfach den Rückgabewert der stopService()-Methode verwenden. Es gibt true zurück, wenn der angegebene Dienst existiert und er beendet wird. Sonst gibt es false zurück. Sie können den Dienst also neu starten, wenn das Ergebnis false ist. Andernfalls wird sichergestellt, dass der aktuelle Dienst angehalten wurde. :) Es wäre besser, wenn Sie sich this ansehen.

4

Wieder eine andere Alternative, die Benutzer möglicherweise sauberer finden, wenn sie ausstehende Absichten verwenden (zum Beispiel mit der Variable 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);
}

Dabei ist CODE eine Konstante, die Sie privat in Ihrer Klasse definieren, um die mit Ihrem Dienst verbundenen ausstehenden Absichten zu identifizieren.

4
Snicolas

Unten ist ein eleganter Hack, der alle Ifs abdeckt. Dies gilt nur für lokale Dienste.

    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;
        }
    }

Und dann später:

    if(AService.isServiceCreated()){
        ...
    }else{
        startService(...);
    }
3
TheRealChx101

Es können mehrere Services mit demselben Klassennamen vorhanden sein. 

Ich habe gerade zwei Apps erstellt. Der Paketname der ersten App lautet com.example.mock. Ich habe ein Unterpaket namens lorem in der App und einen Dienst namens Mock2Service erstellt. Daher lautet der vollständig qualifizierte Name com.example.mock.lorem.Mock2Service.

Dann habe ich die zweite App und einen Dienst namens Mock2Service erstellt. Der Paketname der zweiten App lautet com.example.mock.lorem. Der vollständig qualifizierte Name des Dienstes lautet ebenfalls com.example.mock.lorem.Mock2Service.

Hier ist meine Logcat-Ausgabe.

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

Eine bessere Idee ist, ComponentName-Instanzen zu vergleichen, da equals() von ComponentName sowohl Paketnamen als auch Klassennamen vergleicht. Es dürfen nicht zwei Apps mit demselben Paketnamen auf einem Gerät installiert sein.

Die equals () -Methode von 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;
}

Komponentenname

1
Maksim Dmitriev

In kotlin können Sie im Begleitobjekt eine boolesche Variable hinzufügen und deren Wert in einer beliebigen Klasse überprüfen:

companion object{
     var isRuning = false

}

Ändern Sie den Wert, wenn der Dienst erstellt und zerstört wird

 override fun onCreate() {
        super.onCreate()
        isRuning = true
    }

override fun onDestroy() {
    super.onDestroy()
    isRuning = false
    }
1
Mohamed Saber

Die Antwort von geekQ ist jedoch in der Kotlin-Klasse. Danke 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
}

Der Anruf

isMyServiceRunning(NewService::class.Java)
1

In TheServiceClass definieren Sie:

 public static Boolean serviceRunning = false;

Dann in onStartCommand (...) 

 public int onStartCommand(Intent intent, int flags, int startId) {

    serviceRunning = true;
    ...
}

 @Override
public void onDestroy()
{
    serviceRunning = false;

} 

Rufen Sie dann if(TheServiceClass.serviceRunning == true) von einer beliebigen Klasse auf.

0
fullMoon

Verwenden Sie in Ihrer Service-Unterklasse einen statischen Booleschen Wert, um den Status des Dienstes zu erhalten (siehe unten).

MyService.kt

class MyService : Service() {
    override fun onCreate() {
        super.onCreate()
        isServiceStarted = true
    }
    override fun onDestroy() {
        super.onDestroy()
        isServiceStarted = false
    }
    companion object {
        var isServiceStarted = false
    }
}

MainActivity.kt

class MainActivity : AppCompatActivity(){
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val serviceStarted = FileObserverService.isServiceStarted
        if (!serviceStarted) {
            val startFileObserverService = Intent(this, FileObserverService::class.Java)
            ContextCompat.startForegroundService(this, startFileObserverService)
        }
    }
}
0
Micklo_Nerd

Meine Kotlin-Konvertierung der ActivityManager::getRunningServices-basierten Antworten. Setzen Sie diese Funktion in eine Aktivitäts-

private fun isMyServiceRunning(serviceClass: Class<out Service>) =
    (getSystemService(ACTIVITY_SERVICE) as ActivityManager)
        .getRunningServices(Int.MAX_VALUE)
        ?.map { it.service.className }
        ?.contains(serviceClass.name) ?: false
0
Gulshan

Wenn der Dienst zu einem anderen Prozess oder APK gehört, verwenden Sie die auf dem ActivityManager basierende Lösung.

Wenn Sie Zugriff auf die Quelle haben, verwenden Sie einfach die Lösung, die auf einem statischen Feld basiert. Stattdessen würde ich mit einem Boolean-Objekt ein Date-Objekt verwenden. Während der Dienst ausgeführt wird, aktualisieren Sie einfach den Wert auf 'now' und setzen Sie ihn nach Abschluss auf null. Anhand der Aktivität können Sie überprüfen, ob das Datum Null ist oder das Datum zu alt ist. Dies bedeutet, dass es nicht läuft.

Sie können auch Broadcast-Benachrichtigungen von Ihrem Dienst senden, um anzugeben, dass weitere Informationen wie der Fortschritt angezeigt werden.

0
FranMowinckel

Bitte benutzen Sie diesen Code.

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

simple use bind mit nicht automatisch erstellen - siehe ps. und aktualisieren ...

public abstract class Context {

 ... 

  /*
  * @return {true} If you have successfully bound to the service, 
  *  {false} is returned if the connection is not made 
  *  so you will not receive the service object.
  */
  public abstract boolean bindService(@RequiresPermission Intent service,
        @NonNull ServiceConnection conn, @BindServiceFlags int flags);

beispiel:

    Intent bindIntent = new Intent(context, Class<Service>);
    boolean bindResult = context.bindService(bindIntent, ServiceConnection, 0);

warum nicht verwenden? getRunningServices () 

List<ActivityManager.RunningServiceInfo> getRunningServices (int maxNum)
Return a list of the services that are currently running.

Hinweis: Diese Methode ist nur zum Debuggen oder Implementieren von Benutzerschnittstellen vom Typ "Service Management" vorgesehen.


ps. Android-Dokumentation ist irreführend Ich habe ein Problem mit dem Google-Tracker geöffnet, um alle Zweifel auszuräumen:

https://issuetracker.google.com/issues/68908332

wie wir sehen, ruft der Bindedienst tatsächlich eine Transaktion über den ActivityManager-Binder über die Zwischenspeicherbindungen des Dienstes auf - ich kann nicht nachvollziehen, welcher Dienst für das Binden zuständig ist.

int res = ActivityManagerNative.getDefault().bindService(...);
return res != 0;

transaktion erfolgt über Binder:

ServiceManager.getService("activity");

nächster:

  public static IBinder getService(String name) {
    try {
        IBinder service = sCache.get(name);
        if (service != null) {
            return service;
        } else {
            return getIServiceManager().getService(name);

dies wird in ActivityThread eingestellt über:

 public final void bindApplication(...) {

        if (services != null) {
            // Setup the service cache in the ServiceManager
            ServiceManager.initServiceCache(services);
        }

dies wird in ActivityManagerService in der Methode aufgerufen:

 private final boolean attachApplicationLocked(IApplicationThread thread,
            int pid) {
    ...
    thread.bindApplication(... , getCommonServicesLocked(),...)

dann: 

 private HashMap<String, IBinder> getCommonServicesLocked() {

aber es gibt keine "Aktivität" nur Fensterpaket und Alarm ..

also müssen wir uns wieder anrufen: 

 return getIServiceManager().getService(name);

    sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());

das macht einen Anruf durch:

    mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);

was dazu führt :

BinderInternal.getContextObject()

und das ist eine native Methode ....

  /**
     * Return the global "context object" of the system.  This is usually
     * an implementation of IServiceManager, which you can use to find
     * other services.
     */
    public static final native IBinder getContextObject();

ich habe jetzt keine Zeit, um in c zu graben, so dass ich meine Antwort suspendiere, bis ich den Rest-Aufruf durchsehe.

, aber am besten prüfen Sie, ob der Dienst ausgeführt wird, indem Sie bind erstellen (wenn der Dienst nicht erstellt wurde, ist der Dienst nicht vorhanden) - und den Dienst über den Bindungsstatus abfragen (mithilfe des gespeicherten internen Flags).

update 23.06.2018

ich fand diese interessant:

/**
 * Provide a binder to an already-bound service.  This method is synchronous
 * and will not start the target service if it is not present, so it is safe
 * to call from {@link #onReceive}.
 *
 * For peekService() to return a non null {@link Android.os.IBinder} interface
 * the service must have published it before. In other words some component
 * must have called {@link Android.content.Context#bindService(Intent, ServiceConnection, int)} on it.
 *
 * @param myContext The Context that had been passed to {@link #onReceive(Context, Intent)}
 * @param service Identifies the already-bound service you wish to use. See
 * {@link Android.content.Context#bindService(Intent, ServiceConnection, int)}
 * for more information.
 */
public IBinder peekService(Context myContext, Intent service) {
    IActivityManager am = ActivityManager.getService();
    IBinder binder = null;
    try {
        service.prepareToLeaveProcess(myContext);
        binder = am.peekService(service, service.resolveTypeIfNeeded(
                myContext.getContentResolver()), myContext.getOpPackageName());
    } catch (RemoteException e) {
    }
    return binder;
}

zusamenfassend :) 

"Einen Binder für einen bereits gebundenen Dienst bereitstellen. Diese Methode ist synchron und startet den Zieldienst nicht, wenn er nicht vorhanden ist."

public IBinder peekService (Intent-Dienst, String resolvedType, String callingPackage) löst RemoteException aus;

*

public static IBinder peekService(IBinder remote, Intent service, String resolvedType)
             throws RemoteException {
    Parcel data = Parcel.obtain();
    Parcel reply = Parcel.obtain();
    data.writeInterfaceToken("Android.app.IActivityManager");
    service.writeToParcel(data, 0);
    data.writeString(resolvedType);
    remote.transact(Android.os.IBinder.FIRST_CALL_TRANSACTION+84, data, reply, 0);
    reply.readException();
    IBinder binder = reply.readStrongBinder();
    reply.recycle();
    data.recycle();
    return binder;
}

*

0
ceph3us

Für Kotlin können Sie den folgenden Code verwenden.

fun isMyServiceRunning(calssObj: Class<SERVICE_CALL_NAME>): Boolean {
    val manager = requireActivity().getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
    for (service in manager.getRunningServices(Integer.MAX_VALUE)) {
        if (calssObj.getName().equals(service.service.getClassName())) {
            return true;
        }
    }
    return false;
}
0

Dies gilt mehr für das Debuggen von Intent-Diensten, da sie einen Thread erzeugen, es kann jedoch auch für reguläre Dienste funktionieren. Ich habe diesen Thread dank Binging gefunden

In meinem Fall habe ich mit dem Debugger herumgespielt und die Threadansicht gefunden. Es sieht aus wie das Aufzählungszeichen-Symbol in MS Word. Sie müssen sich jedoch nicht im Debugger-Modus befinden, um sie verwenden zu können. Klicken Sie auf den Prozess und klicken Sie auf diese Schaltfläche. Alle Intent Services werden angezeigt, während sie ausgeführt werden, zumindest im Emulator.

0
Joe Plante