Associa il servizio all'attività in Android


90

Sto cercando di scrivere un semplice lettore multimediale che riproduca l'audio in streaming utilizzando RTSP. Ho un'attività GUI e un servizio che esegue la riproduzione. La mia domanda è come comunicare al meglio tra l'attività e il servizio (es. Aggiornare la GUI in base allo stato del giocatore).

So che posso associare il servizio all'attività utilizzando onBind (), ma se ho capito correttamente questo interromperà il servizio se l'attività viene interrotta. Voglio continuare la riproduzione anche se l'utente esce dall'attività. Esiste un modo standard o preferito per affrontare questo problema?

Risposte:


154

"Se avvii un servizio Android con startService(..)quel servizio rimarrà in esecuzione finché non lo stopService(..)inviti esplicitamente . Ci sono due ragioni per cui un servizio può essere eseguito dal sistema. Se qualcuno chiama, Context.startService()il sistema recupererà il servizio (creandolo e chiamando il suo onCreate()metodo se necessario) e quindi chiamare il suo onStartCommand(Intent, int, int)metodo con gli argomenti forniti dal client. A questo punto il servizio continuerà a funzionare fino a quando non viene chiamato Context.stopService()o stopSelf(). Si noti che più chiamate a Context.startService()non vengono nidificate (sebbene risultino in più chiamate corrispondenti a onStartCommand()), quindi no importa quante volte viene avviato un servizio verrà arrestato una volta Context.stopService()o stopSelf()viene chiamato; tuttavia, i servizi possono utilizzare il lorostopSelf(int) per garantire che il servizio non venga arrestato finché gli intenti avviati non sono stati elaborati.

I client possono anche utilizzare Context.bindService()per ottenere una connessione permanente a un servizio. Allo stesso modo questo crea il servizio se non è già in esecuzione (chiamando onCreate()mentre lo fa), ma non chiama onStartCommand(). Il client riceverà l' IBinderoggetto che il servizio restituisce dal suo onBind(Intent)metodo, consentendo al client di effettuare chiamate di nuovo al servizio. Il servizio rimarrà in esecuzione fintanto che viene stabilita la connessione (indipendentemente dal fatto che il client mantenga o meno un riferimento sul servizio IBinder). Di solito il risultato IBinderè per un'interfaccia complessa che è stata scritta in AIDL.

Un servizio può essere avviato e avere connessioni ad esso associate. In tal caso, il sistema manterrà il servizio in esecuzione fintanto che viene avviato o vi sono una o più connessioni ad esso con il Context.BIND_AUTO_CREATEflag. Quando nessuna di queste situazioni si verifica, onDestroy()viene chiamato il metodo del servizio e il servizio viene effettivamente terminato. Tutta la pulizia (arresto dei thread, annullamento della registrazione dei ricevitori) dovrebbe essere completata al ritorno da onDestroy(). "


1
un po 'di confusione: è vero che se l'attività viene distrutta verrà distrutto anche il servizio? O quel servizio non viene distrutto solo se implemento il mio AIDL? Sto chiedendo perché quando uso startService (specialmente su IntentService) il servizio si interrompe quando il suo lavoro è finito invece di quando l'attività muore. Quindi è vero che se l'attività muore, muore anche il servizio che è vincolato (esclusivamente)?
Katedral Pillon

1
se si utilizza un server semplice chiamando startService, il servizio non si interromperà finché non si chiama stopSelf () o stopService (). E il prossimo, se usi bindService, sì, il servizio morirà se tutti i componenti collegati / bind vengono distrutti.
Asif Mushtaq

1
@UnKnown Se il servizio viene avviato utilizzando startService (), non importa se lo si associa o disassocia, continuerà a funzionare e può essere distrutto solo chiamando stopService () o stopSelf (). Quindi, anche se l'attività che era limitata al servizio viene distrutta, il servizio non verrà distrutto.
CopsOnRoad

Potete aiutarmi con questa domanda stackoverflow.com/questions/51508046/…
Rajesh K

25

Prima di tutto, 2 cose che dobbiamo capire

Cliente

  • fa richiesta a server specifico

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

ecco l' mServiceConnistanza della ServiceConnectionclasse (incorporata) è in realtà l'interfaccia che dobbiamo implementare con due (il primo per la rete connessa e il secondo per la rete non connessa) per monitorare lo stato della connessione di rete.

server

  • Gestisce la richiesta del client e ne crea una replica che è privata solo per il client che invia la richiesta e questa replica del server viene eseguita su thread diversi.

Ora dal lato client, come accedere a tutti i metodi del server?

  • server invia risposta con IBind Object.so L'oggetto IBind è il nostro gestore che accede a tutti i metodi di servizio utilizzando l'operatore (.).

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

ora come chiamare il metodo che si trova nel servizio

myservice.serviceMethod();

ecco l' myServiceoggetto ed serviceMethodeè il metodo in servizio. E in questo modo viene stabilita la comunicazione tra client e server.


10

Ho provato a chiamare

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

di conseguenza e potrei creare un servizio appiccicoso e legarmi ad esso. Esercitazione dettagliata per l' esempio di servizio associato .


5

C'è un metodo chiamato unbindService che prenderà una ServiceConnection che avrai creato chiamando bindService. Ciò ti consentirà di disconnetterti dal servizio lasciandolo ancora in esecuzione.

Ciò potrebbe rappresentare un problema quando ti connetti di nuovo, poiché probabilmente non sai se è in esecuzione o meno quando inizi di nuovo l'attività, quindi dovrai tenerlo in considerazione nel tuo codice attività.

In bocca al lupo!


-1

Questa è una risposta parziale, ma ho scritto una libreria che potrebbe semplificare l'utilizzo dei servizi Android, se vengono eseguiti localmente nello stesso processo dell'app: https://github.com/germnix/acacia

Fondamentalmente si definisce un'interfaccia annotata con @Service e la sua classe di implementazione, e la libreria crea e associa il servizio, gestisce la connessione e il thread di lavoro in background:

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

Puoi ottenere un'istanza dell'associato android.app.Service per nascondere / mostrare le notifiche persistenti, utilizzare il tuo android.app.Service e gestire manualmente il threading se lo desideri.


-5

Se l'utente si ritira, il onDestroy()metodo verrà chiamato. Questo metodo serve per arrestare qualsiasi servizio utilizzato nell'applicazione. Quindi, se vuoi continuare il servizio anche se l'utente si ritira dall'applicazione, basta cancellare onDestroy(). Spero che questo aiuto.


Dovresti sovrascrivere la funzione ed eliminare la chiamata predefinita a onDestroy () della superclasse se il tuo IDE ne crea automaticamente uno. ma perché mai avresti voluto farlo?
Riptyde4
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.