Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

IntentService responding to dead ResultReceiver

An activity instantiates a ResultReceiver and overrides onReceiveResult. The activity then sends an Intent to an IntentService and includes the ResultReceiver as an extra. Once the IntentService is finished processing it sends a message back to the ResultReceiver and processes it in onReceiveResult.

The issue is if the user navigates away from the Activity then the result is still sent back to the ResultReceiver which causes all types of issues. Is there not a way to stop this behavior? I've tried stopping the IntentService in the activity's onDestroy() but the result is still sent back.

Here is a sample Activity

public class Foo extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        Intent i = new Intent(this, SampleIntentService.class);
        i.putExtra("receiver", mReceiver);
        startService(i);
    }

    @Override
    public void onDestroy() {
        stopService(new Intent(this, SampleIntentService.class));
        mReceiver = null;
        super.onDestroy();
    }

    ResultReceiver mReceiver = new ResultReceiver(new Handler()) {
        @Override
        protected void onReceiveResult(int resultCode, Bundle resultData) {
            // Handle response from IntentService here
        }
    };
}

Here is a sample IntentService

public class SampleIntentService extends IntentService {
    public SampleIntentService() {
        super(SampleIntentService.class.getName());
    }

    @Override
    protected void onHandleIntent(Intent intent) {
    ResultReceiver rec = intent.getParcelableExtra("receiver");
        if (rec != null) {
            rec.send(200, null);
        }
    }
}
like image 670
Daniel Ochoa Avatar asked Sep 21 '13 04:09

Daniel Ochoa


1 Answers

I solved this issue by creating a custom ResultReceiver as follows.

public class SampleResultReceiver extends ResultReceiver {
    private Receiver mReceiver;

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

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

    public interface Receiver {
        void onReceiveResult(int resultCode, Bundle resultData);
    }

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

Then in my Activity I do the following:

public class Foo extends Activity implements Receiver {
    private SampleResultReceiver mReceiver;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mReceiver = new SampleResultReceiver(new Handler());
        mReceiver.setReceiver(this);

        Intent i = new Intent(this, SampleIntentService.class);
        i.putExtra("receiver", mReceiver);
        startService(i);
    }

    @Override
    public void onDestroy() {
        if (mReceiver != null) {
            mReceiver.setReceiver(null);
        }
        super.onDestroy();
    }

    @Override
    protected void onReceiveResult(int resultCode, Bundle resultData) {
        // Handle response from IntentService here
    }
}

This will cause any messages sent to your custom ResultReceiver to end up nowhere after the Activity has been destroyed :)

like image 94
Daniel Ochoa Avatar answered Oct 08 '22 08:10

Daniel Ochoa