How to realize IPC
Bound services
A bound service is the server in a client-server interface. It allows components (such as activities) to bind to the service, send requests, receive responses, and perform interprocess communication (IPC).
How to create Bound Service
When creating a service that provides binding, you must provide an IBinder
that provides the programming interface that clients can use to interact with the service.
How to define an IBinder
Android Interface Definition Language (AIDL) decomposes objects into primitives that the operating system can understand and marshals them across processes to perform IPC.
How to create a bounded service using AIDL
Create the .aidl file
This file defines the programming interface with method signatures.
Implement the interface
The Android SDK tools generate an interface in the Java programming language, based on your
.aidl
file. This interface has an inner abstract class namedStub
that extendsBinder
and implements methods from your AIDL interface. You must extend theStub
class and implement the methods.Expose the interface to clients
Implement a
Service
and overrideonBind()
to return your implementation of theStub
class.
General Steps
- create aidl file
- create service
- implement IBinder for service
- instantiate service in client (activity)
AccountManager
https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/accounts
Theory | Example: IPC between service and accountManager |
---|---|
Define Bound service | MyAccountTypeService implement onBind |
provide IBinder | return MyAccountAuthenticator.getIBinder(); |
use AIDL define IBinder | |
create the .aidl file | IAccountAuthenticator.aidl IAccountAuthenticatorResponse.aidl |
Implement the interface | private class Transport extends IAccountAuthenticator.Stub line:152 |
Expose the interface to clients | return MyAccountAuthenticator.getIBinder(); |
Work flow
AccountManager : getAuthToken() -> new AmsTask() ->
mService.getAuthToken()
mService is IAccountManager created by system
the real invoke is AccountManagerService (extends IAccountManager.Stub)
AccountManagerService : getAuthToken() -> new Session() -> bind to mAuthenticator related service -> mAuthenticator.getAuthToken()
*mAuthenticatoir is IAccountAuthenticator assaigned In Session(extend IAccountAuthenticatorResponse.Stub and implement ServiceConnection): onServiceConnected() method
`mAuthenticator = IAccountAuthenticator.Stub.asInterface(service);`
AbstractAccountAuthenticator : getAuthToken() -> AbstractAccountAuthenticator.this.getAuthToken()
here invoke our proper method
AccountAuthenticator : intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, response)
pass AccountAuthenticatorResponse by intent
return bundle
AccountAuthenticatorResponse implements Parcelable contains IAccountAuthenticatorResponse
Session : onResult() -> result contain KEY_INTENT -> response.onResult()
response is IAccountManagerResponse.Stub declare in AccountManager
Response : onResult() -> mActivity.startActivity(intent)
ShareMyAccountActivity : getIntent() -> AccountAuthenticatorResponse.onResult() -> mAccountAuthenticatorResponse.onResult()
mAccountAuthenticatorResponse is IAccountAuthenticatorResponse is assaigned in AccountManagerService.newRequestAccountAccessIntent()
How AccountAuthenticatorResponse work ?
- define a IAccountAuthenticatorResponse aidl file
1 | /** |
- implement this interface
1 | private abstract class Session extends IAccountAuthenticatorResponse.Stub |
- accountManager -> AmTask -> AccountManagerService -> Session( instantiate IAccountAuthenticatorResponse ) -> bind to authenticator service -> call mAuthenticator.getAuthToken(pass IAccountAuthenticatorResponse)
1 |
|
- define an object to get passed IAccountAuthenticatorResponse and use callback send back result
1 | /** |
- AbstactAccountAuthenticator get this response and instantiate it again pass to our proper authenticator
1 | public abstract class AbstractAccountAuthenticator { |
- MyAccountAuthenticator pass this response to ShareMyAccountActivity by intent
1 | class MyAccountAuthenticator extends AbstractAccountAuthenticator |
- ShareMyAccountActivity after user confirm give back result
1 | public class ShareMyAccountActivityInteractorImpl |
Conclusion
IAccountAuthenticatorResponse is used in two parts.
- As Session : implement and instantiate and bind in Service, work like Binder for Bound Service
once service pass it to authenticator by parameter, it will be encapsulated by AccountAuthenticatorResponse
- As AccountAuthenticatorResponse : it can be passed to activity by intent. If its methodes are called, the IAccountAuthenticatorResponse’s callback fonctions also works.
If we take example by its second usage, even without service, we can pass our custom callback to activity.
reference: https://developer.android.com/guide/components/aidl#PassingObjects