Как заставить Android-сервис взаимодействовать с Activity

Я пишу свое первое приложение для Android и пытаюсь разобраться в связи между службами и действиями. У меня есть служба, которая будет работать в фоновом режиме и вести журнал на основе GPS и времени. У меня будет действие, которое будет использоваться для запуска и остановки службы.

Итак, сначала мне нужно выяснить, работает ли Служба при запуске Activity. Здесь есть еще несколько вопросов по этому поводу, так что я думаю, что смогу в этом разобраться (но не стесняйтесь давать советы).

Моя настоящая проблема: если Activity запущена, а служба запущена, мне нужен способ для службы отправлять сообщения в Activity. На данный момент простые строки и целые числа - в основном сообщения о состоянии. Сообщения не будут поступать регулярно, поэтому я не думаю, что опрос службы - хороший способ, если есть другой способ. Мне нужно это общение только тогда, когда действие было запущено пользователем - я не хочу запускать действие из службы. Другими словами, если вы запустите Activity, а служба запущена, вы увидите некоторые сообщения о состоянии в пользовательском интерфейсе Activity, когда произойдет что-то интересное. Если вы не запустите Activity, вы не увидите этих сообщений (они не так уж интересны).

Похоже, я смогу определить, запущена ли Служба, и если да, то добавить Activity в качестве слушателя. Затем удалите Activity в качестве слушателя, когда Activity приостанавливается или останавливается. Это вообще возможно? Единственный способ, которым я могу это сделать, - это заставить Activity реализовать Parcelable и создать файл AIDL, чтобы я мог передать его через удаленный интерфейс службы. Это кажется излишним, и я понятия не имею, как Activity должна реализовывать writeToParcel () / readFromParcel ().

Есть способ лучше или проще? Спасибо за любую помощь.

РЕДАКТИРОВАТЬ:

Для тех, кто позже заинтересуется этим, есть образец кода от Google для обработки этого через AIDL в каталоге образцов: /apis/app/RemoteService.java


person Scott Saunders    schedule 17.03.2010    source источник


Ответы (13)


Есть три очевидных способа связи со службами:

  1. Использование намерений
  2. Использование AIDL
  3. Использование самого объекта службы (как синглтона)

В вашем случае я бы выбрал вариант 3. Сделайте статическую ссылку на сам сервис и заполните его в onCreate ():

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

Создайте статическую функцию MyService getInstance(), которая возвращает статический sInstance.

Затем в Activity.onCreate() вы запускаете службу, асинхронно ждете, пока служба действительно не запустится (вы можете настроить службу, чтобы уведомить ваше приложение о своей готовности, отправив намерение для действия) и получить его экземпляр. Когда у вас есть экземпляр, зарегистрируйте объект прослушивателя службы для службы, и все готово. ПРИМЕЧАНИЕ: при редактировании представлений внутри действия вы должны изменить их в потоке пользовательского интерфейса, служба, вероятно, будет запускать свой собственный поток, поэтому вам нужно вызвать Activity.runOnUiThread().

Последнее, что вам нужно сделать, это удалить ссылку на ваш объект прослушивателя в Activity.onPause(), иначе произойдет утечка экземпляра контекста вашей активности, что нехорошо.

ПРИМЕЧАНИЕ. Этот метод полезен только в том случае, если ваше приложение / действие / задача - единственный процесс, который будет обращаться к вашей службе. Если это не так, вы должны использовать вариант 1. или 2.

person MrSnowflake    schedule 17.03.2010
comment
Как я могу busy-wait это действие? Объясните пожалуйста ? - person iTurki; 24.07.2011
comment
Итак, либо после onCreate, либо после onStartCommand в вашем классе обслуживания установите общедоступную статическую переменную, назовите ее isConnected или что-то еще в true. Затем в своей деятельности сделайте следующее: Intent intent = new Intent (act, YourService.class); startService (намерение); в то время как (! YourService.isConnected) {сон (300); } После этого цикла ваша служба запускается, и вы можете общаться с ней. По моему опыту, определенно существуют некоторые ограничения для взаимодействия с такой службой. - person Matt Wolfe; 28.12.2011
comment
Почему его можно запустить только в Activity.onCreate()? - person skywall; 30.04.2012
comment
Есть какие-нибудь слова о том, почему вы не хотели бы использовать Intents, отправляя данные через Parcellable сообщения между ними? - person Aman Alam; 14.12.2012
comment
Это работает, но ответ @ MaximumGoat намного чище и не требует ожидания. - person Matthew; 03.06.2013
comment
это занятое ожидание со сном (xxx) мне совсем не нравится .. Похоже, не очень хороший шаблон дизайна .. - person Ewoks; 29.07.2013
comment
@DanHulme Вы правы, я изменил свой ответ, чтобы служба уведомляла вызывающую активность, когда она готова. - person MrSnowflake; 29.07.2013
comment
Я использовал broadcastReciever, чтобы сообщить вызывающей активности, когда услуга будет готова. - person BK Batchelor; 13.08.2015

