4

I have an Activity called MainActivity that starts a Service called MainService. It is also binds the Service, so MainActivity can access methods and public variables within MainService. Is it possible to do it the other way round, i.e. the Service is able to access the Activity's methods?

I wish to implement it this way because I have a variable in MainActivity that is set upon onResume(), and on first startup the service has not yet started by the time onResume() runs, so at that point in time the service is still null.

user1118764
  • 9,255
  • 18
  • 61
  • 113

2 Answers2

1

This answer assumes that the Service in question runs in a different process:

Yes, it is possible. The general idea is that not only your Activity binds the remote Service through some AIDL defined interface, but it also implements additional AIDL interface which the Service is aware of, and sets itself as a callback target of the remote Service.

You'll have to have 2 AIDL files: the first one describes the interface of the Service, and the second one describes the interface of the Activity.

The implementation of such a scheme is very similar to "remote Service callbacks" described in this answer, though "callback" method would no longer be void, but return the value you're interested in.

Design considerations:

The above scheme will allow you to get values from Activity, but I don't think you should take this path. From the description of your use case, it looks that you only want to pass some value to the Service when Activity gets resumed. Since your Service is bound anyway, you can simply add a method setSomeValue(int value) to its AIDL definition and call this method from onServiceConnected() callback.

Community
  • 1
  • 1
Vasiliy
  • 16,221
  • 11
  • 71
  • 127
  • 1
    AIDL files are necessary only if you want to share services between different applications. – piotrpo Aug 12 '16 at 09:56
  • @piotrpo, good point! I just assumed that IPC involved, but now I see that it is not stated in the question in which process the Service lives. – Vasiliy Aug 12 '16 at 09:57
0

Yes it's possible. You have to prepare method in your service to return back your activity just after service is bound:

public void bindActivity(MyActivity activity){...}

Then after service is bound to activity just call this method with MyActivity.this as parameter.

However...

You probably should not do it. Much more clear solution is using LocalBroadcastManager to pass events and data or use some more efficient solutions like Otto to do this same, but still - without direct access to one component's fields / methods from another.

piotrpo
  • 12,398
  • 7
  • 42
  • 58
  • It is not a good idea for `Service` to depend on `Activity`. It would be much cleaner if the parameter of this method would be some interface, and `MainActivity` would simply implement it. – Vasiliy Aug 12 '16 at 10:12
  • The only really "clean" solution in my opinion is some message based one. Of course introducing some interface is good idea according to OOD rules, but still - the question is not about design, but rather implementation. – piotrpo Aug 12 '16 at 10:18
  • No need for messaging - the `Service` is bound, therefore just a simple function call suffices. The interface is part of implementation, otherwise the implementation is not clean ;) – Vasiliy Aug 12 '16 at 10:24