Przykład: komunikacja między działaniem a usługą za pomocą wiadomości

584

Nie mogłem znaleźć żadnych przykładów wysyłania wiadomości między działaniem a usługą i spędziłem zbyt wiele godzin, zastanawiając się nad tym. Oto przykładowy projekt, do którego inni mogą się odwoływać.

Ten przykład umożliwia bezpośrednie uruchomienie lub zatrzymanie usługi oraz oddzielne powiązanie / usunięcie powiązania z usługą. Gdy usługa jest uruchomiona, zwiększa liczbę o 10 Hz. Jeśli działanie jest powiązane z Service, wyświetli bieżącą wartość. Dane są przesyłane jako liczba całkowita i ciąg, dzięki czemu można zobaczyć, jak to zrobić na dwa różne sposoby. W działaniu znajdują się również przyciski służące do wysyłania wiadomości do usługi (zmienia wartość przyrostową).

Zrzut ekranu:

Zrzut ekranu z przykładem wiadomości usługi Android

AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.exampleservice"
      android:versionCode="1"
      android:versionName="1.0">
    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name=".MainActivity"
                  android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    <service android:name=".MyService"></service>
    </application>
    <uses-sdk android:minSdkVersion="8" />
</manifest>

res \ wartości \ strings.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="app_name">ExampleService</string>
    <string name="service_started">Example Service started</string>
    <string name="service_label">Example Service Label</string>
</resources>

res \ layout \ main.xml:

<RelativeLayout
    android:id="@+id/RelativeLayout01"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content" >

    <Button
        android:id="@+id/btnStart"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Start Service" >
    </Button>

    <Button
        android:id="@+id/btnStop"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:text="Stop Service" >
    </Button>
</RelativeLayout>

<RelativeLayout
    android:id="@+id/RelativeLayout02"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content" >

    <Button
        android:id="@+id/btnBind"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Bind to Service" >
    </Button>

    <Button
        android:id="@+id/btnUnbind"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:text="Unbind from Service" >
    </Button>
</RelativeLayout>

<TextView
    android:id="@+id/textStatus"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="Status Goes Here"
    android:textSize="24sp" />

<TextView
    android:id="@+id/textIntValue"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="Integer Value Goes Here"
    android:textSize="24sp" />

<TextView
    android:id="@+id/textStrValue"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="String Value Goes Here"
    android:textSize="24sp" />

<RelativeLayout
    android:id="@+id/RelativeLayout03"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content" >

    <Button
        android:id="@+id/btnUpby1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Increment by 1" >
    </Button>

    <Button
        android:id="@+id/btnUpby10"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:text="Increment by 10" >
    </Button>
</RelativeLayout>

src \ com.exampleservice \ MainActivity.java:

package com.exampleservice;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
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 android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

public class MainActivity extends Activity {
    Button btnStart, btnStop, btnBind, btnUnbind, btnUpby1, btnUpby10;
    TextView textStatus, textIntValue, textStrValue;
    Messenger mService = null;
    boolean mIsBound;
    final Messenger mMessenger = new Messenger(new IncomingHandler());

