Как сделать так, чтобы Android-сервис общался с Activity - PullRequest
233 голосов
/ 17 марта 2010

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

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

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

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

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

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

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

Ответы [ 13 ]

0 голосов
/ 09 мая 2019

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

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

public interface MyCallBack{

   public void getResult(String result);

}

Сторона активности:

  1. Реализация интерфейса в Задании
  2. Предоставить реализацию для метода
  3. Привязать активность к сервису
  4. Регистрация и отмена регистрации обратного вызова, когда Служба связана и не связана с Активность.

    public class YourActivity extends AppCompatActivity implements MyCallBack{
    
          private Intent myIntent;
          private GPSService gpsService;
          private boolean bound = false;
    
          @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 startService(){
               myIntent = 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;
        }
     }
    
0 голосов
/ 27 марта 2018

Помимо LocalBroadcastManager, Event Bus и Messenger уже ответили на этот вопрос, мы можем использовать Ожидающее намерение для связи с сервисом.

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

Связь между сервисом и Деятельностью может осуществляться с помощью PendingIntent. Для этого мы можем использовать createPendingResult (). CreatePendingResult () создает новый PendingIntent объект, который вы можете передать службе использовать и отправить возвращать данные к вашей деятельности внутри onActivityResult (int, int, Намерение) обратный вызов. Так как PendingIntent является Parcelable, и может поэтому вы должны быть включены в намерение дополнительно, ваша деятельность может пройти это 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);

                }
            }
        }
    }
}
0 голосов
/ 07 февраля 2018

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

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

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

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

Зеленый робот EventBus

http://greenrobot.org/eventbus/

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

https://github.com/MindorksOpenSource/NYBus

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...