So kommunizieren Android Services mit Activity

251

Ich schreibe meine erste Android-Anwendung und versuche, mich mit der Kommunikation zwischen Diensten und Aktivitäten vertraut zu machen. Ich habe einen Dienst, der im Hintergrund ausgeführt wird und einige GPS- und zeitbasierte Protokollierungen durchführt. Ich werde eine Aktivität haben, mit der der Dienst gestartet und gestoppt wird.

Zuerst muss ich herausfinden können, ob der Dienst ausgeführt wird, wenn die Aktivität gestartet wird. Hier gibt es noch einige andere Fragen, daher denke ich, dass ich das herausfinden kann (aber ich kann Ihnen gerne Ratschläge geben).

Mein eigentliches Problem: Wenn die Aktivität ausgeführt und der Dienst gestartet wird, muss der Dienst Nachrichten an die Aktivität senden können. Einfache Zeichenfolgen und Ganzzahlen an dieser Stelle - meistens Statusmeldungen. Die Nachrichten werden nicht regelmäßig gesendet, daher denke ich nicht, dass das Abrufen des Dienstes ein guter Weg ist, wenn es einen anderen Weg gibt. Ich möchte diese Kommunikation nur, wenn die Aktivität vom Benutzer gestartet wurde. Ich möchte die Aktivität nicht über den Dienst starten. Mit anderen Worten, wenn Sie die Aktivität starten und der Dienst ausgeführt wird, werden in der Benutzeroberfläche der Aktivität einige Statusmeldungen angezeigt, wenn etwas Interessantes passiert. Wenn Sie die Aktivität nicht starten, werden diese Nachrichten nicht angezeigt (sie sind nicht so interessant).

Es scheint, als sollte ich feststellen können, ob der Dienst ausgeführt wird, und wenn ja, die Aktivität als Listener hinzufügen. Entfernen Sie dann die Aktivität als Listener, wenn die Aktivität angehalten oder gestoppt wird. Ist das eigentlich möglich? Die einzige Möglichkeit, dies herauszufinden, besteht darin, dass die Aktivität Parcelable implementiert und eine AIDL-Datei erstellt, damit ich sie über die Remote-Schnittstelle des Dienstes weiterleiten kann. Das scheint jedoch übertrieben zu sein, und ich habe keine Ahnung, wie die Aktivität writeToParcel () / readFromParcel () implementieren soll.

Gibt es einen einfacheren oder besseren Weg? Vielen Dank für jede Hilfe.

BEARBEITEN:

Für alle, die sich später dafür interessieren, gibt es im Beispielverzeichnis einen Beispielcode von Google, der dies über AIDL handhabt: /apis/app/RemoteService.java

Scott Saunders
quelle

Antworten:

94

Es gibt drei offensichtliche Möglichkeiten, mit Diensten zu kommunizieren:

  1. Absichten verwenden
  2. Verwenden von AIDL
  3. Verwenden des Serviceobjekts selbst (als Singleton)

In Ihrem Fall würde ich Option 3 wählen. Erstellen Sie einen statischen Verweis auf den Dienst selbst und füllen Sie ihn in onCreate () aus:

void onCreate(Intent i) {
  sInstance = this;
}

Erstellen Sie eine statische Funktion MyService getInstance(), die die statische zurückgibt sInstance.

Activity.onCreate()Warten Sie dann beim Starten des Dienstes asynchron, bis der Dienst tatsächlich gestartet wurde (Sie können Ihren Dienst benachrichtigen, dass er bereit ist, indem Sie eine Absicht an die Aktivität senden.), Und rufen Sie seine Instanz ab. Wenn Sie die Instanz haben, registrieren Sie Ihr Service-Listener-Objekt bei Ihrem Service und Sie sind festgelegt. ANMERKUNG: Wenn Sie Ansichten innerhalb der Aktivität bearbeiten, sollten Sie sie im UI-Thread ändern. Der Dienst führt wahrscheinlich einen eigenen Thread aus, sodass Sie aufrufen müssen Activity.runOnUiThread().

