Lier le service à l'activité dans Android

90

J'essaie d'écrire un simple lecteur multimédia qui lit l'audio en streaming à l'aide de RTSP. J'ai une activité GUI et un service qui effectue la lecture. Ma question est de savoir comment communiquer au mieux entre l'activité et le service (par exemple, mettre à jour l'interface graphique en fonction de l'état du lecteur).

Je sais que je peux lier le service à l'activité en utilisant onBind (), mais si je comprends bien, cela arrêtera le service si l'activité est tuée. Je souhaite continuer la lecture même si l'utilisateur quitte l'activité. Existe-t-il une manière standard ou préférée de traiter ce problème?

aspartame
la source

Réponses:

154

"Si vous démarrez un service Android avec startService(..)ce service restera en cours d'exécution jusqu'à ce que vous l'appeliez explicitement stopService(..). Il existe deux raisons pour lesquelles un service peut être exécuté par le système. Si quelqu'un appelle, Context.startService()le système récupérera le service (en le créant et en appelant sa onCreate()méthode si nécessaire), puis appelez sa onStartCommand(Intent, int, int)méthode avec les arguments fournis par le client. À ce stade, le service continuera à s'exécuter jusqu'à ce que Context.stopService()ou stopSelf()soit appelé. Notez que plusieurs appels à Context.startService()ne pas imbriquer (bien qu'ils entraînent plusieurs appels correspondants à onStartCommand()), donc non peu importe combien de fois il est démarré, un service sera arrêté une fois Context.stopService()ou stopSelf()est appelé; cependant, les services peuvent utiliser leurstopSelf(int) pour garantir que le service n'est pas arrêté tant que les intentions de démarrage n'ont pas été traitées.

Les clients peuvent également utiliser Context.bindService()pour obtenir une connexion permanente à un service. Cela crée également le service s'il n'est pas déjà en cours d'exécution (appelant onCreate()en faisant cela), mais n'appelle pas onStartCommand(). Le client recevra l' IBinderobjet que le service retourne à partir de sa onBind(Intent)méthode, permettant au client de faire ensuite des appels vers le service. Le service restera en cours d'exécution tant que la connexion est établie (que le client conserve ou non une référence sur le service IBinder). Habituellement, le résultat IBinderest pour une interface complexe qui a été écrite en AIDL.

Un service peut être à la fois démarré et avoir des connexions liées à celui-ci. Dans un tel cas, le système maintiendra le service en cours d'exécution tant qu'il est démarré ou qu'il y a une ou plusieurs connexions avec l' Context.BIND_AUTO_CREATEindicateur. Une fois qu'aucune de ces situations ne tient, la onDestroy()méthode du service est appelée et le service est effectivement terminé. Tous les nettoyages (arrêt des threads, annulation de l’enregistrement des récepteurs) doivent être terminés au retour onDestroy(). »

Schildmeijer
la source
1
un peu de confusion: est-il vrai que si l'activité est détruite, le service sera également détruit? Ou ce service n'est-il pas détruit uniquement si j'implémente ma propre AIDL? Je demande parce que lorsque j'utilise startService (en particulier sur IntentService), le service s'arrête lorsque son travail est terminé, par opposition à la mort de l'activité. Alors est-il vrai que si l'activité meurt, alors le service qui est lié (exclusivement) meurt également?
Katedral Pillon
1
si vous utilisez un serveur simple en appelant startService, le service ne s'arrêtera pas tant que vous n'aurez pas appelé stopSelf () ou stopService (). Et le suivant si vous utilisez bindService, le service yes mourra si tous les composants connectés / liés sont détruits.
Asif Mushtaq
1
@UnKnown Si le service est démarré en utilisant startService (), peu importe si vous le liez ou le dissociez, il continuera à fonctionner et ne pourra être détruit qu'en appelant stopService () ou stopSelf (). Ainsi, même si l'activité qui était liée au service est détruite, le service ne sera pas détruit.
CopsOnRoad
Pouvez-vous s'il vous plaît m'aider avec cette question stackoverflow.com/questions/51508046/…
Rajesh K
25