Спрашивающий, вероятно, уже давно прошел мимо этого, но на случай, если кто-то еще будет это искать ...

Есть другой способ справиться с этим, я думаю, самый простой.

Добавьте BroadcastReceiver к своей деятельности. Зарегистрируйте его для получения определенного намерения в onResume и отмените его регистрацию в onPause. Затем отправьте это намерение из своей службы, когда вы хотите отправить обновления своего статуса или что у вас есть.

Убедитесь, что вы не будете недовольны, если какое-то другое приложение будет прослушивать ваш Intent (может ли кто-нибудь сделать что-нибудь злонамеренное?), Но кроме этого, все должно быть в порядке.

Был запрошен образец кода:

В моем сервисе есть это:

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

(RefreshTask.REFRESH_DATA_INTENT - это просто постоянная строка.)

В своей деятельности по прослушиванию я определяю свой 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
        }
    }
}

Я объявляю свой приемник лучшим в классе:

private DataUpdateReceiver dataUpdateReceiver;

Я заменяю onResume, чтобы добавить это:

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

И я отменяю onPause, чтобы добавить:

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

Теперь я прислушиваюсь к тому, что моя служба говорит: «Эй, иди обнови себя». Я мог бы передавать данные в Intent вместо обновления таблиц базы данных, а затем возвращаться, чтобы найти изменения в моей деятельности, но поскольку я хочу, чтобы изменения сохранялись в любом случае, имеет смысл передавать данные через БД.

person MaximumGoat    schedule 19.01.2011
comment
Как? То, что вы описываете, - именно то, что мне нужно. Но более того, мне нужен полный пример кода. Заранее спасибо. К вашему сведению, в последний раз, когда я пытался написать виджет, на обмен сообщениями у меня ушло 2 месяца. Смейтесь, если хотите, но вам, экспертам, нужно больше публиковать, потому что ИМХО Android сложнее iOS! - person ; 28.07.2011
comment
aaaaaaa, «Руководство по продвинутой разработке под Android» для занятого программиста содержит отличную главу о виджетах. Это единственный ресурс, который помог мне разобраться в этой неразберихе. Автор CommonsWare имеет репутацию 115 тыс. На StackOverflow, и я очень рекомендую эту книгу. commonsware.com/AdvAndroid - person MaximumGoat; 09.08.2011
comment
Broadcasts великолепны, и, кроме того, если вы не хотите, чтобы трансляция выходила за рамки вашего собственного процесса, подумайте об использовании LocalBroadcast: developer.android.com/reference/android/support/v4/content/. - person Cody Caughlan; 26.02.2012
comment
Спасибо, Коди, я этого раньше не видел. - person MaximumGoat; 28.02.2012
comment
это рекомендуемый способ пересылки большого количества данных от службы к действию? Я имею в виду добавление дополнительных средств в намерение и трансляцию его из службы, регистрацию радиоприемника в действии? 10q - person Ewoks; 12.08.2012
comment
Это очень хороший способ общения. Но что делать, если результаты были получены, когда активность была приостановлена? Так что после действия onResume можно долго ждать результатов. И никаких данных не будет, потому что данные были пропущены. - person Anton-M; 21.04.2013
comment
Антон М .: Ваша активность может запрашивать базу данных в onResume, а также при получении уведомления об обновлении данных. - person MaximumGoat; 22.04.2013
comment
Если вы не отмените регистрацию приемника в onPause, ваше приложение может получать широковещательные сообщения в фоновом режиме без пробуждения и действовать в соответствии с ними, например, с помощью уведомления для пользователя. - person Ryan R; 08.07.2013
comment
@CodyCaughlan Я вижу, что метод sendBroadcast возвращает логическое значение, и я не знаю, что это значит? - person gone; 20.10.2015
comment
Почему мы устанавливаем слушателя в onResume(), а не в onCreate() - person BabbevDan; 16.03.2016
comment
Все еще актуальный ответ 7 лет спустя и очень простой! - person ThePartyTurtle; 07.08.2018
comment
избавил меня от боли :) - person user2672052; 11.01.2020
comment
LocalBroadcastManager теперь устарел в пользу LiveData или других инструментов шаблона наблюдателя: developer.android. ru / reference / androidx / localbroadcastmanager / - person Ali Nem; 23.01.2020
comment
Обновите ответ, чтобы упомянуть / предпочесть LocalBroadcast - person user2297550; 01.01.2021