Das letzte, was Sie tun müssen, ist, den Verweis auf Ihr Listener-Objekt in zu entfernen Activity.onPause(), da sonst eine Instanz Ihres Aktivitätskontexts ausläuft und nicht gut ist.

HINWEIS: Diese Methode ist nur nützlich, wenn Ihre Anwendung / Aktivität / Aufgabe der einzige Prozess ist, der auf Ihren Dienst zugreift. Ist dies nicht der Fall, müssen Sie Option 1 oder 2 verwenden.

MrSnowflake
quelle
2
Wie kann ich busy-waitdie Aktivität? Kannst du bitte erklären ?
iTurki
1
Legen Sie also entweder nach onCreate oder nach onStartCommand in Ihrer Serviceklasse eine öffentliche statische Variable fest, rufen Sie sie isConnected oder etwas auf true auf. Führen Sie dann in Ihrer Aktivität Folgendes aus: Absichtsabsicht = neue Absicht (act, YourService.class); startService (Absicht); while (! YourService.isConnected) {sleep (300); } Nach dieser Schleife wird Ihr Dienst ausgeführt und Sie können mit ihm kommunizieren. Nach meiner Erfahrung gibt es definitiv einige Einschränkungen bei der Interaktion mit einem solchen Dienst.
Matt Wolfe
Warum kann es nur in gestartet werden Activity.onCreate()?
Skywall
Gibt es ein Wort darüber, warum Sie keine IntentsDaten über ParcellableNachrichten zwischen ihnen senden möchten ?
Aman Alam
2
Dies funktioniert, aber die Antwort von @ MaximumGoat ist viel sauberer und beinhaltet kein Warten.
Matt
262

Der Fragesteller ist wahrscheinlich längst daran vorbeigekommen, aber falls jemand anderes danach sucht ...

Es gibt noch einen anderen Weg, der meiner Meinung nach der einfachste ist.

Fügen Sie BroadcastReceiverIhrer Aktivität ein hinzu. Registrieren Sie es, um eine benutzerdefinierte Absicht zu erhalten, onResumeund heben Sie die Registrierung auf onPause. Senden Sie diese Absicht dann von Ihrem Dienst aus, wenn Sie Ihre Statusaktualisierungen senden möchten oder was Sie haben.

Stellen Sie sicher, dass Sie nicht unglücklich wären, wenn eine andere App auf Sie hören würde Intent(könnte jemand etwas Böses tun?), Aber darüber hinaus sollten Sie in Ordnung sein.

Codebeispiel wurde angefordert:

In meinem Dienst habe ich Folgendes:

// Do stuff that alters the content of my local SQLite Database
sendBroadcast(new Intent(RefreshTask.REFRESH_DATA_INTENT));

( RefreshTask.REFRESH_DATA_INTENTist nur eine konstante Zeichenfolge.)

In meiner Höraktivität definiere ich meine BroadcastReceiver:

private class DataUpdateReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent.getAction().equals(RefreshTask.REFRESH_DATA_INTENT)) {
          // Do stuff - maybe update my view based on the changed DB contents
        }
    }
}

Ich erkläre meinen Empfänger zum Klassenbesten:

private DataUpdateReceiver dataUpdateReceiver;

Ich überschreibe onResume, um dies hinzuzufügen:

if (dataUpdateReceiver == null) dataUpdateReceiver = new DataUpdateReceiver();
IntentFilter intentFilter = new IntentFilter(RefreshTask.REFRESH_DATA_INTENT);
registerReceiver(dataUpdateReceiver, intentFilter);

Und ich überschreibe, onPauseum hinzuzufügen:

if (dataUpdateReceiver != null) unregisterReceiver(dataUpdateReceiver);

Jetzt wartet meine Aktivität darauf, dass mein Dienst sagt: "Hey, aktualisiere dich." Ich könnte Daten in der übergeben, Intentanstatt Datenbanktabellen zu aktualisieren und dann zurück zu gehen, um die Änderungen in meiner Aktivität zu finden, aber da ich möchte, dass die Änderungen trotzdem bestehen bleiben, ist es sinnvoll, die Daten über die Datenbank zu übergeben.