    class IncomingHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
            case MyService.MSG_SET_INT_VALUE:
                textIntValue.setText("Int Message: " + msg.arg1);
                break;
            case MyService.MSG_SET_STRING_VALUE:
                String str1 = msg.getData().getString("str1");
                textStrValue.setText("Str Message: " + str1);
                break;
            default:
                super.handleMessage(msg);
            }
        }
    }
    private ServiceConnection mConnection = new ServiceConnection() {
        public void onServiceConnected(ComponentName className, IBinder service) {
            mService = new Messenger(service);
            textStatus.setText("Attached.");
            try {
                Message msg = Message.obtain(null, MyService.MSG_REGISTER_CLIENT);
                msg.replyTo = mMessenger;
                mService.send(msg);
            }
            catch (RemoteException e) {
                // In this case the service has crashed before we could even do anything with it
            }
        }

        public void onServiceDisconnected(ComponentName className) {
            // This is called when the connection with the service has been unexpectedly disconnected - process crashed.
            mService = null;
            textStatus.setText("Disconnected.");
        }
    };

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        btnStart = (Button)findViewById(R.id.btnStart);
        btnStop = (Button)findViewById(R.id.btnStop);
        btnBind = (Button)findViewById(R.id.btnBind);
        btnUnbind = (Button)findViewById(R.id.btnUnbind);
        textStatus = (TextView)findViewById(R.id.textStatus);
        textIntValue = (TextView)findViewById(R.id.textIntValue);
        textStrValue = (TextView)findViewById(R.id.textStrValue);
        btnUpby1 = (Button)findViewById(R.id.btnUpby1);
        btnUpby10 = (Button)findViewById(R.id.btnUpby10);

        btnStart.setOnClickListener(btnStartListener);
        btnStop.setOnClickListener(btnStopListener);
        btnBind.setOnClickListener(btnBindListener);
        btnUnbind.setOnClickListener(btnUnbindListener);
        btnUpby1.setOnClickListener(btnUpby1Listener);
        btnUpby10.setOnClickListener(btnUpby10Listener);

        restoreMe(savedInstanceState);

        CheckIfServiceIsRunning();
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putString("textStatus", textStatus.getText().toString());
        outState.putString("textIntValue", textIntValue.getText().toString());
        outState.putString("textStrValue", textStrValue.getText().toString());
    }
    private void restoreMe(Bundle state) {
        if (state!=null) {
            textStatus.setText(state.getString("textStatus"));
            textIntValue.setText(state.getString("textIntValue"));
            textStrValue.setText(state.getString("textStrValue"));
        }
    }
    private void CheckIfServiceIsRunning() {
        //If the service is running when the activity starts, we want to automatically bind to it.
        if (MyService.isRunning()) {
            doBindService();
        }
    }

    private OnClickListener btnStartListener = new OnClickListener() {
        public void onClick(View v){
            startService(new Intent(MainActivity.this, MyService.class));
        }
    };
    private OnClickListener btnStopListener = new OnClickListener() {
        public void onClick(View v){
            doUnbindService();
            stopService(new Intent(MainActivity.this, MyService.class));
        }
    };
    private OnClickListener btnBindListener = new OnClickListener() {
        public void onClick(View v){
            doBindService();
        }
    };
    private OnClickListener btnUnbindListener = new OnClickListener() {
        public void onClick(View v){
            doUnbindService();
        }
    };
    private OnClickListener btnUpby1Listener = new OnClickListener() {
        public void onClick(View v){
            sendMessageToService(1);
        }
    };
    private OnClickListener btnUpby10Listener = new OnClickListener() {
        public void onClick(View v){
            sendMessageToService(10);
        }
    };
    private void sendMessageToService(int intvaluetosend) {
        if (mIsBound) {
            if (mService != null) {
                try {
                    Message msg = Message.obtain(null, MyService.MSG_SET_INT_VALUE, intvaluetosend, 0);
                    msg.replyTo = mMessenger;
                    mService.send(msg);
                }
                catch (RemoteException e) {
                }
            }
        }
    }


    void doBindService() {
        bindService(new Intent(this, MyService.class), mConnection, Context.BIND_AUTO_CREATE);
        mIsBound = true;
        textStatus.setText("Binding.");
    }
    void doUnbindService() {
        if (mIsBound) {
            // If we have received the service, and hence registered with it, then now is the time to unregister.
            if (mService != null) {
                try {
                    Message msg = Message.obtain(null, MyService.MSG_UNREGISTER_CLIENT);
                    msg.replyTo = mMessenger;
                    mService.send(msg);
                }
                catch (RemoteException e) {
                    // There is nothing special we need to do if the service has crashed.
                }
            }
            // Detach our existing connection.
            unbindService(mConnection);
            mIsBound = false;
            textStatus.setText("Unbinding.");
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        try {
            doUnbindService();
        }
        catch (Throwable t) {
            Log.e("MainActivity", "Failed to unbind from the service", t);
        }
    }
}

