Pregunta

¿Cómo compruebo si se está ejecutando un servicio en segundo plano?

Quiero una actividad de Android que cambie el estado del servicio: me permite encenderla si está apagada y apagarla si está encendida.

¿Fue útil?

Solución

Hace poco tuve el mismo problema. Dado que mi servicio era local, simplemente usé un campo estático en la clase de servicio para cambiar el estado, como lo describe hackbod aquí

EDITAR (para el registro):

Aquí está la solución propuesta por hackbod:

  

Si su código de cliente y servidor es parte del mismo .apk y usted es   vinculante al servicio con una intención concreta (una que especifica el   clase de servicio exacto), entonces simplemente puede hacer que su servicio establezca una   variable global cuando se está ejecutando que su cliente puede verificar.

     

No tenemos una API deliberadamente para verificar si un servicio es   Corriendo porque, casi sin falta, cuando quieres hacer algo.   así terminas con condiciones de carrera en tu código.

Otros consejos

Uso lo siguiente desde dentro de una actividad:

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

Y lo llamo usando:

isMyServiceRunning(MyService.class)

Esto funciona de manera confiable, ya que se basa en la información sobre los servicios en ejecución provistos por el sistema operativo Android a través de ActivityManager # getRunningServices .

Todos los enfoques que utilizan los eventos onDestroy o onSometing o los Binders o las variables estáticas no funcionarán de manera confiable porque como desarrollador nunca se sabe, cuando Android decide finalizar el proceso o a cuál de las llamadas devueltas se llama o no. Tenga en cuenta que " killable " columna en la tabla de eventos del ciclo de vida en la documentación de Android.

¡Lo tengo!

Usted DEBE llamar a startService () para que su servicio se registre correctamente y no será suficiente pasar BIND_AUTO_CREATE .

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

Y ahora la clase 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 pequeño complemento es:

Mi objetivo es saber si un servicio se está ejecutando sin ejecutarlo realmente si no se está ejecutando.

Llamar a bindService o llamar a un intento que pueda ser detectado por el servicio no es una buena idea, ya que iniciará el servicio si no se está ejecutando.

Entonces, como sugirió miracle2k, lo mejor es tener un campo estático en la clase de servicio para saber si el servicio se ha iniciado o no.

Para hacerlo aún más claro, sugiero transformar el servicio en un singleton con una búsqueda muy perezosa: es decir, no hay instanciación en absoluto de singleton a través de métodos estáticos. El método estático getInstance de su servicio / singleton solo devuelve la instancia del singleton si se ha creado. Pero en realidad no inicia ni instancia el propio singleton. El servicio solo se inicia con los métodos normales de inicio del servicio.

Entonces sería aún más limpio modificar el patrón de diseño de singleton para cambiar el nombre del método getInstance confuso a algo como el método isInstanceCreated (): boolean .

El código se verá así:

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

Esta solución es elegante, pero solo es relevante si tiene acceso a la clase de servicio y solo para las clases está al lado de la aplicación / paquete del servicio. Si sus clases están fuera del servicio / paquete de servicio, puede consultar el ActivityManager con las limitaciones subrayadas por Pieter-Jan Van Robays.

Puedes usar esto (no probé esto todavía, pero espero que esto funcione):

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

El método startService devuelve un objeto ComponentName si ya hay un servicio en ejecución. Si no, se devolverá nulo.

Consulte resumen público ComponentName startService (Intent service) .

Esto no es como verificar, creo, porque está iniciando el servicio, así que puedes agregar stopService (someIntent); debajo del código.

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

He modificado ligeramente una de las soluciones presentadas anteriormente, pero al pasar la clase en lugar de un nombre de cadena genérico, para estar seguro de comparar las cadenas que salen del mismo método 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;
    }
}

y luego

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

Un extracto de Android documentos:

  

Me gusta sendBroadcast (Intenente ) , pero si hay algún receptor para   el Intento esta función los bloqueará y los enviará inmediatamente   antes de regresar.

Piense en este truco como " haciendo ping a " El Service , ya que podemos transmitir de forma sincrónica, podemos transmitir y obtener un resultado, sincrónicamente, en el subproceso de la interfaz de usuario.

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

