How to have Android Service communicate with Activity

前端 未结 13 1876
说谎
说谎 2020-11-22 02:54

I\'m writing my first Android application and trying to get my head around communication between services and activities. I have a Service that will run in the background an

相关标签:
13条回答
  • 2020-11-22 03:18

    Binding is another way to communicate

    Create a callback

    public interface MyCallBack{
    
       public void getResult(String result);
    
    }
    

    Activity side:

    1. Implement the interface in the Activity

    2. Provide the implementation for the method

    3. Bind the Activity to Service

    4. Register and Unregister Callback when the Service gets bound and unbound with 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 );
            }
      
       }
      

    Service Side:

    1. Initialize callback

    2. Invoke the callback method whenever needed

       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 讨论(0)
  • 2020-11-22 03:19

    There are three obvious ways to communicate with services:

    1. Using Intents
    2. Using AIDL
    3. Using the service object itself (as singleton)

    In your case, I'd go with option 3. Make a static reference to the service it self and populate it in onCreate():

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

    Make a static function MyService getInstance(), which returns the static sInstance.

    Then in Activity.onCreate() you start the service, asynchronously wait until the service is actually started (you could have your service notify your app it's ready by sending an intent to the activity.) and get its instance. When you have the instance, register your service listener object to you service and you are set. NOTE: when editing Views inside the Activity you should modify them in the UI thread, the service will probably run its own Thread, so you need to call Activity.runOnUiThread().

    The last thing you need to do is to remove the reference to you listener object in Activity.onPause(), otherwise an instance of your activity context will leak, not good.

    NOTE: This method is only useful when your application/Activity/task is the only process that will access your service. If this is not the case you have to use option 1. or 2.

    0 讨论(0)
  • 2020-11-22 03:19

    The other method that's not mentioned in the other comments is to bind to the service from the activity using bindService() and get an instance of the service in the ServiceConnection callback. As described here http://developer.android.com/guide/components/bound-services.html

    0 讨论(0)
  • 2020-11-22 03:21

    As mentioned by Madhur, you can use a bus for communication.

    In case of using a Bus you have some options:

    Otto event Bus library (deprecated in favor of RxJava)

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

    Green Robot’s EventBus

    http://greenrobot.org/eventbus/

    NYBus (RxBus, implemented using RxJava. very similar to the EventBus)

    https://github.com/MindorksOpenSource/NYBus

    0 讨论(0)
  • 2020-11-22 03:22

    I am surprised that no one has given reference to Otto event Bus library

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

    I have been using this in my android apps and it works seamlessly.

    0 讨论(0)
  • 2020-11-22 03:23

    To follow up on @MrSnowflake answer with a code example. This is the XABBER now open source Application class. The Application class is centralising and coordinating Listeners and ManagerInterfaces and more. Managers of all sorts are dynamically loaded. Activity´s started in the Xabber will report in what type of Listener they are. And when a Service start it report in to the Application class as started. Now to send a message to an Activity all you have to do is make your Activity become a listener of what type you need. In the OnStart() OnPause() register/unreg. The Service can ask the Application class for just that listener it need to speak to and if it's there then the Activity is ready to receive.

    Going through the Application class you'll see there's a loot more going on then this.

    0 讨论(0)
提交回复
热议问题