borges
borges

Reputation: 3687

How to correctly send a ResultReceiver subclass to a Service?

I am trying to bind to a custom service with no success.

My custom service

public class CustomService extends Service {
    private CustomReceiver mReceiver;
    private final CustomBinder mBinder = new CustomBinder();

    public class CustomBinder extends Binder implements ICustomService {
        // Implementation of the interface
    }

    public interface ICustomService {
        // Public interface to comunicate to the service
    }

@Override
public IBinder onBind(Intent intent) {
    Log.d("customservice", "Service bound.");
    mReceiver = intent.getParcelableExtra("receiver"); // ERROR HERE!
    return mBinder;
}

// Other methods

My custom receiver

public class CustomReceiver extends ResultReceiver {    
    public interface IReceiver {
        public void onReceiveResult(int resultCode, Bundle resultData);
    }

    private IReceiver mReceiver;

    public CustomReceiver(Handler handler) {
        super(handler);
    }

    public void setReceiver(IReceiver receiver) {
        mReceiver = receiver;
    }

    @Override
    protected void onReceiveResult(int resultCode, Bundle resultData) {
        if (mReceiver != null) {
            mReceiver.onReceiveResult(resultCode, resultData);
        }
    }
}

My activity

public class MainActivity extends Activity implements CustomReceiver.IReceiver {
    IRegressiveService mService;
    CustomReceiver mReceiver;
    boolean mBound = false;

    private ServiceConnection mConnection = new ServiceConnection() {
        public void onServiceConnected(ComponentName name, IBinder service) {
            mService = (ICustomService) service;
            mBound = true;
        }

        public void onServiceDisconnected(ComponentName name) {
            mBound = false;
        }
    };

    @Override
    public void onCreate(Bundle savedInstanceState) {
        //...
        mReceiver = new CustomReceiver(new Handler());
        mReceiver.setReceiver(this);

        Intent bindServiceIntent = new Intent(this, CustomService.class);
        bindServiceIntent.putExtra("receiver", mReceiver);
        bindService(bindServiceIntent, mConnection, Context.BIND_AUTO_CREATE);
    }

    public void onReceiveResult(int resultCode, Bundle resultData) {
        //...
    }

    //...
}

Stacktrace (incomplete)

04-29 20:23:55.851: E/AndroidRuntime(690): FATAL EXCEPTION: main
04-29 20:23:55.851: E/AndroidRuntime(690): java.lang.RuntimeException: Unable to bind to service [package].CustomService@44f38cd8 with Intent { cmp=[package].CustomService (has extras) }: java.lang.ClassCastException: android.os.ResultReceiver
04-29 20:23:55.851: E/AndroidRuntime(690): at android.app.ActivityThread.handleBindService(ActivityThread.java:2996)
[...]
04-29 20:23:55.851: E/AndroidRuntime(690): Caused by: java.lang.ClassCastException: android.os.ResultReceiver
04-29 20:23:55.851: E/AndroidRuntime(690): at [package].CustomService.onBind(CustomService.java:37)
04-29 20:23:55.851: E/AndroidRuntime(690): at android.app.ActivityThread.handleBindService(ActivityThread.java:2983)
[...]

In short

In the Activity, I pass to the Service a instance of CustomReceiver (a ResultReceiver subclass) with the "receiver" key. But when I try to recover this object, in the Service, ClassCastException is raised. Why? How can I fix this?

I am targeting API level 8.

And I can not find this behavior in any of other SO questions.

Upvotes: 3

Views: 4636

Answers (3)

Will
Will

Reputation: 11

I was having the exact same issue with the ClassCastException and it did not make any sense to me. I saw the answer here about setting the mReceiver to just use a ResultReceiver instead of the CustomReceiver in the Service. I did that and still got the same error, but I noticed that my import Statements were not the same.

In my MainActivity I imported the statement:

import android.support.v4.os.ResultReceiver;

However in my service I had imported the statement:

import android.os.ResultReceiver;

I made sure in my service and my MainActivity I used following:

import android.support.v4.os.ResultReceiver;

It now works properly! Hope this helps someone!

I'm also a few years late..

Upvotes: 1

Squonk
Squonk

Reputation: 48871

I've just checked my code. Try declaring mReceiver in your Service as a base ResultReceiver as follows...

public class CustomService extends Service {
    private ResultReceiver mReceiver;
    ...
}

This is what I do and I don't get a ClassCastException in my Service when getting the receiver from the Intent (mine is also a custom ResultReceiver).

Upvotes: 2

Femi
Femi

Reputation: 64700

A BroadcastReceiver is (by default) not Parcelable. So you'll expect to get a ClassCastException. If you need to pass a specific instance add a setter method to your Service and then call that method from your ServiceConnection implementation with the object.

Upvotes: -1

Related Questions