Question

Comment vérifier si un service en arrière-plan est en cours d'exécution?

Je souhaite une activité Android qui modifie l'état du service. Elle me permet de l'activer si elle est désactivée et de l'activer si elle est activée.

Était-ce utile?

La solution

J'ai eu le même problème il n'y a pas longtemps. Comme mon service était local, j'ai fini par utiliser simplement un champ statique dans la classe de service pour changer d'état, comme décrit par hackbod ici

EDIT (pour l'enregistrement):

Voici la solution proposée par hackbod:

  

Si votre code client et serveur fait partie du même .apk et que vous êtes   liaison au service avec une intention concrète (celle qui spécifie le   classe de service exacte), vous pouvez simplement configurer votre service   variable globale en cours d’exécution que votre client peut vérifier.

     

Nous n'avons délibérément pas d'API pour vérifier si un service est   en cours d'exécution parce que, presque sans faute, lorsque vous voulez faire quelque chose   comme ça, vous vous retrouvez avec des conditions de concurrence dans votre code.

Autres conseils

J'utilise les éléments suivants dans une activité:

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

Et je l’appelle en utilisant:

isMyServiceRunning(MyService.class)

Cela fonctionne de manière fiable, car il est basé sur les informations relatives à l'exécution de services fournis par le système d'exploitation Android via ActivityManager # getRunningServices .

Toutes les approches utilisant des événements onDestroy ou onSometing, des liants ou des variables statiques ne fonctionneront pas de manière fiable, car en tant que développeur, vous ne savez jamais, quand Android décide de tuer votre processus ou quels rappels mentionnés sont appelés ou non. Veuillez noter le " killable " colonne dans le tableau des événements du cycle de vie dans la documentation Android.

Compris!

Vous DEVEZ appeler startService () pour que votre service soit correctement enregistré et que transmettre BIND_AUTO_CREATE ne suffira pas.

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

Et maintenant 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 petit complément est:

Mon objectif est de savoir si un service est en cours d'exécution sans l'avoir réellement exécuté s'il ne fonctionne pas.

Appeler bindService ou appeler une intention susceptible d'être interceptée par le service n'est pas une bonne idée, car il lancera le service s'il n'est pas en cours d'exécution.

Ainsi, comme suggéré par miracle2k, le mieux est d’avoir un champ statique dans la classe de service pour savoir si le service a été démarré ou non.

Pour le rendre encore plus propre, je suggère de transformer le service en un singleton avec une extraction très très paresseuse: en d’autres termes, il n’existe aucune instanciation du singleton via des méthodes statiques. La méthode getInstance statique de votre service / singleton renvoie simplement l'instance du singleton si elle a été créée. Mais cela ne démarre ni n’instancie le singleton lui-même. Le service est uniquement démarré par le biais de méthodes de démarrage de service normales.

Il serait alors encore plus propre de modifier le modèle de conception singleton pour renommer la méthode getInstance, qui prête à confusion, en quelque chose comme la méthode isInstanceCreated (): boolean .

Le code ressemblera à:

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

Cette solution est élégante, mais elle n’est pertinente que si vous avez accès à la classe de service et uniquement aux classes qui se trouvent dans l’application / le package du service. Si vos classes sont en dehors de l'application / du package de service, vous pouvez interroger ActivityManager avec les limitations soulignées par Pieter-Jan Van Robays.

Vous pouvez utiliser ceci (je ne l'ai pas encore essayé, mais j'espère que cela fonctionnera):

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

La méthode startService renvoie un objet ComponentName s'il existe déjà un service. Sinon, null sera renvoyé.

Voir résumé public. Nom du composant startService (service d'intention) .

Ce n'est pas comme si je vérifiais, car il lance le service. Vous pouvez donc ajouter stopService (someIntent); sous le code.

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

J'ai légèrement modifié l'une des solutions présentées ci-dessus, mais en passant la classe au lieu d'un nom de chaîne générique, afin de pouvoir comparer les chaînes issues de la même méthode 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;
    }
}

et ensuite

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

Extrait de la documentation Android :

  

Comme sendBroadcast (Intent ) , mais s’il existe des destinataires pour   l'intention cette fonction va bloquer et immédiatement les envoyer   avant de revenir.

Pensez à ce hack comme un "ping". le Service étant donné que nous pouvons diffuser de manière synchrone, nous pouvons diffuser et obtenir un résultat - de manière synchrone - sur le fil de l'interface utilisateur.

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

