Frage

Wie kann ich überprüfen, ob ein Hintergrunddienst ausgeführt wird?

Ich mag eine Android-Aktivität, die den Status des Dienstes schaltet - es mich läßt einschalten, wenn es ausgeschaltet ist, und ausgeschaltet, wenn es auf

.
War es hilfreich?

Lösung

Ich hatte das gleiche Problem nicht vor langer Zeit. Da mein Service vor Ort war, landete ich einfach ein statisches Feld in der Serviceklasse mit Zustand zu wechseln, wie durch hackbod hier

EDIT (zur Erinnerung):

Hier wird die Lösung durch hackbod vorgeschlagen:

  

Wenn Ihr Client und Server-Code ist Teil der gleichen APK und Sie sind   Bindung an den Dienst mit einem konkreten Intent (einer, die angibt,   genaue Service-Klasse), dann können Sie einfach haben Ihre Service-Set ein   globale Variable, wenn es ausgeführt wird, dass Ihr Kunde überprüfen kann.

     

Wir haben bewusst keine API zu überprüfen, ob ein Dienst   laufen, weil, ohne fast scheitern, wenn Sie etwas tun wollen   wie das am Ende mit Rennbedingungen in Ihrem Code auf.

Andere Tipps

Ich verwende die folgende aus dem Innern 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 mit:

isMyServiceRunning(MyService.class)

Das funktioniert zuverlässig, weil es durch das Android-Betriebssystem durch Activity # getRunningServices .

die Ansätze Alle onDestroy oder onSometing Ereignisse oder Bindemittel oder statische Variablen verwenden, weil als Entwickler nicht zuverlässig arbeiten Sie nie wissen, wann Android entscheidet Ihr Prozess oder welche der genannten Rückrufe zu töten genannt werden oder nicht. Bitte beachten Sie die „angreifbar“ Spalte in der Lifecycle Ereignistabelle in der Android-Dokumentation.

Verstanden!

Sie muss Anruf startService() für Ihren Dienst ordnungsgemäß registriert werden und vorbei BIND_AUTO_CREATE wird nicht ausreichen.

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

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

Eine kleine Ergänzung ist:

Mein Ziel ist es zu wissen, ob ein Dienst ohne actualy läuft er ausgeführt wird, wenn es nicht läuft.

Beim bindService oder eine Absicht aufrufen, die durch den Dienst gefangen werden kann, ist keine gute Idee, dann, wie es den Dienst zu starten, wenn es nicht läuft.

So, wie miracle2k vorgeschlagen, ist die beste ein statisches Feld in der Serviceklasse zu haben, zu wissen, ob der Dienst gestartet wurde oder nicht.

Um es noch sauber, schlage ich vor, den Dienst in einem Singleton mit einem sehr, sehr faul fetching zu verwandeln: das heißt, es gibt keine Instanziierung überhaupt den Singleton Beispiel durch statische Methoden. Die statische getInstance Methode Ihres Service / Singleton gibt nur die Instanz des Singleton, wenn es erstellt wurde. Aber es ist nicht actualy startet oder instanziiert die Singleton selbst. Der Dienst wird durch die normalen Dienststart Methoden nur dann gestartet.

Es wäre dann noch sauberer sein, das Singleton-Entwurfsmuster zu modifizieren, um die verwirrende getInstance Methode in so etwas wie die isInstanceCreated() : boolean Methode zu umbenennen.

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 es ist nur relevant, wenn Sie den Zugriff auf die Serviceklasse haben und nur für die Klassen ISIDE das app / Paket des Dienstes. Wenn Ihre Klassen außerhalb des Dienstes app / Paket sind dann könnten Sie die Activitymanager mit Einschränkungen durch Pieter-Jan Van Robays unterstrichen abgefragt werden.

