Domanda

Come posso verificare se un servizio in background è in esecuzione?

Voglio un'attività Android che commuta lo stato del servizio: mi consente di attivarlo se è spento e spento se è acceso.

È stato utile?

Soluzione

Ho avuto lo stesso problema non molto tempo fa. Dato che il mio servizio era locale, ho semplicemente usato un campo statico nella classe di servizio per attivare lo stato, come descritto da hackbod qui

MODIFICA (per la cronaca):

Ecco la soluzione proposta da hackbod:

  

Se il tuo codice client e server fa parte dello stesso .apk e tu lo sei   vincolante per il servizio con un intento concreto (uno che specifica il   classe di servizio esatta), quindi puoi semplicemente impostare il tuo servizio a   variabile globale quando è in esecuzione che il client può controllare.

     

Non abbiamo deliberatamente un'API per verificare se un servizio è   correre perché, quasi a colpo sicuro, quando vuoi fare qualcosa   in questo modo finisci con le condizioni di gara nel tuo codice.

Altri suggerimenti

Uso all'interno di un'attività quanto segue:

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

E lo chiamo usando:

isMyServiceRunning(MyService.class)

Funziona in modo affidabile, perché si basa sulle informazioni sull'esecuzione dei servizi fornite dal sistema operativo Android tramite ActivityManager # getRunningServices .

Tutti gli approcci che usano eventi onDestroy o onSometing o leganti o variabili statiche non funzioneranno in modo affidabile perché come sviluppatore non si sa mai, quando Android decide di interrompere il processo o quale dei callback menzionati viene chiamato o meno. Tieni presente che " killable " colonna nella tabella degli eventi del ciclo di vita nella documentazione di Android.

Capito!

Devi DEVI chiamare startService () affinché il tuo servizio sia registrato correttamente e passare BIND_AUTO_CREATE non sarà sufficiente.

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

E ora la classe 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;
     }
}

Un piccolo complemento è:

Il mio obiettivo è sapere se un servizio è in esecuzione senza realmente eseguirlo se non è in esecuzione.

Chiamare bindService o chiamare un intento che può essere colto dal servizio non è una buona idea, in quanto avvierà il servizio se non è in esecuzione.

Quindi, come suggerito da miracle2k, la cosa migliore è avere un campo statico nella classe di servizio per sapere se il servizio è stato avviato o meno.

Per renderlo ancora più pulito, suggerisco di trasformare il servizio in un singleton con un recupero molto molto pigro: cioè, non c'è alcuna istanza di singleton tramite metodi statici. Il metodo statico getInstance del tuo servizio / singleton restituisce l'istanza del singleton solo se è stata creata. Ma in realtà non avvia o istanzia il singleton stesso. Il servizio viene avviato solo tramite i normali metodi di avvio del servizio.

Sarebbe quindi ancora più pulito modificare il modello di progettazione singleton per rinominare il metodo confuso getInstance in qualcosa come il isInstanceCreated (): booleano .

Il codice sarà simile a:

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

Questa soluzione è elegante, ma è rilevante solo se si ha accesso alla classe di servizio e solo per le classi è l'app / pacchetto del servizio. Se le tue classi sono al di fuori dell'app / pacchetto di servizi, puoi interrogare ActivityManager con le limitazioni sottolineate da Pieter-Jan Van Robays.

Puoi usarlo (non l'ho ancora provato, ma spero che funzioni):

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

Il metodo startService restituisce un oggetto ComponentName se esiste già un servizio. In caso contrario, verrà restituito null.

Vedi abstract pubblico ComponentName startService (servizio intento) .

Penso che non sia come controllare, perché sta avviando il servizio, quindi puoi aggiungere stopService (someIntent); sotto il codice.

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

Ho leggermente modificato una delle soluzioni presentate sopra, ma passando la classe anziché un nome di stringa generico, per essere sicuro di confrontare le stringhe che escono dallo stesso metodo 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;
    }
}

e poi

Boolean isServiceRunning = ServiceTools.isServiceRunning(
                    MainActivity.this.getApplicationContext(),
                    BackgroundIntentService.class);

Un estratto da Android documenti:

  

Come sendBroadcast (Intent ) , ma se ci sono ricevitori per   l'intento questa funzione li bloccherà e li spedirà immediatamente   prima di tornare.

Pensa a questo hack come " pinging " il Service poiché possiamo trasmettere in modo sincrono possiamo trasmettere e ottenere un risultato - in modo sincrono - sul thread dell'interfaccia utente.

servizio