MaximumGoat
quelle
5
Wie? Was Sie beschreiben, ist genau das, was ich brauche. Darüber hinaus benötige ich einen vollständigen Beispielcode. Danke im Voraus. Zu Ihrer Information, als ich das letzte Mal versuchte, ein Widget zu schreiben, dauerte der Messaging-Teil 2 Monate. Lachen Sie, wenn Sie wollen, aber Ihre Experten müssen mehr veröffentlichen, da IMHO Android komplizierter ist als iOS!
1
aaaaaaa, Der Leitfaden für beschäftigte Programmierer zur erweiterten Android-Entwicklung enthält ein hervorragendes Kapitel zu Widgets. Es ist die einzige Ressource, die mich durch dieses Chaos gebracht hat. CommonsWare, der Autor, hat einen Ruf von 115.000 bei StackOverflow, und ich kann das Buch nur empfehlen. commonsware.com/AdvAndroid
MaximumGoat
64
Broadcastssind fantastisch und wenn Sie nicht möchten, dass Ihre Sendung über Ihren eigenen Prozess hinausgeht, sollten Sie LocalBroadcast
Folgendes
2
Danke Cody, das hatte ich noch nie gesehen.
MaximumGoat
3
Dies ist eine sehr gute Art der Kommunikation. Aber was tun, wenn Ergebnisse erzielt wurden, wenn die Aktivität unterbrochen war? Nach onResume kann die Aktivität also lange auf Ergebnisse warten. Und es werden keine Daten empfangen, da Daten übersehen wurden.
Anton-M
39

Verwenden Sie LocalBroadcastManagerdiese Option , um einen Empfänger zu registrieren, der auf eine Sendung wartet, die vom lokalen Dienst in Ihrer App gesendet wurde. Die Referenz finden Sie hier:

http://developer.android.com/reference/android/support/v4/content/LocalBroadcastManager.html

Jack Gao
quelle
3
Ja, eine sehr schöne Diskussion über Localbroadcast hier Link
SohailAziz
1
LocalBroadcastManagerist jetzt zugunsten LiveDataoder anderer Beobachtermuster-Tools veraltet : developer.android.com/reference/androidx/localbroadcastmanager/…
Ali Nem
20

Ich bin überrascht, dass niemand auf die Otto Event Bus Bibliothek Bezug genommen hat

http://square.github.io/otto/

Ich habe dies in meinen Android-Apps verwendet und es funktioniert nahtlos.