Activité

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

Je veux juste ajouter une note à la réponse de @Snicolas. Les étapes suivantes peuvent être utilisées pour vérifier le service d'arrêt avec / sans appeler onDestroy () .

  1. onDestroy () appelé: Accédez à Paramètres - > Application - > Services en cours d'exécution - > Sélectionnez et arrêtez votre service.

  2. onDestroy () non appelé: accédez à Paramètres - > Application - > Gérer les applications - > Sélectionnez et " Force Stop " votre application dans laquelle votre service est exécuté. Toutefois, comme votre application est arrêtée ici, les instances de service le seront également. Les

Enfin, je voudrais mentionner que l’approche mentionnée ici, qui utilise une variable statique dans la classe singleton, fonctionne pour moi.

onDestroy n'est pas toujours appelé dans le service, donc c'est inutile!

Par exemple: Il suffit de relancer l’application avec une modification d’Eclipse. L’application est abandonnée de force avec SIG: 9.

Pour vérifier si un service est en cours d'exécution, il suffit de le lui demander. Implémentez un BroadcastReceiver dans votre service qui répond aux pings de vos activités. Enregistrez le BroadcastReceiver au démarrage du service et annulez l’enregistrement lorsque le service est détruit. À partir de votre activité (ou de tout composant), envoyez un diffusion locale

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

Tout d’abord, vous ne devez pas essayer d’atteindre le service en utilisant ActivityManager. (Discuté ici )

Les services peuvent être exécutés indépendamment, être liés à une activité ou aux deux. La manière de vérifier dans une activité si votre service est en cours d'exécution ou non consiste à créer une interface (qui étend le classeur) dans laquelle vous déclarez des méthodes que l'activité et le service comprennent. Vous pouvez le faire en créant votre propre interface dans laquelle vous déclarez, par exemple, "isServiceRunning ()". Vous pouvez ensuite lier votre activité à votre service, exécuter la méthode isServiceRunning (), le service vérifiera lui-même s’il est en cours d’exécution et renvoie un booléen à votre activité.

Vous pouvez également utiliser cette méthode pour arrêter votre service ou interagir avec lui d'une autre manière.

J'ai utilisé ce didacticiel . apprendre à implémenter ce scénario dans mon application.

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

Pour le cas d'utilisation donné ici, nous pouvons simplement utiliser la valeur de retour de la méthode stopService () . Il renvoie true s'il existe le service spécifié et s'il est tué. Sinon, il retourne false . Vous pouvez donc redémarrer le service si le résultat est false , sinon il est assuré que le service actuel a été arrêté. :) Il serait préférable de consulter ceci .

Encore une fois, une autre alternative que les utilisateurs pourraient trouver plus propre s’ils utilisent des intentions en attente (par exemple avec 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);
}

CODE est une constante que vous définissez en privé dans votre classe pour identifier les intentions en attente associées à votre service.

Ci-dessous est un hack élégant qui couvre tous les Ifs . Ceci concerne uniquement les services locaux.

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

Et ensuite:

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

La réponse de geekQ mais en classe Kotlin. Merci 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
}

L'appel

isMyServiceRunning(NewService::class.java)

Il peut y avoir plusieurs services avec le même nom de classe.

Je viens de créer deux applications. Le nom de package de la première application est com.example.mock . J'ai créé un sous-paquet nommé lorem dans l'application et un service appelé Mock2Service . Son nom complet est donc com.example.mock.lorem.Mock2Service .

Ensuite, j'ai créé la deuxième application et un service appelé Mock2Service . Le nom de package de la deuxième application est com.example.mock.lorem . Le nom complet du service est également com.example.mock.lorem.Mock2Service également.

Voici ma sortie 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

Une meilleure idée consiste à comparer les instances NomComposant car equals () sur NomComposant compare les noms de package et les noms de classe. Et il ne peut pas y avoir deux applications avec le même nom de package installées sur un appareil.

La méthode equals () de NomComposant .

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

Nom du composant

Ceci s’applique davantage au débogage d’Intent Service car ils génèrent un thread, mais peuvent également fonctionner pour des services standard. J'ai trouvé ce fil grâce à Binging

Dans mon cas, j'ai joué avec le débogueur et trouvé la vue des discussions. Cela ressemble en quelque sorte à l'icône représentant un point de balle dans MS Word. Quoi qu'il en soit, vous n'avez pas besoin d'être en mode débogueur pour l'utiliser. Cliquez sur le processus et cliquez sur ce bouton. Tous les services d’intention apparaîtront en cours d’exécution, au moins sur l’émulateur.