Sie können diese verwenden (ich habe nicht versucht, dies noch nicht, aber ich hoffe, das 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 Methode Start gibt ein Component Objekt, wenn es einen bereits laufenden Betrieb ist. Wenn nicht, wird null zurückgeführt werden.

Siehe public abstract Componentstartservice (Intent-Service) .

Dies ist nicht so, Kontrolle Ich denke, weil sie den Dienst fängt, so dass Sie stopService(someIntent); unter dem Code hinzufügen können.

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

Ich habe etwas eine der Lösungen modifiziert oben dargestellt, sondern von einem allgemeinen string namen der Klasse vorbei, um sicher zu sein, Zeichenfolge vergleichen aus der gleichen Methode class.getName() coming out

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

Ein Auszug aus Android docs:

  

Wie sendBroadcast (Intent ), aber wenn es irgendwelche Empfänger für   Die Absicht blockiert diese Funktion und sofort versenden sie   vor der Rückkehr.

Denken Sie an diesem Hack als die Service „Pingen“ , da wir übertragen können synchron können wir übertragen und ein Ergebnis bekommen - synchron -. Auf dem UI-Thread

Service

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

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

Ich will nur eine Notiz auf die Antwort von @Snicolas hinzuzufügen. Die folgenden Schritte verwendet werden können Stop-Service mit / ohne onDestroy() aufrufen.

prüfen
  1. onDestroy() genannt. Gehen Sie zu Einstellungen -> Anwendungen -> Running Services -> Wählen Sie und Ihren Dienst beenden

  2. onDestroy() nicht aufgerufen: Gehen Sie zu Einstellungen -> Anwendungen -> Anwendungen verwalten -> auswählen und "Force-Stop" Ihre Anwendung in dem Ihr Dienst ausgeführt wird. Jedoch, wie Ihre Anwendung hier gestoppt wird, also auf jeden Fall die Service-Instanzen wird auch gestoppt werden.

Schließlich möchte ich erwähnen, dass der Ansatz eine statische Variable in Singleton-Klasse erwähnte für mich funktioniert.

onDestroy ist nicht immer im Dienst genannt, so ist dies nutzlos!

Zum Beispiel: einfach die App läuft wieder mit einem Wechsel von Eclipse-. Die Anwendung wird mit SIG gewaltsam beendet: 9.

Der richtige Weg, um zu überprüfen, ob ein Dienst läuft, einfach zu fragen. Implementieren Sie eine BroadcastReceiver in Ihrem Dienst, der von Ihren Aktivitäten auf Pings reagiert. Registrieren Sie den BroadcastReceiver, wenn der Dienst gestartet wird, und es abzumelden, wenn der Dienst nicht zerstört wird. Aus Ihrer Tätigkeit (oder jede Komponente), ein lokalen Broadcast senden Absicht, den Service und die, wenn sie reagiert, wissen Sie, es läuft. Notieren Sie sich den feinen Unterschied zwischen ACTION_PING und ACTION_PONG im Code unten.

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

Zu allererst musn't versuchen Sie, den Dienst zu erreichen, indem Sie den Activitymanager verwenden. (Diskutiert hier )

Dienste können allein laufen, zu einer Aktivität oder beide gebunden sein. Die Art und Weise in einer Aktivität zu überprüfen, ob Ihr Dienst ausgeführt wird oder nicht, ist durch eine Schnittstelle zu machen (das sich Binder), wo Sie Methoden deklarieren, die sowohl die Aktivität als auch die Dienstleistung, verstehen. Sie können dies tun, indem Sie Ihre eigene Schnittstelle zu machen, wo man zum Beispiel „isServiceRunning ()“ erklären. Anschließend können Sie Ihre Aktivität zu Ihrem Dienst binden, wobei das Verfahren isServiceRunning run (), wird der Dienst für sich selbst überprüfen, ob es läuft oder nicht und gibt einen booleschen auf Ihre Aktivität.

Sie können auch diese Methode verwenden, den Service zu stoppen oder mit ihm in einer anderen Art und Weise interagieren.

Ich habe diese Tutorial in meiner Anwendung zu erfahren, wie dieses Szenario zu implementieren.

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

Für den Anwendungsfall gegeben hier können wir einfach nutzen die stopService() Methode Rückgabewert machen. Es gibt true, wenn den angegebenen Dienst vorhanden ist und es getötet wird. Else kehrt false. So können Sie den Dienst neu starten, wenn das Ergebnis false ist sonst ist sichergestellt, dass der aktuelle Dienst gestoppt wurde. :) Es wäre besser, wenn Sie einen Blick auf diese .

Wieder eine andere Alternative, die Leute könnten sauberer finden, wenn sie anhängig Absichten verwenden (zum Beispiel mit dem 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);
}

Wo CODE eine Konstante ist, dass Sie privat in Ihrer Klasse definieren die anstehenden Absichten zu Ihrem Dienst zugeordnet zu identifizieren.

Im Folgenden finden Sie ein elegantes Hack, der alle Ifs abdeckt. Dies ist für lokale Dienste nur.

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

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

Die Antwort von geekQ aber in Kotlin Klasse. Dank 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 Aufruf

isMyServiceRunning(NewService::class.java)

Es kann mehr Dienste mit den gleichen Klassennamen sein.

Ich habe gerade zwei Apps erstellt. Der Paketname des ersten App ist com.example.mock. Ich habe eine subpackage genannt lorem in der App und ein Dienst namens Mock2Service. So seine vollständig qualifizierten Namen ist com.example.mock.lorem.Mock2Service.

Dann habe ich die zweite App und ein Dienst namens Mock2Service. Der Paketname des zweiten App ist com.example.mock.lorem. Der vollständig qualifizierte Name des Dienstes ist com.example.mock.lorem.Mock2Service auch.

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, weil equals() von ComponentName beiden Paketnamen und Klassennamen vergleicht. Und es kann nicht zwei Anwendungen wird mit dem gleichen Paketnamen auf einem Gerät installiert.

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

Component

Dies gilt mehr in Richtung Intent Service-Debugging, da sie einen Thread erzeugen, kann aber auch für die regelmäßigen Dienste arbeiten. Ich fand dieses Thema dank Binging