Solo quiero agregar una nota a la respuesta por @Snicolas. Los siguientes pasos se pueden usar para verificar el servicio de parada con / sin llamar a onDestroy () .

  1. onDestroy () llamado: Ir a Configuración - > Aplicación - > Servicios en ejecución - > Seleccione y detenga su servicio.

  2. onDestroy () no se llama: ve a Configuración - > Aplicación - > Gestionar aplicaciones - > Seleccione y " Forzar parada " Su aplicación en la que se ejecuta su servicio. Sin embargo, como su aplicación se detiene aquí, definitivamente las instancias de servicio también se detendrán.

Finalmente, me gustaría mencionar que el enfoque mencionado allí usando una variable estática en la clase de singleton está funcionando para mí.

onDestroy no siempre se llama en el servicio, por lo que no sirve para nada.

Por ejemplo: simplemente ejecute la aplicación nuevamente con un cambio desde Eclipse. La aplicación se cierra a la fuerza usando SIG: 9.

La forma correcta de verificar si un servicio se está ejecutando es simplemente preguntándolo. Implemente un BroadcastReceiver en su servicio que responda a pings de sus actividades. Registre el BroadcastReceiver cuando se inicie el servicio y anule el registro cuando se destruya el servicio. Desde su actividad (o cualquier componente), envíe un emisión local intento al servicio y si responde, sabes que está funcionando. Tenga en cuenta la sutil diferencia entre ACTION_PING y ACTION_PONG en el código a continuación.

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

En primer lugar, no debe intentar acceder al servicio mediante el ActivityManager. (Se comentó aquí )

Los servicios se pueden ejecutar solos, vinculados a una actividad o a ambos. La forma de verificar una Actividad si su Servicio se está ejecutando o no es haciendo una interfaz (que extienda el Binder) donde declare los métodos que tanto la Actividad como el Servicio comprenden. Puede hacer esto creando su propia Interfaz donde declare, por ejemplo, " isServiceRunning () " ;. Luego, puede vincular su Actividad a su Servicio, ejecutar el método isServiceRunning (), el Servicio comprobará si está funcionando o no y devuelve un booleano a su Actividad.

También puede usar este método para detener su Servicio o interactuar con él de otra manera.

Utilicé este tutorial para aprender a implementar este escenario en mi aplicación.

Versión 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;
}

Para el caso de uso que se presenta aquí, simplemente podemos utilizar el valor de retorno del método stopService () . Devuelve true si existe el servicio especificado y se cancela. De lo contrario, devuelve false . Por lo tanto, puede reiniciar el servicio si el resultado es false , de lo contrario se garantiza que el servicio actual se ha detenido. :) Sería mejor si miras this .

Nuevamente, otra alternativa que las personas podrían encontrar más limpia si usan intenciones pendientes (por ejemplo, con el 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);
}

Donde CODE es una constante que define de forma privada en su clase para identificar los intentos pendientes asociados a su servicio.

A continuación se muestra un truco elegante que cubre todos los Ifs . Esto es solo para servicios locales.

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

Y luego más adelante:

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

La respuesta de geekQ pero en la clase Kotlin. Gracias 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 llamada

isMyServiceRunning(NewService::class.java)

Puede haber varios servicios con el mismo nombre de clase.

Acabo de crear dos aplicaciones. El nombre del paquete de la primera aplicación es com.example.mock . Creé un subpaquete llamado lorem en la aplicación y un servicio llamado Mock2Service . Por lo tanto, su nombre completo es com.example.mock.lorem.Mock2Service .

Luego creé la segunda aplicación y un servicio llamado Mock2Service . El nombre del paquete de la segunda aplicación es com.example.mock.lorem . El nombre completo del servicio es com.example.mock.lorem.Mock2Service , también.

Aquí está mi salida 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

Una mejor idea es comparar las instancias de ComponentName porque es igual a () de ComponentName compara los nombres de los paquetes y los nombres de clase. Y no puede haber dos aplicaciones con el mismo nombre de paquete instalado en un dispositivo.

El método equals () de 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

Esto se aplica más a la depuración de Intent Service, ya que generan un subproceso, pero también puede funcionar para servicios regulares. Encontré este hilo gracias a Binging