Si le service appartient à un autre processus ou à un APK, utilisez la solution basée sur ActivityManager.

Si vous avez accès à sa source, utilisez simplement la solution basée sur un champ statique. Mais au lieu d'utiliser un booléen, je suggère d'utiliser un objet Date. Pendant que le service est en cours d'exécution, il suffit de mettre à jour sa valeur sur 'maintenant' et à la fin, définissez-le sur null. À partir de l’activité, vous pouvez vérifier si la valeur NULL ou la date est trop ancienne, ce qui signifie qu’elle ne fonctionne pas.

Vous pouvez également envoyer une notification de diffusion à partir de votre service indiquant que des informations supplémentaires sont en cours d'exécution, telles que la progression.

Dans TheServiceClass, définissez:

 public static Boolean serviceRunning = false;

Puis dans onStartCommand (...)

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

    serviceRunning = true;
    ...
}

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

} 

Ensuite, appelez si (TheServiceClass.serviceRunning == true) depuis n'importe quelle classe.

l'utilisation simple lie avec ne pas créer auto - voir ps. et mettre à jour ...

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

exemple:

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

pourquoi ne pas utiliser? getRunningServices ()

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

Remarque: cette méthode est uniquement destinée au débogage ou à la mise en oeuvre d'interfaces utilisateur de type gestion de services.

ps. La documentation Android est trompeuse, j'ai ouvert un problème sur Google Tracker pour éliminer les doutes:

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

comme nous pouvons le voir, le service de liaison appelle en fait une transaction via le classeur ActivityManager via les classeurs de cache de service - i dint le service responsable de la liaison, mais le résultat de la liaison est le suivant:

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

la transaction est effectuée via le classeur:

ServiceManager.getService("activity");

suivant:

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

ceci est défini dans ActivityThread via:

 public final void bindApplication(...) {

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

cela est appelé dans ActivityManagerService dans la méthode:

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

alors:

 private HashMap<String, IBinder> getCommonServicesLocked() {

mais il n'y a pas d '"activité" seulement le paquet de fenêtre et l'alarme ..

nous avons donc besoin de revenir pour appeler:

 return getIServiceManager().getService(name);

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

cela passe un appel par:

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

qui mène à:

BinderInternal.getContextObject()

et ceci est une méthode native ....

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

Je n'ai pas le temps maintenant de creuser dans c, jusqu'à ce que je dissèque le repos, je suspends ma réponse.

mais le meilleur moyen de vérifier si le service est en cours d'exécution consiste à créer une liaison (si la liaison n'est pas créée, le service n'existe pas) - et interrogez le service sur son état via la liaison (en utilisant un indicateur interne stocké). il déclare).

mise à jour 23.06.2018

j'ai trouvé ces intéressants:

/**
 * 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 bref :)

"Fournir un classeur à un service déjà lié. Cette méthode est synchrone et ne démarrera pas le service cible s'il n'est pas présent. "

public IBinder peekService (service d’intention, String resolTType,                 String callingPackage) lève 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;
}
  

*

Dans votre sous-classe de service Utilisez un booléen statique pour obtenir l'état du service comme indiqué ci-dessous.

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

Ma conversion en kotlin des réponses basées sur ActivityManager :: getRunningServices . Mettez cette fonction dans une activité -

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

Veuillez utiliser ce 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;
    }

Prenez le facile les gars ...:)

Je pense que la solution la plus appropriée consiste à conserver une paire clé-valeur dans Préférences partagées pour savoir si le service est en cours d'exécution ou non.

La logique est très simple; à n'importe quel poste de votre classe de service; mettez une valeur booléenne qui agira comme un indicateur pour vous indiquant si le service est en cours d'exécution ou non. Lisez ensuite cette valeur où vous le souhaitez dans votre application.

Vous trouverez ci-dessous un exemple de code que j'utilise dans mon application:

Dans ma classe de service (service A pour flux audio), j'exécute le code suivant lorsque le service est activé;

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

Ensuite, dans toute activité de mon application, je vérifie le statut du service à l'aide du code suivant;

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

Pas d'autorisations spéciales, pas de boucles ... Facile, solution propre:)

Si vous avez besoin d'informations supplémentaires, consultez le lien

J'espère que cela vous aidera.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top