In meinem Fall spielte ich mit dem Debugger um und die Themenübersicht zu finden. Es sieht ein bisschen wie das Aufzählungszeichen-Symbol in MS Word. Wie auch immer, man muss es nicht sein, im Debugger-Modus zu verwenden. Klicken Sie auf den Prozess, und klicken Sie auf diese Schaltfläche. Jegliche Absicht Dienstleistungen wird sich zeigen, während sie laufen, zumindest auf dem Emulator.

Wenn der Dienst gehört zu einem anderen Prozess oder APK die Lösung auf dem Activitymanager basiert.

Wenn Sie den Zugriff auf die Quelle haben, benutzen Sie einfach die Lösung, basierend auf einem statischen Feld. Aber anstatt eine boolean mit würde ich ein Date-Objekt vorschlagen, mit. Während der Dienst ausgeführt wird, aktualisieren Sie einfach den Wert auf ‚jetzt‘ und wenn es gesetzt beendet sie auf null. Von der Aktivität können Sie überprüfen, ob sein null oder das Datum zu alt ist, was bedeuten wird, dass es nicht läuft.

Sie können auch Broadcast-Meldung von Ihrem Service senden, die anzeigt, dass entlang weitere Informationen wie Fortschritt ausgeführt wird.

Innerhalb TheServiceClass definieren:

 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;

} 

Dann ruft if(TheServiceClass.serviceRunning == true) aus jeder Klasse.

einfache Bedienung bindet mit nicht schaffen auto - 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 nur für das Debuggen gedacht oder Service-Management-Typ Benutzeroberflächen Implementierung


ps. android Dokumentation ist irreführend, ich habe ein Problem auf Google-Tracker zu beseitigen alle Zweifel geöffnet:

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

als wir bindet Dienst ruft tatsächlich eine Transaktion über Activity Bindemittel durch Service-Cache Bindemittel sehen - i Spur DINT, den Service für die Bindung verantwortlich ist, sondern, wie wir das Ergebnis für bind sehen können, ist:

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

Transaktion wird durch Bindemittel:

ServiceManager.getService("activity");

nächste:

  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 über:

 public final void bindApplication(...) {

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

Dies ist in ActivityManagerService in 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 ..

so erhalten wir müssen zurückrufen:

 return getIServiceManager().getService(name);

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

Das macht rufen durch:

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

was zu:

BinderInternal.getContextObject()

und das ist 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 Zeit nicht jetzt in c gegraben so, bis ich Rest Anruf sezieren ich meine Antwort aussetzen.

aber bester Weg für die Überprüfung, ob Dienst ausgeführt ist binden zu erstellen (wenn bind nicht erstellt existiert Dienst nicht) - und den Service über seinen Zustand durch die bind Abfrage (gespeicherte internen Flag mit auf es Zustand).

aktualisieren 2018.06.23

fand ich jene 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;
}

kurz :)

„Geben Sie ein Bindemittel zu einem bereits gebundenen Service. Diese Methode ist synchron und wird nicht den Zieldienst gestartet werden, wenn es nicht vorhanden ist.“

public IBinder peekService (Intent-Service, String resolvedType,                 String callingPackage) throws Remote;

  

*

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

*

In der Service-Sub-Klasse eine statische Boolean Verwenden Sie den Zustand des Dienstes zu erhalten, wie unten gezeigt wird.

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

Meine Kotlin Umwandlung der ActivityManager::getRunningServices basierten Antworten. Setzen Sie diese Funktion in einer Aktivität -

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

Bitte diesen Code verwenden.

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

Take it easy Jungs ...:)

Ich denke, die am besten geeignete Lösung, die ein Schlüssel-Wert-Paar in SharedPreferences hält etwa wenn der Dienst ausgeführt wird oder nicht.

Logik ist sehr einfach; an einer beliebigen Stelle in Ihrer Service-Klasse; setzen einen Booleschen Wert, der als ein Flag für Sie handeln wird, ob der Dienst ausgeführt wird oder nicht. Dann diesen Wert liest wo auch immer Sie in Ihrer Anwendung.

Ein Beispielcode, den ich in meiner app bin mit unter:

In meinem Service-Klasse (A-Service für Audio Stream), führe ich den folgenden Code, wenn der Dienst bis ist;

private void updatePlayerStatus(boolean isRadioPlaying)
{
        SharedPreferences sharedPref = this.getSharedPreferences(getString(R.string.str_shared_file_name), Context.MODE_PRIVATE);
        SharedPreferences.Editor editor = sharedPref.edit();
        editor.putBoolean(getString(R.string.str_shared_file_radio_status_key), isRadioPlaying);
        editor.commit();
}

Dann in jeder Tätigkeit meiner Anwendung, ich bin Überprüfung den Status des Dienstes mit Hilfe des folgenden Code;

private boolean isRadioRunning() {
        SharedPreferences sharedPref = this.getSharedPreferences(getString(R.string.str_shared_file_name), Context.MODE_PRIVATE);

        return sharedPref.getBoolean(getString(R.string.str_shared_file_radio_status_key), false);
}

Keine besonderen Berechtigungen, keine Loops ... Einfache Möglichkeit, saubere Lösung:)

Wenn Sie zusätzliche Informationen benötigen, lesen Sie bitte die Link

Hope, das hilft.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top