src \ com.exampleservice \ MyService.java:

package com.exampleservice;

import java.util.ArrayList;
import java.util.Timer;
import java.util.TimerTask;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
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;

public class MyService extends Service {
    private NotificationManager nm;
    private Timer timer = new Timer();
    private int counter = 0, incrementby = 1;
    private static boolean isRunning = false;

    ArrayList<Messenger> mClients = new ArrayList<Messenger>(); // Keeps track of all current registered clients.
    int mValue = 0; // Holds last value set by a client.
    static final int MSG_REGISTER_CLIENT = 1;
    static final int MSG_UNREGISTER_CLIENT = 2;
    static final int MSG_SET_INT_VALUE = 3;
    static final int MSG_SET_STRING_VALUE = 4;
    final Messenger mMessenger = new Messenger(new IncomingHandler()); // Target we publish for clients to send messages to IncomingHandler.


    @Override
    public IBinder onBind(Intent intent) {
        return mMessenger.getBinder();
    }
    class IncomingHandler extends Handler { // Handler of incoming messages from clients.
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
            case MSG_REGISTER_CLIENT:
                mClients.add(msg.replyTo);
                break;
            case MSG_UNREGISTER_CLIENT:
                mClients.remove(msg.replyTo);
                break;
            case MSG_SET_INT_VALUE:
                incrementby = msg.arg1;
                break;
            default:
                super.handleMessage(msg);
            }
        }
    }
    private void sendMessageToUI(int intvaluetosend) {
        for (int i=mClients.size()-1; i>=0; i--) {
            try {
                // Send data as an Integer
                mClients.get(i).send(Message.obtain(null, MSG_SET_INT_VALUE, intvaluetosend, 0));

                //Send data as a String
                Bundle b = new Bundle();
                b.putString("str1", "ab" + intvaluetosend + "cd");
                Message msg = Message.obtain(null, MSG_SET_STRING_VALUE);
                msg.setData(b);
                mClients.get(i).send(msg);

            }
            catch (RemoteException e) {
                // The client is dead. Remove it from the list; we are going through the list from back to front so this is safe to do inside the loop.
                mClients.remove(i);
            }
        }
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.i("MyService", "Service Started.");
        showNotification();
        timer.scheduleAtFixedRate(new TimerTask(){ public void run() {onTimerTick();}}, 0, 100L);
        isRunning = true;
    }
    private void showNotification() {
        nm = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
        // In this sample, we'll use the same text for the ticker and the expanded notification
        CharSequence text = getText(R.string.service_started);
        // Set the icon, scrolling text and timestamp
        Notification notification = new Notification(R.drawable.icon, text, System.currentTimeMillis());
        // The PendingIntent to launch our activity if the user selects this notification
        PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, MainActivity.class), 0);
        // Set the info for the views that show in the notification panel.
        notification.setLatestEventInfo(this, getText(R.string.service_label), text, contentIntent);
        // Send the notification.
        // We use a layout id because it is a unique number.  We use it later to cancel.
        nm.notify(R.string.service_started, notification);
    }
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i("MyService", "Received start id " + startId + ": " + intent);
        return START_STICKY; // run until explicitly stopped.
    }

    public static boolean isRunning()
    {
        return isRunning;
    }


    private void onTimerTick() {
        Log.i("TimerTick", "Timer doing work." + counter);
        try {
            counter += incrementby;
            sendMessageToUI(counter);

        }
        catch (Throwable t) { //you should always ultimately catch all exceptions in timer tasks.
            Log.e("TimerTick", "Timer Tick Failed.", t);
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        if (timer != null) {timer.cancel();}
        counter=0;
        nm.cancel(R.string.service_started); // Cancel the persistent notification.
        Log.i("MyService", "Service Stopped.");
        isRunning = false;
    }
}
Lance Lefebure
źródło
53
Świetny przykład! Kolejna miła funkcja: jeśli umieścisz android:process=:myservicenameatrybut serviceznacznika swojej usługi w <service android:name="sname" android:process=":myservicename" />pliku manifest.xml, na przykład:, wtedy uruchomisz usługę jako inny proces - a więc w innym wątku. Oznacza to, że każde ciężkie obliczenie wykonane / długie żądanie usługi nie spowoduje zawieszenia wątku interfejsu użytkownika.
sydd
28
Wiem, że podjąłeś wysiłek, aby to zrobić, ale sensowniej byłoby umieścić go na github lub podobnej stronie udostępniania kodu źródłowego i opublikować link tutaj. Ludziom łatwiej jest uruchomić i uruchomić w ten sposób.
Ehtesh Choudhury
25
Dobry przykład. Umieszczam ten kod w repozytorium online (z niewielkimi modyfikacjami) dla tych, którzy chcieliby klonować: bitbucket.org/alexfu/androidserviceexample/src
Alex Fu
7
Przesyłanie wiadomości jest naprawdę konieczne tylko wtedy, gdy twoja usługa może być wywoływana przez inne aplikacje. W przeciwnym razie możesz trzymać się Bindera, który zwraca ci odniesienie do Usługi i po prostu wywołać publiczne metody.
type-a1pha
13
Powinieneś był zadać pytanie, a następnie samemu utworzyć odpowiedź, a nie odpowiedzieć na problem na pytanie. Świetny przykład;)
7hi4g0

