About Binder Caching

There was a debate earlier in the week on the android-developers Google Group regarding the behavior of onBind() in a service. While the original question was whether two clients can both be bound to a remote service (answer: yes), a sidebar developed regarding onBind() and caching.

Something I had not realized, until Kostya Vasilyev pointed it out, is that Service caches the object returned by onBind() for a given Intent. In other words, the second and subsequent times that a running Service is bound to, onBind() will not be called, if the Intent used each time is equivalent. Here, “equivalent” means that the action, data (Uri), categories, and MIME type are identical.

If, however, you use different Intent structures, such as different action strings, that will result in onBind() being called multiple times, one for each distinct Intent.

This is important for remote service binding. The contract between your Service and third-party developers is not really the Service itself, but a specific Binder structure, described via AIDL. Ideally, you should use an <intent-filter> with a custom action string as your public stable name for that Binder/AIDL structure, so you can refactor class implementations without breaking the effective public API. However, if you decide that you need a new Binder (e.g., add new methods), you can use a different action string, and have onBind() return the right Binder based on the received action. This way, you can support both old and new versions of your Binder/AIDL API simultaneously.

If onBind() caching was oblivious to the changes in Intent, then this would not work — the first onBind() call would return whatever Binder it needed, and everybody else would wind up with that same Binder, like it or not. However, I can confirm that onBind() caching does respect the Intent contents, and so the multiple-action-string pattern should work just fine.