Madhur Ahuja
quelle
7
Alternativ gibt es die EventBus- Bibliothek von greenrobot .
Jazzer
15
Denken Sie jedoch daran, dass EventBus und otto immer in einem Prozess sind. Wenn Sie einen Dienst verwenden, der sich in einem eigenen Prozess befindet (beginnend mit dem Festlegen, dass android:process=":my_service"sie nicht kommunizieren können.
Ron
20

Die Verwendung eines Messenger ist eine weitere einfache Möglichkeit, zwischen einem Dienst und einer Aktivität zu kommunizieren.

Erstellen Sie in der Aktivität einen Handler mit einem entsprechenden Messenger. Dadurch werden Nachrichten von Ihrem Dienst verarbeitet.

class ResponseHandler extends Handler {
    @Override public void handleMessage(Message message) {
            Toast.makeText(this, "message from service",
                    Toast.LENGTH_SHORT).show();
    }
}
Messenger messenger = new Messenger(new ResponseHandler());

Der Messenger kann an den Dienst übergeben werden, indem er an eine Nachricht angehängt wird:

Message message = Message.obtain(null, MyService.ADD_RESPONSE_HANDLER);
message.replyTo = messenger;
try {
    myService.send(message);
catch (RemoteException e) {
    e.printStackTrace();
}

Ein vollständiges Beispiel finden Sie in den API-Demos: MessengerService und MessengerServiceActivity . Im vollständigen Beispiel erfahren Sie, wie MyService funktioniert.

Kjetil
quelle
1
Sehr geschätzt! Funktioniert perfekt. Nur ein Detail im Code: myService.send(message);sollte messenger.send(message);stattdessen sein.
Federico Cristina
9

Die andere Methode, die in den anderen Kommentaren nicht erwähnt wird, besteht darin, mit bindService () eine Bindung an den Dienst aus der Aktivität herzustellen und eine Instanz des Dienstes im ServiceConnection-Rückruf abzurufen. Wie hier beschrieben http://developer.android.com/guide/components/bound-services.html

Miguel
quelle
4
Dies ist der richtige Weg, um eine Referenz der Dienstinstanz zu erhalten.
21.
9

Sie können das auch LiveDatawie ein verwenden EventBus.

class MyService : LifecycleService() {
    companion object {
        var BUS = MutableLiveData<Object>()
    }

    override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
        super.onStartCommand(intent, flags, startId)

        val testItem : Object

        // expose your data
        if (BUS.hasActiveObservers()) {
            BUS.postValue(testItem)
        }

        return START_NOT_STICKY
    }
}

Fügen Sie dann einen Beobachter von Ihrem hinzu Activity.

MyService.BUS.observe(this, Observer {
    it?.let {
        // Do what you need to do here
    }
})

Sie können mehr von diesem Blog lesen .

Zeenosaurier
quelle
2

Eine andere Möglichkeit könnte darin bestehen, Beobachter mit einer gefälschten Modellklasse über die Aktivität und den Dienst selbst zu verwenden und eine MVC-Mustervariation zu implementieren. Ich weiß nicht, ob es der beste Weg ist, dies zu erreichen, aber es ist der Weg, der für mich funktioniert hat. Wenn Sie ein Beispiel brauchen, fragen Sie danach und ich werde etwas posten.

Umleiten__
quelle
Ich kämpfe mit ähnlichen Gedanken. Ich habe Aktivität und 2 Dienste, die das gleiche Modell haben. Das Modell kann entweder in einer Aktivität oder in einem dieser Dienste aktualisiert werden, daher habe ich mir überlegt, Beobachter irgendwie zu verwenden, kann es aber nicht herausfinden. Können Sie ein Beispiel posten, um Ihre Idee zu zeigen?
Pzo
2

Meine Methode:

Klasse zum Verwalten des Sendens und Empfangens von Nachrichten von / zu Service / Aktivität:

import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.util.Log;

import java.util.ArrayList;
import java.util.List;

public class MessageManager {

    public interface IOnHandleMessage{
        // Messages
        int MSG_HANDSHAKE = 0x1;

        void onHandleMessage(Message msg);
    }

    private static final String LOGCAT = MessageManager.class.getSimpleName();

    private Messenger mMsgSender;
    private Messenger mMsgReceiver;
    private List<Message> mMessages;

    public MessageManager(IOnHandleMessage callback, IBinder target){
        mMsgReceiver = new Messenger(new MessageHandler(callback, MessageHandler.TYPE_ACTIVITY));
        mMsgSender = new Messenger(target);
        mMessages = new ArrayList<>();
    }

    public MessageManager(IOnHandleMessage callback){
        mMsgReceiver = new Messenger(new MessageHandler(callback, MessageHandler.TYPE_SERVICE));
        mMsgSender = null;
        mMessages = new ArrayList<>();
    }

    /* START Getter & Setter Methods */
    public Messenger getMsgSender() {
        return mMsgSender;
    }

    public void setMsgSender(Messenger sender) {
        this.mMsgSender = sender;
    }

    public Messenger getMsgReceiver() {
        return mMsgReceiver;
    }

    public void setMsgReceiver(Messenger receiver) {
        this.mMsgReceiver = receiver;
    }

    public List<Message> getLastMessages() {
        return mMessages;
    }

    public void addMessage(Message message) {
        this.mMessages.add(message);
    }
    /* END Getter & Setter Methods */

    /* START Public Methods */
    public void sendMessage(int what, int arg1, int arg2, Bundle msgData){
        if(mMsgSender != null && mMsgReceiver != null) {
            try {
                Message msg = Message.obtain(null, what, arg1, arg2);
                msg.replyTo = mMsgReceiver;
                if(msgData != null){
                    msg.setData(msgData);
                }
                mMsgSender.send(msg);
            } catch (RemoteException rE) {
                onException(rE);
            }
        }
    }

    public void sendHandshake(){
        if(mMsgSender != null && mMsgReceiver != null){
            sendMessage(IOnHandleMessage.MSG_HANDSHAKE, 0, 0, null);
        }
    }
    /* END Public Methods */

    /* START Private Methods */
    private void onException(Exception e){
        Log.e(LOGCAT, e.getMessage());
        e.printStackTrace();
    }
    /* END Private Methods */

    /** START Private Classes **/
    private class MessageHandler extends Handler {

        // Types
        final static int TYPE_SERVICE = 0x1;
        final static int TYPE_ACTIVITY = 0x2;

        private IOnHandleMessage mCallback;
        private int mType;

        public MessageHandler(IOnHandleMessage callback, int type){
            mCallback = callback;
            mType = type;
        }

        @Override
        public void handleMessage(Message msg){
            addMessage(msg);
            switch(msg.what){
                case IOnHandleMessage.MSG_HANDSHAKE:
                    switch(mType){
                        case TYPE_SERVICE:
                            setMsgSender(msg.replyTo);
                            sendHandshake();
                            break;
                        case TYPE_ACTIVITY:
                            Log.v(LOGCAT, "HERE");
                            break;
                    }
                    break;
                default:
                    if(mCallback != null){
                        mCallback.onHandleMessage(msg);
                    }
                    break;
            }
        }

    }
    /** END Private Classes **/

}

Im Aktivitätsbeispiel:

public class activity extends AppCompatActivity
      implements     ServiceConnection,
                     MessageManager.IOnHandleMessage { 

    [....]

    private MessageManager mMessenger;

    private void initMyMessenger(IBinder iBinder){
        mMessenger = new MessageManager(this, iBinder);
        mMessenger.sendHandshake();
    }

    private void bindToService(){
        Intent intent = new Intent(this, TagScanService.class);
        bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
        /* START THE SERVICE IF NEEDED */
    }

    private void unbindToService(){
    /* UNBIND when you want (onDestroy, after operation...)
        if(mBound) {
            unbindService(mServiceConnection);
            mBound = false;
        }
    }

    /* START Override MessageManager.IOnHandleMessage Methods */
    @Override
    public void onHandleMessage(Message msg) {
        switch(msg.what){
            case Constants.MSG_SYNC_PROGRESS:
                Bundle data = msg.getData();
                String text = data.getString(Constants.KEY_MSG_TEXT);
                setMessageProgress(text);
                break;
            case Constants.MSG_START_SYNC:
                onStartSync();
                break;
            case Constants.MSG_END_SYNC:
                onEndSync(msg.arg1 == Constants.ARG1_SUCCESS);
                mBound = false;
                break;
        }
    }
    /* END Override MessageManager.IOnHandleMessage Methods */

    /** START Override ServiceConnection Methods **/
    private class BLEScanServiceConnection implements ServiceConnection {

        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            initMyMessenger(iBinder);
            mBound = true;
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            mMessenger = null;
            mBound = false;
        }
    }
    /** END Override ServiceConnection Methods **/

Im Servicebeispiel:

public class Blablabla extends Service
    implements     MessageManager.IOnHandleMessage {

    [...]

    private MessageManager mMessenger;

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        super.onBind(intent);
        initMessageManager();
        return mMessenger.getMsgReceiver().getBinder();
    }

    private void initMessageManager(){
        mMessenger = new MessageManager(this);
    }

    /* START Override IOnHandleMessage Methods */
    @Override
    public void onHandleMessage(Message msg) {
    /* Do what you want when u get a message looking the "what" attribute */
    }
    /* END Override IOnHandleMessage Methods */

Senden Sie eine Nachricht von Aktivität / Service:

mMessenger.sendMessage(what, arg1, arg2, dataBundle);

So funktioniert das:

auf die Aktivität, die Sie starten oder den Dienst binden. Die Service "OnBind" -Methoden geben den Binder an seinen MessageManager zurück. In der Aktivität über die "Service Connection" -Schnittstellenimplementierung "OnServiceConnected" erhalten Sie diesen IBinder und initiieren den MessageManager damit. Nachdem die Aktivität seinen MessageManager initiiert hat, sendet der MessageHandler und Handshake an den Dienst, damit er seinen Absender "MessageHandler" (den "privaten Messenger mMsgSender" in MessageManager) festlegen kann. Dabei weiß der Dienst, wer seine Nachrichten sendet.

Sie können dies auch mithilfe einer Liste / Warteschlange des Messenger "Absenders" im MessageManager implementieren, um mehrere Nachrichten an verschiedene Aktivitäten / Dienste zu senden, oder Sie können eine Liste / Warteschlange des Messenger "Empfängers" im MessageManager verwenden, um mehrere zu empfangen Nachricht von verschiedenen Aktivitäten / Diensten.

In der Instanz "MessageManager" haben Sie eine Liste aller empfangenen Nachrichten.

Da Sie sehen können, dass die Verbindung zwischen "Activity's Messenger" und "Service Messenger" mithilfe dieser "MessageManager" -Instanz automatisch erfolgt, erfolgt dies über die "OnServiceConnected" -Methode und über den "Handshake".

Hoffe das ist hilfreich für dich :) Vielen Dank! Tschüss: D.

Z3R0
quelle
2

Um die Antwort von @MrSnowflake mit einem Codebeispiel zu verfolgen. Dies ist die jetzt Open Source- ApplicationKlasse von XABBER . Die ApplicationKlasse zentralisiert und koordiniert Listenersund ManagerInterfaces und mehr. Manager aller Art werden dynamisch geladen. Activity´sIm Xabber gestartet wird gemeldet, in welcher Art Listenersie sind. Und wenn ein ServiceStart erfolgt, meldet er sich Applicationwie gestartet in der Klasse. Jetzt eine Nachricht an eine senden Activityalles , was Sie Ihr machen zu tun haben , Activityein geworden listener, welche Art Sie benötigen. Im OnStart() OnPause()Register / unreg. Sie Servicekönnen die ApplicationKlasse nur darum bitten, dass listenersie mit ihr sprechen muss, und wenn sie dort ist, ist die Aktivität bereit zu empfangen.

Wenn Sie durch die ApplicationKlasse gehen, werden Sie sehen, dass eine Beute mehr los ist als diese.

Erik
quelle
Der bereitgestellte Link führt jetzt zu einem Github 404. Hat er sich bewegt?
JE Carter II
Ja, scheint jetzt zu funktionieren. Muss ein vorübergehendes Problem bei Github gewesen sein.
JE Carter II
1

Bindung ist eine andere Art zu kommunizieren

Erstellen Sie einen Rückruf

public interface MyCallBack{

   public void getResult(String result);

}

Aktivitätsseite:

  1. Implementieren Sie die Schnittstelle in der Aktivität

  2. Stellen Sie die Implementierung für die Methode bereit

  3. Binden Sie die Aktivität an den Service

  4. Registrieren und Aufheben der Registrierung des Rückrufs, wenn der Dienst an die Aktivität gebunden und nicht mehr gebunden ist.

    public class YourActivity extends AppCompatActivity implements MyCallBack{
    
          private Intent notifyMeIntent;
          private GPSService gpsService;
          private boolean bound = false;
    
          @Override
          public void onCreate(Bundle sis){
    
              // activity code ...
    
              startGPSService();
    
          }
    
          @Override
          public void getResult(String result){
           // show in textView textView.setText(result);
          }
    
          @Override
          protected void onStart()
          {
              super.onStart();
              bindService();
          }
    
          @Override
          protected void onStop() {
              super.onStop();
              unbindService();
          }
    
          private ServiceConnection serviceConnection = new ServiceConnection() {
    
                @Override
                public void onServiceConnected(ComponentName className, IBinder service) {
    
                      GPSService.GPSBinder binder = (GPSService.GPSBinder) service;
                      gpsService= binder.getService();
                      bound = true;
                      gpsService.registerCallBack(YourActivity.this); // register
    
               }
    
               @Override
               public void onServiceDisconnected(ComponentName arg0) {
                      bound = false;
               }
          };
    
          private void bindService() {
    
               bindService(notifyMeIntent, serviceConnection, Context.BIND_AUTO_CREATE);
          }
    
          private void unbindService(){
               if (bound) {
                     gpsService.registerCallBack(null); // unregister            
                     unbindService(serviceConnection);
                     bound = false;
                }
          }
    
          // Call this method somewhere to start Your GPSService
          private void startGPSService(){
               notifyMeIntent = new Intent(this, GPSService.class);
               startService(myIntent );
          }
    
     }

Service-Seite:

  1. Rückruf initialisieren

  2. Rufen Sie bei Bedarf die Rückrufmethode auf

     public class GPSService extends Service{
    
         private MyCallBack myCallback;
         private IBinder serviceBinder = new GPSBinder();
    
         public void registerCallBack(MyCallBack myCallback){
              this.myCallback= myCallback;
         }
    
         public class GPSBinder extends Binder{
    
             public GPSService getService(){
                  return GPSService.this;
             }
        }
    
        @Nullable
        @Override
        public IBinder onBind(Intent intent){
             return serviceBinder;
        }
     }
Rohit Singh
quelle
Du serviceConnectionbist raus onCreate. Bitte bearbeiten Sie es.
Adeel Zafar
Es muss nicht drinnen sein auf Create
Rohit Singh
0

Neben LocalBroadcastManager, Event Bus und Messenger , die in dieser Frage bereits beantwortet wurden, können wir Pending Intent verwenden , um vom Dienst aus zu kommunizieren.

Wie hier in meinem Blogbeitrag erwähnt

Die Kommunikation zwischen Dienst und Aktivität kann über PendingIntent erfolgen. Damit wir createPendingResult () verwenden können, erstellt .createPendingResult () ein neues PendingIntent-Objekt, das Sie dem Dienst übergeben können, um es zu verwenden und Ergebnisdaten an Ihre Aktivität in onActivityResult (int, zurück zu senden). Rückruf von int, Intent). Da ein PendingIntent parcelbar ist und daher in einen Intent-Zusatz eingefügt werden kann, kann Ihre Aktivität diesen PendingIntent an den Dienst übergeben. Der Dienst kann wiederum die send () -Methode für den PendingIntent aufrufen, um den zu benachrichtigen Aktivität über onActivityErgebnis eines Ereignisses.