En mi caso, jugué con el depurador y encontré la vista de hilos. Se parece al ícono de la viñeta en MS Word. De todas formas, no tienes que estar en modo depurador para usarlo. Haga clic en el proceso y haga clic en ese botón. Cualquier Intent Services se mostrará mientras se estén ejecutando, al menos en el emulador.

Si el servicio pertenece a otro proceso o APK, use la solución basada en el ActivityManager.

Si tiene acceso a su fuente, solo use la solución basada en un campo estático. Pero en lugar de eso, usar un booleano sugeriría usar un objeto Date. Mientras se está ejecutando el servicio, simplemente actualice su valor a 'ahora' y cuando termine, configúrelo en nulo. Desde la actividad puede verificar si es nulo o la fecha es demasiado antigua, lo que significa que no se está ejecutando.

También puede enviar notificaciones de transmisión desde su servicio indicando que se está ejecutando junto con información adicional como el progreso.

Dentro de TheServiceClass define:

 public static Boolean serviceRunning = false;

Luego InStartCommand (...)

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

    serviceRunning = true;
    ...
}

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

} 

Luego, llame a si (TheServiceCerv.serviceRunning == true) de cualquier clase.

enlace de uso simple con no crear auto - vea ps. y actualizar ...

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

ejemplo:

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

¿por qué no usar? getRunningServices ()

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

Nota: este método solo está destinado a la depuración o la implementación de interfaces de usuario de tipo de gestión de servicios.


ps. la documentación de Android es engañosa. He abierto un problema en el rastreador de google para eliminar cualquier duda:

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

como podemos ver, el servicio de vinculación realmente invoca una transacción a través del enlazador ActivityManager a través de los enlazadores de caché de servicio - no doy cuenta de qué servicio es responsable de vincular pero, como podemos ver, el resultado de vinculación es:

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

la transacción se realiza a través de la carpeta:

ServiceManager.getService("activity");

siguiente:

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

esto se establece en ActivityThread a través de:

 public final void bindApplication(...) {

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

esto se llama en ActivityManagerService en el método:

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

entonces:

 private HashMap<String, IBinder> getCommonServicesLocked() {

pero no hay " actividad " solo paquete de ventana y alarma ..

por lo que necesitamos volver a llamar:

 return getIServiceManager().getService(name);

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

esto hace que la llamada a través de:

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

que conduce a:

BinderInternal.getContextObject()

y este es el método 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();

ahora no tengo tiempo para excavar en c, así que hasta que diseccione la llamada de reposo, suspendo mi respuesta.

pero la mejor manera de comprobar si el servicio se está ejecutando es crear un enlace (si no se crea el enlace, no existe el servicio) - y consultar al servicio sobre su estado a través del enlace (utilizando el indicador interno almacenado en estado).

actualización 23.06.2018

Los encontré interesantes:

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

en resumen :)

" Proporcionar una carpeta a un servicio ya vinculado. Este método es síncrono y no iniciará el servicio de destino si no está presente. & Quot;

público IBinder peekService (servicio de intenciones, String resolutionType,                 String callingPackage) lanza 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;
}
  

*

En su subclase de servicio, use un booleano estático para obtener el estado del servicio como se muestra a continuación.

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

Mi conversión a kotlin de las respuestas basadas en ActivityManager :: getRunningServices . Pon esta función en una actividad-

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

Por favor usa este código.

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

Tómalo con calma, chicos ... :)

Creo que la solución más adecuada es mantener un par clave-valor en SharedPreferences sobre si el servicio se está ejecutando o no.

La lógica es muy recta; en cualquier posición deseada en su clase de servicio; ponga un valor booleano que actuará como un indicador para usted sobre si el servicio se está ejecutando o no. Luego lea este valor donde lo desee en su aplicación.

A continuación se muestra un código de muestra que estoy usando en mi aplicación:

En mi clase de servicio (un servicio para transmisión de audio), ejecuto el siguiente código cuando el servicio está activo;

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

Luego, en cualquier actividad de mi aplicación, estoy verificando el estado del servicio con la ayuda del siguiente código;

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

Sin permisos especiales, sin bucles ... Forma fácil, solución limpia :)

Si necesita información adicional, consulte el enlace

Espero que esto ayude.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top