shannon
shannon

Reputation: 589

How to pass a handler from activity to service

How to pass handler from an activity to service? I am trying to update the activity UI on the state of Bluetooth connection by using Handler as shown below from service class.

mHandler.obtainMessage(MenuActivity.MESSAGE_STATE_CHANGE, state, -1).sendToTarget();

In the activity, I implemented this:

   public void handleMessage(Message msg) {
            switch (msg.what) {
            case MESSAGE_STATE_CHANGE:
                 if (true)
                     Log.i(TAG, "MESSAGE_STATE_CHANGE: " + msg.arg1);
                 switch(msg.arg1){
                    case BluetoothService.STATE_CONNECTED:
                        showToast("Connected to " + mConnectedDeviceName, Toast.LENGTH_SHORT);
                        break;

I tried to use a constructor to pass the handler from the activity to service like this:

public BluetoothService(Handler handler, BluetoothAdapter mBluetoothAdapter) {
        mAdapter = mBluetoothAdapter;
        mState = STATE_NONE;
        mHandler = handler;
}

But there was an error which shows Unable to instantiate service and found that the service needs to have a public no-args constructor. But after removing the constructor, the handler did not get passed into the service.

How to solve this problem?

Upvotes: 5

Views: 5936

Answers (1)

Libin
Libin

Reputation: 17095

You have to bind to the service from activity and establish a ServiceConnection and then get the instance of service and set your handler.

Here is the activity and service class which i use for one of my media player application.....

public class MainActivity extends Activity
{
private CustomService mService = null;

private boolean mIsBound;

@Override
protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    startService(new Intent(this.getBaseContext(), CustomService.class));
    doBindService();
}


private ServiceConnection mConnection = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName componentName, IBinder iBinder)
    {
        mService = ((CustomService.LocalBinder)iBinder).getInstance();
        mService.setHandler(yourHandler);
    }

    @Override
    public void onServiceDisconnected(ComponentName componentName)
    {
        mService = null;
    }
};

private void doBindService()
{
    // Establish a connection with the service.  We use an explicit
    // class name because we want a specific service implementation that
    // we know will be running in our own process (and thus won't be
    // supporting component replacement by other applications).
    bindService(new Intent(this,
            CustomService.class), mConnection, Context.BIND_AUTO_CREATE);
    mIsBound = true;
}

private void doUnbindService()
{
    if (mIsBound)
    {
        // Detach our existing connection.
        unbindService(mConnection);
        mIsBound = false;
    }
}

@Override
protected void onDestroy()
{
    super.onDestroy();
    doUnbindService();
}

}

CustomService Code ....

public class CustomService extends Service
{
private final IBinder mIBinder = new LocalBinder();

private Handler mHandler = null;

@Override
public void onCreate()
{
    super.onCreate();
}

@Override
public int onStartCommand(Intent intent, int flag, int startId)
{
    return START_STICKY;
}

@Override
public void onDestroy()
{
    if(mHandler != null)
    {
        mHandler = null;
    }
}

@Override
public IBinder onBind(Intent intent)
{
    return mIBinder;
}

public class LocalBinder extends Binder
{
    public CustomService getInstance()
    {
        return CustomService.this;
    }
}

public void setHandler(Handler handler)
{ 
   mHandler = handler;
}

}

Upvotes: 9

Related Questions