Odpowiedzi:

46

Spójrz na przykład LocalService .

Twoje Servicezwraca instancję się do konsumentów, którzy nazywają onBind. Następnie możesz bezpośrednio wchodzić w interakcję z usługą, np. Rejestrować własny interfejs nasłuchiwania w usłudze, aby uzyskać oddzwanianie.

Christopher Orr
źródło
2
Jedynym problemem jest to, że nie używałby Posłańca, więc nie odpowiedziałby na to pseudo-pytanie. Korzystałem z LocalService, ale z przyjemnością znalazłem przykład Messenger / Handler. Nie wierzę, że LocalService można wprowadzić w inny proces.
Ben,
@ Christoper-Orr: Jestem bardzo wdzięczny, że opublikowałeś ten link do Android BroadcastReceiversamouczka. Użyłem a LocalBroadcastManagerdo ciągłej wymiany danych między dwoma Activityinstancjami.
Dirk
Problem LocalBroadcastManagerpolega na tym, że nie blokuje i trzeba czekać na wyniki. Czasami chcesz natychmiastowych rezultatów.
TheRealChx101
Czy możesz mi pomóc z tym pytaniem stackoverflow.com/questions/51508046/…
Rajesh K
20

Do wysyłania danych do usługi możesz użyć:

Intent intent = new Intent(getApplicationContext(), YourService.class);
intent.putExtra("SomeData","ItValue");
startService(intent);

A potem w usłudze onStartCommand () pobierz dane z zamiaru.

Aby wysłać dane lub zdarzenie z usługi do aplikacji (dla jednego lub więcej działań):

private void sendBroadcastMessage(String intentFilterName, int arg1, String extraKey) {
    Intent intent = new Intent(intentFilterName);
    if (arg1 != -1 && extraKey != null) {
        intent.putExtra(extraKey, arg1);
    }
    sendBroadcast(intent);
}

Ta metoda dzwoni z Twojej usługi. Możesz po prostu wysłać dane dotyczące swojej aktywności.

private void someTaskInYourService(){

    //For example you downloading from server 1000 files
    for(int i = 0; i < 1000; i++) {
        Thread.sleep(5000) // 5 seconds. Catch in try-catch block
        sendBroadCastMessage(Events.UPDATE_DOWNLOADING_PROGRESSBAR, i,0,"up_download_progress");
    }

Aby otrzymać zdarzenie z danymi, utwórz i zarejestruj metodę registerBroadcastReceivers () w swojej działalności:

private void registerBroadcastReceivers(){
    broadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            int arg1 = intent.getIntExtra("up_download_progress",0);
            progressBar.setProgress(arg1);
        }
    };
    IntentFilter progressfilter = new IntentFilter(Events.UPDATE_DOWNLOADING_PROGRESS);
    registerReceiver(broadcastReceiver,progressfilter);