@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"));
    }
}

attività

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

Voglio solo aggiungere una nota alla risposta di @Snicolas. I seguenti passaggi possono essere utilizzati per controllare il servizio di arresto con / senza chiamare onDestroy () .

  1. onDestroy () chiamato: Vai su Impostazioni - > Applicazione - > Servizi in corso - > Seleziona e interrompi il tuo servizio.

  2. onDestroy () non chiamato: vai su Impostazioni - > Applicazione - > Gestisci applicazioni - > Seleziona e " Force Stop " l'applicazione in cui è in esecuzione il servizio. Tuttavia, poiché l'applicazione viene arrestata qui, anche le istanze del servizio verranno arrestate.

Infine, vorrei menzionare che l'approccio menzionato lì utilizzando una variabile statica nella classe singleton funziona per me.

onDestroy non viene sempre chiamato nel servizio, quindi è inutile!

Ad esempio: esegui di nuovo l'app con una modifica da Eclipse. L'applicazione viene forzatamente chiusa utilizzando SIG: 9.

Il modo corretto per verificare se un servizio è in esecuzione è semplicemente chiederlo. Implementa un BroadcastReceiver nel tuo servizio che risponda ai ping delle tue attività. Registrare BroadcastReceiver all'avvio del servizio e annullare la registrazione quando il servizio viene distrutto. Dalla tua attività (o qualsiasi componente), invia una trasmissione locale intento al servizio e se risponde, sai che è in esecuzione. Nota la sottile differenza tra ACTION_PING e ACTION_PONG nel codice seguente.

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

Prima di tutto non devi provare a raggiungere il servizio utilizzando ActivityManager. (Discusso qui )

I servizi possono essere eseguiti da soli, essere associati a un'attività o entrambi. Il modo per verificare un'attività se il servizio è in esecuzione o meno consiste nel creare un'interfaccia (che estende Binder) in cui si dichiarano metodi comprensibili sia per l'attività che per il servizio. Puoi farlo creando la tua interfaccia in cui dichiari ad esempio " isServiceRunning () " ;. Puoi quindi associare la tua attività al tuo servizio, eseguire il metodo isServiceRunning (), il servizio verificherà se è in esecuzione o meno e restituisce un valore booleano alla tua attività.

Puoi anche usare questo metodo per interrompere il tuo Servizio o interagire con esso in un altro modo.

Ho usato questo tutorial per imparare come implementare questo scenario nella mia applicazione.

Versione Xamarin C #:

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

Per il caso d'uso indicato qui, possiamo semplicemente utilizzare il valore di ritorno del metodo stopService () . Restituisce true se esiste il servizio specificato e viene ucciso. Altrimenti restituisce false . Quindi è possibile riavviare il servizio se il risultato è false , altrimenti è garantito che il servizio corrente è stato interrotto. :) Sarebbe meglio se dai un'occhiata a questo .

Ancora una volta, un'altra alternativa che le persone potrebbero trovare più pulite se usano intenzioni in sospeso (ad esempio con il 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);
}

Dove CODE è una costante che definisci privatamente nella tua classe per identificare gli intenti in sospeso associati al tuo servizio.

Di seguito è riportato un elegante trucco che copre tutti gli Ifs . Questo è solo per servizi locali.

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

E poi in seguito:

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

La risposta di geekQ ma nella classe di Kotlin. Grazie 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
}

La chiamata

isMyServiceRunning(NewService::class.java)

Possono esserci diversi servizi con lo stesso nome di classe.

Ho appena creato due app. Il nome del pacchetto della prima app è com.example.mock . Ho creato un subpackage chiamato lorem nell'app e un servizio chiamato Mock2Service . Quindi il suo nome completo è com.example.mock.lorem.Mock2Service .

Quindi ho creato la seconda app e un servizio chiamato Mock2Service . Il nome del pacchetto della seconda app è com.example.mock.lorem . Il nome completo del servizio è anche com.example.mock.lorem.Mock2Service .

Ecco l'output del mio logcat.

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

Un'idea migliore è quella di confrontare le istanze ComponentName perché equals () di ComponentName confronta sia i nomi dei pacchetti che i nomi delle classi. E non ci possono essere due app con lo stesso nome di pacchetto installato su un dispositivo.

Il metodo equals () di 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;
}

ComponentName

Ciò si applica di più al debug del servizio di intenti poiché generano un thread, ma può funzionare anche per i servizi regolari. Ho trovato questa discussione grazie a Binging

