Is there a need to have one ServiceConnection per each Service bind?
Asked Answered
W

2

6

I have several Android Services that I want to bind to in my Activity, so I can monitor several actions from the user.

To be able to bind every Service, and I will have several, do I need several private ServiceConnections in my activity like the following?

/** Defines callbacks for service binding, passed to bindService() */
private ServiceConnection mConnection = new ServiceConnection() {

    @Override
    public void onServiceConnected(ComponentName className,
            IBinder service) {
        // We've bound to LocalService, cast the IBinder and get LocalService instance
        GPSLocalBinder gpsBinder = (GPSLocalBinder) service;
        PhotoLocalBinder photoBinder = (PhotoLocalBinder) service;
        gpsService = gpsBinder.getService();
        photoService = photoBinder.getService();
        mGpsBound = true;
        mPhotoBound = true;
    }

    @Override
    public void onServiceDisconnected(ComponentName arg0) {
        mGpsBound = false;
        mPhotoBound = false;
    }
};

Or do I need a manager class between my Activity and the Services that provides better usage and understanding of the bounded Services?

Washtub answered 7/3, 2014 at 17:20 Comment(0)
A
1

Is there a need to have one serviceConnection for each android service?

I assume you're asking if you can reuse the same serviceConnection for multiple services. There's no need to have one for each service connection, but this is probably the best approach. I see in your code this

        GPSLocalBinder gpsBinder = (GPSLocalBinder) service;
        PhotoLocalBinder photoBinder = (PhotoLocalBinder) service;
        gpsService = gpsBinder.getService();
        photoService = photoBinder.getService();

This is very confusing... this seems like a service can be cast into two different services!!

You'll realize that the onServiceConnected callback is where most of the magic happens, where you (the Activity) finally can get a pointer to your Service and start calling methods and interact with your service. If you want to reuse the same serviceConnection for different services you'd need to find out which custom subclass the IBinder object belongs to and then cast appropriately. Ufff, too much trouble. I would recommend having one serviceConnection per service.

Or do i need a manager class between my activity and the services that provides better usage and understanding of the bounded services?

For both this and your first question, you can do whatever you want. There's no approach better than the other (IMHO) and the best one is the one you understand better and makes you feel more comfortable.

Avruch answered 7/3, 2014 at 17:39 Comment(1)
Thx for your enlightment on this subject.Washtub
T
0

A single ServiceConnection instance can be used for binding to multiple Services.

In ServiceConnection.onServiceConnected(), you'd have to check which service was bound (using className.getClassName() or className.getPackageName()) and put it in the appropriate field/variable, etc.

I used this thread as a reference, though I modified it to match my needs.

private static final int SERVICE_1_INDEX = 0;
private static final int SERVICE_2_INDEX = 1;

/** Array of the subclasses of {@link BaseService}s which have been bound */
private BaseService[] mServices;
/** ServiceConnection which handles the binding/unbinding of the services */
private MyServiceConnection mServiceConnection;

@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    mServiceConnection = new MyServiceConnection();
}

@Override
public void onResume() {
    super.onResume();
    bindServices();
}

@Override
public void onPause() {
    super.onPause();
    unbindServices();
}

private void bindServices() {
    Intent service1Intent = new Intent(getActivity().getApplicationContext(), MyService1.class);
    Intent service2Intent = new Intent(getActivity().getApplicationContext(), MyService2.class);

    getContext().bindService(service1Intent, mServiceConnection, Context.BIND_AUTO_CREATE);
    getContext().bindService(service2Intent, mServiceConnection, Context.BIND_AUTO_CREATE);
}

private void unbindServices() {
    if (mServiceConnection != null) {
        getContext().unbindService(mServiceConnection);
    }
}

private class MyServiceConnection implements ServiceConnection {
    public void onServiceConnected(ComponentName className, IBinder boundService ) {
        Log.d("className(bound)", className.getClassName());
        Log.d("className(Service1)", MyService1.class.getName());
        Log.d("className(Service2)", MyService2.class.getName());
        BaseService.LocalBinder binder = (BaseService.LocalBinder) boundService;
        if (className.getClassName().equals(MyService1.class.getName())) {
            mServices[SERVICE_1_INDEX] = binder.getService();
            // call method on your service like:
            // binder.getService().someMethod();
            // (you may need to cast to your actual Service)
        }
        else {
            mBaseServices[SERVICE_2_INDEX] = binder.getService();
            // call method on the service like in if-block
        }
    }

    public void onServiceDisconnected(ComponentName className) {
        if (className.getClassName().equals(MyService1.class.getName())) {
            mBaseServices[SERVICE_1_INDEX] = null;
        }
        else {
            mBaseServices[SERVICE_2_INDEX] = null;
        }
    }
}
Trigonal answered 31/10, 2016 at 11:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.