Используйте LocalBroadcastManager, чтобы зарегистрировать приемник для прослушивания трансляции, отправленной из локальной службы внутри вашего приложения, ссылка находится здесь:

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

person Jack Gao    schedule 13.01.2012
comment
Да, очень хорошее обсуждение localbroadcast здесь ссылка - person SohailAziz; 30.04.2012
comment
LocalBroadcastManager теперь устарел в пользу LiveData или других инструментов шаблона наблюдателя: developer.android. ru / reference / androidx / localbroadcastmanager / - person Ali Nem; 23.01.2020

Использование Messenger - еще один простой способ связи между Сервисом и Активностью.

В Activity создайте обработчик с соответствующим Messenger. Это будет обрабатывать сообщения от вашего Сервиса.

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

Мессенджер можно передать службе, прикрепив его к сообщению:

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

Полный пример можно найти в демонстрациях API: MessengerService и MessengerServiceActivity. Обратитесь к полному примеру, чтобы узнать, как работает MyService.

person Kjetil    schedule 25.02.2012
comment
Очень признателен! Прекрасно работает. Просто деталь в коде: вместо myService.send(message); должно быть messenger.send(message);. - person Federico Cristina; 03.08.2019

Я удивлен, что никто не упомянул библиотеку Otto Event Bus.

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

Я использую это в своих приложениях для Android, и он работает без проблем.

person Madhur Ahuja    schedule 11.03.2014
comment
В качестве альтернативы есть библиотека EventBus от greenrobot. - person Jazzer; 06.04.2015
comment
Но помните, что EventBus и otto всегда находятся в одном процессе. Когда вы используете службу, которая находится в собственном процессе (начиная с установки android:process=":my_service", они не могут взаимодействовать. - person Ron; 16.04.2015

Вы также можете использовать LiveData, который работает как EventBus.

class MyService : LifecycleService() {
    companion object {
        val BUS = MutableLiveData<Any>()
    }

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

Затем добавьте наблюдателя из вашего Activity.

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

Вы можете прочитать больше в этом блоге.

person zeenosaur    schedule 19.11.2018

Другой метод, который не упоминается в других комментариях, - это привязка к службе из действия с помощью bindService () и получение экземпляра службы в обратном вызове ServiceConnection. Как описано здесь, http://developer.android.com/guide/components/bound-services.html

person miguel    schedule 04.12.2014
comment
Это правильный способ получить ссылку на экземпляр службы. - person 김준호; 21.05.2016

Связывание - это еще один способ общения

Создать обратный звонок

public interface MyCallBack{

   public void getResult(String result);

}

Сторона деятельности:

  1. Реализуйте интерфейс в Activity

  2. Предоставьте реализацию для метода

  3. Привязать действие к службе

  4. Зарегистрируйте и отмените регистрацию обратного вызова, когда Служба привязывается и отключается от Activity.

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

Сторона обслуживания:

  1. Инициализировать обратный вызов

  2. При необходимости вызывать метод обратного вызова

     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;
        }
     }
    
person Rohit Singh    schedule 09.05.2019
comment
ваш serviceConnection вышел из onCreate. Пожалуйста, отредактируйте его. - person Adeel Zafar; 09.08.2019
comment
Необязательно быть внутри onCreate - person Rohit Singh; 09.08.2019

Другой способ - использовать наблюдателей с поддельным классом модели через действие и саму службу, реализуя вариант шаблона MVC. Я не знаю, лучший ли это способ добиться этого, но у меня это сработало. Если вам нужен пример, попросите его, и я что-нибудь опубликую.