Aktivität

public class PendingIntentActivity extends AppCompatActivity
{
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

PendingIntent pendingResult = createPendingResult(
100, new Intent(), 0);
Intent intent = new Intent(getApplicationContext(), PendingIntentService.class);
intent.putExtra("pendingIntent", pendingResult);
startService(intent);

}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 100 && resultCode==200) {
Toast.makeText(this,data.getStringExtra("name"),Toast.LENGTH_LONG).show();
}
super.onActivityResult(requestCode, resultCode, data);
}
}

Bedienung

public class PendingIntentService extends Service {

    private static final String[] items= { "lorem", "ipsum", "dolor",
            "sit", "amet", "consectetuer", "adipiscing", "elit", "morbi",
            "vel", "ligula", "vitae", "arcu", "aliquet", "mollis", "etiam",
            "vel", "erat", "placerat", "ante", "porttitor", "sodales",
            "pellentesque", "augue", "purus" };
    private PendingIntent data;

    @Override
    public void onCreate() {
        super.onCreate();
    }

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

        data = intent.getParcelableExtra("pendingIntent");

        new LoadWordsThread().start();
        return START_NOT_STICKY;
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }

    class LoadWordsThread extends Thread {
        @Override
        public void run() {
            for (String item : items) {
                if (!isInterrupted()) {

                    Intent result = new Intent();
                    result.putExtra("name", item);
                    try {
                        data.send(PendingIntentService.this,200,result);
                    } catch (PendingIntent.CanceledException e) {

                        e.printStackTrace();
                    }
                    SystemClock.sleep(400);

                }
            }
        }
    }
}
Android-Entwickler
quelle