How does the Android ResultReceiver callback work if it is passed through the Bundle as Parcelable?

I passed ResultReceiver from my activity to my service.

An example operation code to pass the ResultReceiver to my service so that the service can call back for Activity:

ResultReceiver receiver = new ResultReceiver(new Handler()) { protected void onReceiveResult(int resultCode, Bundle resultData) { //process results } } Intent instructionServiceIntent = new Intent(context, InstructionService.class); instructionServiceIntent.putExtra("receiver", receiver); context.startService(instructionServiceIntent); 

Instruction Example service code:

 protected void onHandleIntent(Intent intent) { Bundle parameters = intent.getExtras(); ResultReceiver resultReceiver = parameters.getParcelable("receiver"); resultReceiver.send(METHOD_STATUS_RUNNING, Bundle.EMPTY); } 

Now this works fine, when I call the resultReceiver.send method in my service, the corresponding onReceiveResult method in action is executed.

My question is: how does it work? As far as I understand, ResultReceiver is transferred from this operation to the service as Parcelable, which means its "copy" of this object, and not a link to the original ResultReceiver object that was created in Activity. Thus, how does calling the send method on a copy of the ResultReceiver in the service class make it so that the original ResultReceiver object in action executes it using theReceiveResult method?

+6
source share
1 answer

ResultReciver implements Parcelable , so it can be passed in intent.

For a startup service, it’s easier to just load the intent used to start the service with the data, just like the intent sent to the action, and then the intent data in onStartComand ();

If you want to send messages back to the service, you must bind to the startboundservice service, and in the service, return a handler in onBind () for this operation.

This is where the magic of ResultReceiver works. This is just a message with a pre-processed handler, so it can be serialized and passed back.

If you just want to get an answer from some class of fragments that you create on the fly, or something is out of the norm, actually serialize the callback, you can pass a message filled with a handler that will process the message.

Below I create a handler, then create a message with a handler. Then I start a snippet that does something obscure and finally returns a message. Thus, an ineffective message is just a copy, but in fact it is a callback that is passed in a bundle.

This is new code, so I don’t know how stable it is ...

 public void get_UserEmail(final MyGooglePlayCallback userEmailCallback) { //handle message gets called when the fragment calls msg.sendToTarget() // class JX implements Handler.Callback { @Override public boolean handleMessage(Message msg) { Bundle b = msg.getData(); String s = ""; if (b != null) { s = b.getString("email"); } msg.recycle(); userEmailCallback.onComplete(s); return true; } } JX jx = new JX(); Handler h = new Handler(jx); final Message msg = Message.obtain(h); MyGooglePlayCallback cb; // start the account picker to get the email String[] accountTypes = new String[]{"com.google"}; Intent intentx = AccountPicker.newChooseAccountIntent(null, null, accountTypes, false, null, null, null, null); MyFragmentActivityForResult2 f = MyFragmentActivityForResult2.newInstance( intentx, REQUEST_CODE_PICK_ACCOUNT, msg); FragmentTransaction fragmentTransaction = fragManager .beginTransaction(); fragmentTransaction.add(f, "xx" + REQUEST_CODE_PICK_ACCOUNT); fragmentTransaction.commit(); } public static class MyFragmentActivityForResult2 extends Fragment { private Message msg; private int requestCode; private Intent intent; static MyFragmentActivityForResult2 newInstance(Intent intent, int requestCode, Message message) { MyFragmentActivityForResult2 f = new MyFragmentActivityForResult2(); Bundle args = new Bundle(); args.putInt("requestCode", requestCode); args.putParcelable("message", message); args.putParcelable("intent", intent); f.setArguments(args); return f; } MyFragmentActivityForResult2() { } @Override public void onAttach(Activity activity) { super.onAttach(activity); Bundle b = this.getArguments(); requestCode = b.getInt("requestCode"); msg = b.getParcelable("message"); intent = b.getParcelable("intent"); startActivityForResult(intent, requestCode); } @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == this.requestCode) { String mEmail = ""; if (resultCode == Activity.RESULT_OK) { mEmail = data .getStringExtra(AccountManager.KEY_ACCOUNT_NAME); } Bundle b = new Bundle(); b.putString("email", mEmail); msg.setData(b); msg.arg1 = requestCode; msg.arg2 = resultCode; msg.sendToTarget(); } fragManager.beginTransaction().remove(this).commit(); } } 
+2
source

Source: https://habr.com/ru/post/969733/


All Articles