person ReDirEct__    schedule 26.03.2012
comment
Я борюсь с подобным мнением. У меня есть активность и 2 службы с одинаковой моделью. Модель может быть обновлена ​​как в действии, так и в любой другой службе, поэтому я подумал о том, чтобы как-то использовать Observers, но не могу понять. Можете ли вы опубликовать пример, чтобы показать свою идею? - person pzo; 21.12.2012

Помимо LocalBroadcastManager, Event Bus и Messenger, на которые уже были даны ответы в этом вопросе, мы можем использовать Pending Intent для связи из службы.

Как упоминалось здесь в моем сообщении в блоге

Связь между службой и Activity может осуществляться с помощью PendingIntent. Для этого мы можем использовать createPendingResult () .createPendingResult () создает новый объект PendingIntent, который вы можете передать службе для использования и отправки данных результатов обратно в ваша активность внутри обратного вызова onActivityResult (int, int, Intent). Поскольку PendingIntent является Parcelable и, следовательно, может быть помещен в дополнение Intent, ваша активность может передать это PendingIntent службе. Служба, в свою очередь, может вызвать send () для PendingIntent, чтобы уведомить о действии через onActivityResult о событии.

Деятельность

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

Услуга

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

                }
            }
        }
    }
}
person Android Developer    schedule 27.03.2018

Мой метод:

Класс для управления отправкой и получением сообщений от / до службы / активности:

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 **/

}

В примере деятельности:

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 **/

Пример обслуживания:

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 */

Отправьте сообщение из Activity / Service:

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

Как это работает:

о деятельности, которую вы запускаете, или привязываете службу. Методы службы «OnBind» возвращают Binder в его MessageManager. В Activity через реализацию методов интерфейса «Service Connection» «OnServiceConnected» вы получаете этот IBinder и запускаете MessageManager, используя его. После того, как Activity инициировал свой MessageManager, MessageHandler отправляет и устанавливает связь с сервисом, чтобы он мог установить своего отправителя «MessageHandler» («private Messenger mMsgSender;» в MessageManager). Благодаря этому сервис узнает, кто отправляет его сообщения.

Вы также можете реализовать это с помощью «отправителя» списка / очереди Messenger в MessageManager, чтобы вы могли отправлять несколько сообщений в различные действия / службы, или вы можете использовать «получатель» списка / очереди Messenger в MessageManager, чтобы вы могли получать несколько сообщений. сообщение от различных мероприятий / услуг.

В экземпляре «MessageManager» у вас есть список всех полученных сообщений.

Как вы можете видеть, соединение между Activity Messenger и Service Messenger с помощью этого экземпляра MessageManager является автоматическим, оно осуществляется с помощью метода OnServiceConnected и с помощью «рукопожатия».

Надеюсь, это будет полезно для вас :) Большое спасибо! Пока: D

person Z3R0    schedule 01.02.2019

Чтобы дополнить ответ @MrSnowflake примером кода. Это Application класс XABBER с открытым исходным кодом. Класс Application централизует и координирует Listeners, ManagerInterfaces и многое другое. Менеджеры всех видов загружаются динамически. Activity´s, запущенный в Xabber, сообщит, в каком Listener типе они. И когда Service запускается, он сообщает классу Application о запуске. Теперь, чтобы отправить сообщение Activity, все, что вам нужно сделать, это сделать ваш Activity listener того типа, который вам нужен. В OnStart() OnPause() прописать / отменить регистрацию. Service может запросить Application класс только о том listener, с которым ему нужно поговорить, и если он есть, то Activity готово к приему.

Пройдя курс Application, вы увидите, что там происходит нечто большее, чем это.

person Erik    schedule 17.08.2013
comment
Приведенная ссылка теперь приводит к github 404. Он переместился? - person J E Carter II; 11.10.2019
comment
Ага, похоже, теперь работает. Должно быть, временная проблема на github. - person J E Carter II; 14.10.2019

Как упоминал Мадхур, для общения можно использовать автобус.

В случае использования автобуса у вас есть несколько вариантов:

Библиотека шины событий Otto (устарела в пользу RxJava)

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

Автобусы Green Robot’s EventBus

http://greenrobot.org/eventbus/

NYBus (RxBus, реализованный с использованием RxJava. Очень похож на EventBus)

https://github.com/MindorksOpenSource/NYBus

person Mahpooya    schedule 07.02.2018