Tout d'abord, 2 choses que nous devons comprendre

Client

  • il fait une demande à un serveur spécifique

    bindService(new 
        Intent("com.android.vending.billing.InAppBillingService.BIND"),
            mServiceConn, Context.BIND_AUTO_CREATE);`

voici une mServiceConninstance de ServiceConnectionclasse (intégrée), c'est en fait une interface que nous devons implémenter avec deux méthodes (1ère pour le réseau connecté et 2ème réseau non connecté) pour surveiller l'état de la connexion réseau.

Serveur

  • Il gère la demande du client et crée sa propre réplique, qui est privée uniquement pour le client qui envoie la demande et cette réplique du serveur s'exécute sur un thread différent.

Maintenant côté client, comment accéder à toutes les méthodes de serveur?

  • serveur envoie une réponse avec IBind Object.so IBind object est notre gestionnaire qui accède à toutes les méthodes de service en utilisant l'opérateur (.).

    MyService myService;
    public ServiceConnection myConnection = new ServiceConnection() {
        public void onServiceConnected(ComponentName className, IBinder binder) {
            Log.d("ServiceConnection","connected");
            myService = binder;
        }
        //binder comes from server to communicate with method's of 
    
        public void onServiceDisconnected(ComponentName className) {
            Log.d("ServiceConnection","disconnected");
            myService = null;
        }
    }

maintenant comment appeler la méthode qui se trouve en service

myservice.serviceMethod();

voici l' myServiceobjet et la serviceMethodeméthode en service. Et de cette manière, la communication est établie entre le client et le serveur.

Hardik Gajera
la source
10

J'ai essayé d'appeler

startService(oIntent);
bindService(oIntent, mConnection, Context.BIND_AUTO_CREATE);

par conséquent et je pourrais créer un service collant et me lier à lui. Tutoriel détaillé pour l' exemple de service lié .

M. Hefny
la source
5

Il existe une méthode appelée unbindService qui prendra un ServiceConnection que vous aurez créé lors de l'appel de bindService. Cela vous permettra de vous déconnecter du service tout en le laissant en cours d'exécution.

Cela peut poser un problème lorsque vous vous y reconnectez, car vous ne savez probablement pas s'il est en cours d'exécution ou non lorsque vous redémarrez l'activité, vous devrez donc en tenir compte dans votre code d'activité.

Bonne chance!

Vrutberg
la source
-1

C'est une réponse biaisée, mais j'ai écrit une bibliothèque qui peut simplifier l'utilisation des services Android, s'ils s'exécutent localement dans le même processus que l'application: https://github.com/germnix/acacia

Fondamentalement, vous définissez une interface annotée avec @Service et sa classe d'implémentation, et la bibliothèque crée et lie le service, gère la connexion et le thread de travail en arrière-plan:

@Service(ServiceImpl.class)
public interface MyService {
    void doProcessing(Foo aComplexParam);
}

public class ServiceImpl implements MyService {
    // your implementation
}

MyService service = Acacia.createService(context, MyService.class);
service.doProcessing(foo);

<application
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme">
    ...
    <service android:name="com.gmr.acacia.AcaciaService"/>
    ...
</application>

Vous pouvez obtenir une instance du android.app.Service associé pour masquer / afficher les notifications persistantes, utiliser votre propre android.app.Service et gérer manuellement le threading si vous le souhaitez.

allemand
la source
-5

Si l'utilisateur recule, la onDestroy()méthode sera appelée. Cette méthode consiste à arrêter tout service utilisé dans l'application. Donc, si vous souhaitez continuer le service même si l'utilisateur se retire de l'application, effacez simplement onDestroy(). J'espère que cette aide.

Mira Febriani
la source
Vous devriez remplacer la fonction et supprimer l'appel par défaut à onDestroy () de la superclasse si votre IDE en crée automatiquement un. mais pourquoi voudriez-vous faire ça?
Riptyde4