Aby wysłać więcej danych, możesz zmodyfikować metodę sendBroadcastMessage();. Pamiętaj: musisz zarejestrować transmisje w onResume () i wyrejestrować się w metodach onStop ()!

AKTUALIZACJA

Nie używaj mojego rodzaju komunikacji między Aktywnością a Usługą. To jest zły sposób. Dla lepszego doświadczenia skorzystaj ze specjalnych bibliotek, takich jak:

1) EventBus z greenrobot

2) Otto z Square Inc

PS Używam tylko EventBus z greenrobot w moich projektach,

a. czarny 13
źródło
2
gdzie powinienem zarejestrować odbiornik w onResume i onStop, czy muszę to robić w działaniu?
user3233280,
Tak. Aby otrzymać zdarzenie z usługi, musisz zarejestrować transmisję w onResume. Pamiętaj, że musisz wyrejestrować transmisję w OnStop. Teraz nie polecam używać mojej metody. Proszę używać specjalnych bibliotek lib do komunikowania się z innymi widokami / działaniami / usługami, takimi jak EventBus github.com/greenrobot/EventBus lub Otto github.com/square/otto
a.black13 25.10.14
1
czy mogę pomóc, jak mogę tego użyć, utknąłem w projekcie w komunikacji usługowej
3233280,
8
Czy Google odradza to, czy po prostu twierdzisz, że to „źle”, ponieważ uważasz, że inne rozwiązania są lepsze?
Kevin Krumwiede,
plus jeden za udostępnienie linków do EventBusi Otto.
Mohammed Ali
14

Uwaga: nie musisz sprawdzać, czy usługa jest uruchomiona CheckIfServiceIsRunning(), ponieważ bindService()uruchomi się, jeśli nie będzie działać.

Ponadto: jeśli obrócisz telefon, nie chcesz go bindService()ponownie, ponieważ onCreate()zostanie on ponownie wywołany. Pamiętaj, aby zdefiniować, onConfigurationChanged()aby temu zapobiec.

Ktoś gdzieś
źródło
W moim przypadku usługa nie jest potrzebna przez cały czas. Jeśli usługa jest już uruchomiona w momencie rozpoczęcia działania, chcę się z nią powiązać. Jeśli usługa nie działa w momencie rozpoczęcia działania, chcę, aby usługa została zatrzymana.
Lance Lefebure,
1
Nie jestem pewien, czy to prawda, bindService nie uruchamia usługi, czy możesz wskazać dokumentację?
Calin
1
developer.android.com/reference/android/app/Service.html stanach akapit pierwszyServices can be started with Context.startService() and Context.bindService()
ktoś gdzieś
8
Message msg = Message.obtain(null, 2, 0, 0);
                    Bundle bundle = new Bundle();
                    bundle.putString("url", url);
                    bundle.putString("names", names);
                    bundle.putString("captions",captions); 
                    msg.setData(bundle);

Więc wysyłasz to do serwisu. Potem otrzymaj.

użytkownik1964369
źródło
8

Wszystko jest w porządku. Dobry przykład activity/servicekomunikacji za pomocą Messengera .

Jeden komentarz: metoda MyService.isRunning()nie jest wymagana. bindService()Można to zrobić dowolną liczbę razy. bez szkody.

Jeśli MyService działa w innym procesie, funkcja statyczna MyService.isRunning()zawsze zwróci false. Więc nie ma potrzeby tej funkcji.

Ishank Gupta
źródło
2

W ten sposób wdrożyłem Activity-> Service Communication: na mojej działalności miałem