Nel mio caso, ho giocato con il debugger e ho trovato la vista thread. Sembra un po 'come l'icona del punto elenco in MS Word. Ad ogni modo, non è necessario essere in modalità debugger per usarlo. Fare clic sul processo e fare clic su quel pulsante. Qualsiasi Intent Services verrà visualizzato mentre sono in esecuzione, almeno sull'emulatore.

Se il servizio appartiene a un altro processo o APK, utilizzare la soluzione basata su ActivityManager.

Se hai accesso alla sua fonte, usa semplicemente la soluzione basata su un campo statico. Ma invece usando un booleano suggerirei di usare un oggetto Date. Mentre il servizio è in esecuzione, basta aggiornare il suo valore su "now" e quando termina impostarlo su null. Dall'attività puoi verificare se il suo valore nullo o la data è troppo vecchia, il che significa che non è in esecuzione.

Puoi anche inviare una notifica di trasmissione dal tuo servizio indicando che sta scorrendo ulteriori informazioni come progresso.

All'interno di TheServiceClass definisci:

 public static Boolean serviceRunning = false;

Quindi in onStartCommand (...)

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

    serviceRunning = true;
    ...
}

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

} 

Quindi, chiama if (TheServiceClass.serviceRunning == true) da qualsiasi classe.

rilegatura semplice con non creare auto - vedi ps. e aggiorna ...

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

esempio:

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

perché non utilizzarlo? getRunningServices ()

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

Nota: questo metodo è destinato esclusivamente al debug o all'implementazione delle interfacce utente del tipo di gestione del servizio.


ps. la documentazione di Android è fuorviante, ho aperto un problema sul tracker di Google per eliminare qualsiasi dubbio:

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

come possiamo vedere il servizio di bind in realtà invoca una transazione tramite il binder ActivityManager attraverso i binder della cache del servizio - non tengo traccia di quale servizio è responsabile dell'associazione ma come possiamo vedere il risultato per il bind è:

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

la transazione viene effettuata tramite raccoglitore:

ServiceManager.getService("activity");

successivo:

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

questo è impostato in ActivityThread tramite:

 public final void bindApplication(...) {

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

questo è chiamato in ActivityManagerService nel metodo:

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

quindi:

 private HashMap<String, IBinder> getCommonServicesLocked() {

ma non c'è "attività" solo pacchetto finestra e allarme ..

quindi dobbiamo tornare a chiamare:

 return getIServiceManager().getService(name);

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

questo fa chiamare attraverso:

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

che porta a:

BinderInternal.getContextObject()

e questo è un metodo nativo ....

  /**
     * 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();

Non ho tempo per scavare in c, quindi fino a quando non analizzo la chiamata di riposo sospendo la mia risposta.

ma il modo migliore per verificare se il servizio è in esecuzione è creare un bind (se il bind non è stato creato, il servizio non esiste) e interrogare il servizio sul suo stato attraverso il bind (usando il flag interno memorizzato su afferma).

aggiornamento 23.06.2018

li ho trovati interessanti:

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

in breve :)

" Fornire un raccoglitore a un servizio già associato. Questo metodo è sincrono e non avvierà il servizio di destinazione se non è presente. & Quot;

public IBinder peekService (Intent service, String resolvedType,                 String callingPackage) genera RemoteException;

  

*

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

*

Nella sottoclasse del servizio Utilizzare un valore booleano statico per ottenere lo stato del servizio come mostrato di seguito.

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

La mia conversione kotlin delle risposte basate su ActivityManager :: getRunningServices . Inserisci questa funzione in un'attività-

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

Utilizza questo codice.

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

Vacci piano ragazzi ... :)

Penso che la soluzione più adatta sia tenere una coppia chiave-valore in SharedPreferences per sapere se il servizio è in esecuzione o meno.

La logica è molto semplice; in qualsiasi posizione desiderata nella tua classe di servizio; inserisci un valore booleano che fungerà da flag per te se il servizio è in esecuzione o meno. Quindi leggi questo valore dove vuoi nella tua applicazione.

Di seguito è riportato un codice di esempio che sto utilizzando nella mia app:

Nella mia classe di servizio (A service for Audio Stream), eseguo il codice seguente quando il servizio è attivo;

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

Quindi in qualsiasi attività della mia domanda, sto controllando lo stato del servizio con l'aiuto del seguente codice;

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

Nessuna autorizzazione speciale, nessun loop ... Modo semplice, soluzione pulita :)

Se hai bisogno di ulteriori informazioni, consulta il link

Spero che questo aiuti.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top