Search code examples
androidbindingserviceandroid-activityparameter-passing

Android: pass parameter to Service from Activity


I'm binding to Service by this way:

Activity class:

ListenLocationService mService;
@Override
public void onCreate(Bundle savedInstanceState) {
        ...
        Intent intent = new Intent(this, ListenLocationService.class);
        intent.putExtra("From", "Main");
        bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
        ...
}

private ServiceConnection mConnection = new ServiceConnection() {

        public void onServiceConnected(ComponentName className,
                IBinder service) {
            LocalBinder binder = (LocalBinder) service;
            mService = binder.getService();         
        }

        public void onServiceDisconnected(ComponentName arg0) {
        }
    };

This is onBind method of my Service:

@Override
public IBinder onBind(Intent intent) {
    Bundle extras = intent.getExtras(); 
    if(extras == null)
        Log.d("Service","null");
    else
    {
        Log.d("Service","not null");
        String from = (String) extras.get("From");
        if(from.equalsIgnoreCase("Main"))
            StartListenLocation();
    }
    return mBinder;
}

So I have "null" in LogCat - bundle is null in spite of I made intent.putExtra before bindService

In general Service works fine. However I need to call StartListenLocation(); only from main activity of application (I decide to do this by sending a flag).

How can I send a data to service?Or maybe there's another way to check what activity launched onBind?


Solution

  • 1 Create a interface that declare all method signature that you want to call from a Activity:

    public interface ILocationService {
      public void StartListenLocation(Location location);
    }
    

    2 Make your binder implements ILocaionService and define the actual method body:

    public class MyBinder extends Binder implements ILocationService {
      ... ...
    
      public void StartListenLocation(Location location) {
        // implement your method properly
      }
    
      ... ...
    }
    

    3 In activity that bind to the service, reference your binder by the interface:

    ... ...
    
    ILocationService mService; // communication is handled via Binder not the actual service class.
    
    private ServiceConnection mConnection = new ServiceConnection() {
    
      public void onServiceConnected(ComponentName className, IBinder service) {
        mService = (ILocationService) service;     
      }
    
      ... ...
    };
    
    ... ...
    
    // At some point if you need call service method with parameter:
    Location location = new Location();
    mService.StartListenLocation(location);
    

    All communications (i.e. method call to your Service) should be handled and performed via the binder class initialize and return in ServiceConnection.onServiceConnected(), not the actual service class (binder.getService() is unnecessary). This is how bind service communication designed to work in the API.

    Note that bindService() is an asynchronous call. There will be a lag after you call bindService() and before ServiceConnection.onServiceConnected() callback get involved by system. So the best place to perform service method is immediately after mService get initialized in ServiceConnection.onServiceConnected() method.

    Hope this helps.