private static class MyResultReciever extends ResultReceiver {
     /**
     * Create a new ResultReceive to receive results.  Your
     * {@link #onReceiveResult} method will be called from the thread running
     * <var>handler</var> if given, or from an arbitrary thread if null.
     *
     * @param handler
     */
     public MyResultReciever(Handler handler) {
         super(handler);
     }

     @Override
     protected void onReceiveResult(int resultCode, Bundle resultData) {
         if (resultCode == 100) {
             //dostuff
         }
     }

A potem użyłem tego do uruchomienia mojej usługi

protected void onCreate(Bundle savedInstanceState) {
MyResultReciever resultReciever = new MyResultReciever(handler);
        service = new Intent(this, MyService.class);
        service.putExtra("receiver", resultReciever);
        startService(service);
}

W mojej służbie miałem

public int onStartCommand(Intent intent, int flags, int startId) {
    if (intent != null)
        resultReceiver = intent.getParcelableExtra("receiver");
    return Service.START_STICKY;
}

Mam nadzieję że to pomoże

ketrox
źródło
0

Wydaje mi się, że mogłeś zaoszczędzić trochę pamięci, deklarując swoją aktywność za pomocą „implementuje Handler.Callback”

Quasaur
źródło
0

Świetny samouczek, fantastyczna prezentacja. Schludny, prosty, krótki i bardzo objaśniający. Chociaż notification.setLatestEventInfo(this, getText(R.string.service_label), text, contentIntent);metody już nie ma. Jak stwierdzono trante tutaj , dobre podejście byłoby:

private static final int NOTIFICATION_ID = 45349;

private void showNotification() {
    NotificationCompat.Builder builder =
            new NotificationCompat.Builder(this)
                    .setSmallIcon(R.mipmap.ic_launcher)
                    .setContentTitle("My Notification Title")
                    .setContentText("Something interesting happened");

    Intent targetIntent = new Intent(this, MainActivity.class);
    PendingIntent contentIntent = PendingIntent.getActivity(this, 0, targetIntent, PendingIntent.FLAG_UPDATE_CURRENT);
    builder.setContentIntent(contentIntent);
    _nManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
    _nManager.notify(NOTIFICATION_ID, builder.build());
}

@Override
public void onDestroy() {
    super.onDestroy();
    if (_timer != null) {_timer.cancel();}
    _counter=0;
    _nManager.cancel(NOTIFICATION_ID); // Cancel the persistent notification.
    Log.i("PlaybackService", "Service Stopped.");
    _isRunning = false;
}

Sprawdziłem siebie, wszystko działa jak urok (nazwy działań i usług mogą się różnić od oryginalnych).

zielonoskóra
źródło
0

Widziałem wszystkie odpowiedzi. Chcę powiedzieć najsolidniejszy sposób teraz . To sprawi, że będziesz się komunikować między Activity - Service - Dialog - Fragments(Wszystko).

EventBus

Ta biblioteka, której używam w swoich projektach, ma świetne funkcje związane z przesyłaniem wiadomości.

EventBus w 3 krokach

  1. Zdefiniuj zdarzenia:

    public static class MessageEvent { /* Additional fields if needed */ }

  2. Przygotuj subskrybentów:

Zadeklaruj i dodaj adnotację do metody subskrybowania, opcjonalnie określ tryb wątku :

@Subscribe(threadMode = ThreadMode.MAIN) 
public void onMessageEvent(MessageEvent event) {/* Do something */};

Zarejestruj się i wyrejestruj subskrybenta. Na przykład na Androidzie działania i fragmenty powinny zazwyczaj rejestrować się zgodnie z ich cyklem życia:

@Override
public void onStart() {
    super.onStart();
    EventBus.getDefault().register(this);
}

@Override
public void onStop() {
    super.onStop();
    EventBus.getDefault().unregister(this);
}
  1. Publikuj wydarzenia:

    EventBus.getDefault().post(new MessageEvent());

Po prostu dodaj tę zależność do poziomu aplikacji

compile 'org.greenrobot:eventbus:3.1.1'
Khemraj
źródło