Digress: As one-to-one is explained orally by a colleague for consultation, it is not convenient for multiple parties to spread and inherit. Therefore, I would like to write this article to explain it.
1. Brief description of android service:
Android Service, also known as Java Service, is a Service implemented in the framework layer and written in Java.
Native Service, also known as System Service, is a Service implemented in the Runtime layer. It is written in C ++.
For the two services, both the peer service communication uses the binder, but one uses *. aidl and the other uses the IInterface.
The essence of writing serialized code is the same. This book first introduces the compilation of native service and two native services.
How to communicate:
2. native service features
A. Because the underlying core service is the closest part of the Android framework to Linux/Driver. To make full use of hardware
Core Service is an important channel for upper-layer Java applications to use Driver/HW Device features.
B. During the boot process, you can start the core services (such as the Chinese Character Input Method Service) so that many applications can share the service.
C. Because of sharing, the program size and unified interface changes can be effectively reduced.
3. How to implement a native service
Key points are as follows:
A. The core service is usually executed in an independent Process.
B. The IBinder interface must be provided so that other programs can bind and call across processes.
C. Because of sharing, multi-Thread security (Thread-safe) must be ensured ).
D. Define the object in the C ++ class. With the help of SM, pass the reference value of this object to the IServiceManager: addService () function and add it to the Binder Driver.
E. The application can remotely bind the core service with the assistance of SM. At this time, SM will return the IBinder interface to the application.
F. Applications can communicate with core services through the IBinder: transact () function.
The following example describes how to complete each step.
The module structure of a test example is described as follows:
ServiceTestA is a common process that provides two integer lasts and Division operations.
ServiceTestB is a common process that provides addition and subtraction operations for two integers.
TestService is a program for testing processes. It mainly verifies the interface functions of two service processes. The code can
Put it in any process for access and call
A. Compile the Service Process
ServiceTestA. h header file definition:
# Ifndef _ SERVICE_TEST_A __
# Define _ SERVICE_TEST_A __
# Include <utils/RefBase. h>
# Include <binder/IInterface. h>
# Include <binder/Parcel. h>
# Include <utils/threads. h>
Namespace android {
// Inherit the BBinder class to provide the IBinder Interface
Class serviceTestA: public BBinder
{
Public:
ServiceTestA ();
Virtual ~ ServiceTestA ();
Static int instantiate (); // creates a unique class instance.
Virtual status_t onTransact (uint32_t, const Parcel &, Parcel *, uint32_t );
Private:
// Protected by mLock multi-thread security
Mutable Mutex mLock;
};
}
# Endif/* _ SERVICE_TEST_A __*/
ServiceTestA. cpp implementation file:
# Include <cutils/log. h>
# Include <cutils/properties. h>
# Include <binder/IServiceManager. h>
# Include <binder/IPCThreadState. h>
# Include <serviceTestA/serviceTestA. h>
Namespace android {
Enum {
CALCULATE_MUL_NUM = 0,
CALCULATE_DIV_NUM,
};
Int serviceTestA: instantiate (){
LOGI ("serviceTestA instantiate ");
Int r = defaservicservicemanager ()-> addService (String16 ("service. TestA "),
New serviceTestA ());
LOGI ("serviceTestA r = % d/n", r );
Return r;
}
ServiceTestA: serviceTestA (){
LOGI ("serviceTestA created ");
}
ServiceTestA ::~ ServiceTestA (){
LOGI ("serviceTestA destroyed ");
}
Status_t serviceTestA: onTransact (uint32_t code, const Parcel & data, Parcel * reply, uint32_t flags ){
LOGI ("serviceTestA: onTransact code = % d", code );
Mutex: Autolock _ l (mLock );
Switch (code ){
Case CALCULATE_MUL_NUM :{
Int a = data. readInt32 ();
Int B = data. readInt32 ();
Int sum = a * B;
LOGI ("sum mul value = % d", sum );
Reply-> writeInt32 (sum );
Return NO_ERROR;
} Break;
Case CALCULATE_DIV_NUM :{
Int a = data. readInt32 ();
Int B = data. readInt32 ();
Int sum = a/B;
LOGI ("sum div value = % d", sum );
Reply-> writeInt32 (sum );
Return NO_ERROR;
} Break;
Default:
Return BBinder: onTransact (code, data, reply, flags );
}
Return 0;
}
}
Android. mk file:
LOCAL_PATH: = $ (call my-dir)
Include $ (CLEAR_VARS)
LOCAL_SRC_FILES: = serviceTestA. cpp
LOCAL_SHARED_LIBRARIES: = libutils libbinder
LOCAL_C_INCLUDES: = $ (TOP)/frameworks/base/include
LOCAL_MODULE: = libServiceTestA
LOCAL_PRELINK_MODULE: = false
Include $ (BUILD_SHARED_LIBRARY)
The libServiceTestA dynamic library is generated here, and the service program is upgraded by using the example.
Compile an independent process program:
Its purpose is to create a serviceTestA Class Object and store the object reference in the Binder Driver.
# Include <sys/types. h>
# Include <unistd. h>
# Include <cutils/log. h>
# Include <binder/IServiceManager. h>
# Include <binder/IPCThreadState. h>
# Include <serviceTestA/serviceTestA. h>
Using namespace android;
Int main (int argc, char * argv []) {
Sp <ProcessState> proc (ProcessState: self ());
Sp <IServiceManager> sm = defaultServiceManager ();
LOGI ("ServiceManager: % p", sm. get ());
ServiceTestA: instantiate (); // This is the key ....
ProcessState: self ()-> startThreadPool ();
IPCThreadState: self ()-> joinThreadPool ();
Return 0;
}
Android. mk file:
LOCAL_PATH: = $ (call my-dir)
Include $ (CLEAR_VARS)
LOCAL_SRC_FILES: = main. cpp
LOCAL_SHARED_LIBRARIES: = libutils libServiceTestA
LOCAL_MODULE: = serviceTestA
Include $ (BUILD_EXECUTABLE)
Www.2cto.com
The most important thing here is to call serviceTestA: instantiate ();
First, execute new serviceTestA () to create a serviceTestA class object;
Call the defaservicservicemanager () function to obtain the IServiceManager interface of SM;
Call IServiceManager: addService () to save the object reference to the Binder Driver and
Register and manage ServiceManager so that other processes can find the corresponding service process through ServiceManager: getService
The above code is the same as that of serviceTestB service process.
B. Test the Service Process
TestService. cpp:
# Include <cutils/log. h>
# Include <cutils/properties. h>
# Include <binder/IServiceManager. h>
# Include <binder/IPCThreadState. h>
# Include <serviceTestA/serviceTestA. h>
# Include <serviceTestB/serviceTestB. h>
Using namespace android;
Enum {
CALCULATE_ADD_NUM = 0,
CALCULATE_SUB_NUM,
};
Enum {
CALCULATE_MUL_NUM = 0,
CALCULATE_DIV_NUM,
};
Int main (int argc, char * argv []) {
Sp <IBinder> TestAbinder;
Sp <IBinder> TestBbinder;
Parcel data, reply;
Int sum = 0;
LOGI ("testService main is call ...");
Sp <IServiceManager> sm = defaultServiceManager ();
While (1 ){
TestAbinder = sm-> getService (String16 ("service. TestA "));
LOGE ("TestA: getAddService % p/n", sm. get ());
If (TestAbinder = 0 ){
LOGE ("TestAService not published, waiting ...");
Usleep (1000000 );
Continue;
}
Else {
LOGI ("TestA: getAddService success ...");
Break;
}
}
While (1 ){
TestBbinder = sm-> getService (String16 ("service. TestB "));
LOGE ("TestB: getAddService % p/n", sm. get ());
If (TestBbinder = 0 ){
LOGE ("TestBService not published, waiting ...");
Usleep (1000000 );
Continue;
}
Else {
LOGI ("TestB: getAddService success ...");
Break;
}
}
// Test the functions of the two services
Data. writeInt32 (1000 );
Data. writeInt32 (200 );
LOGI ("BpAddService: create remote ()-> transact ()/n ");
TestAbinder-> transact (CALCULATE_MUL_NUM, data, & reply );
Sum = reply. readInt32 ();
LOGI ("CALCULATE_ADD_NUM value = % d", sum );
Data. writeInt32 (1000 );
Data. writeInt32 (200 );
LOGI ("BpAddService: create remote ()-> transact ()/n ");
TestAbinder-> transact (CALCULATE_DIV_NUM, data, & reply );
Sum = reply. readInt32 ();
LOGI ("CALCULATE_SUB_NUM value = % d", sum );
Data. writeInt32 (1000 );
Data. writeInt32 (200 );
LOGI ("BpAddService: create remote ()-> transact ()/n ");
TestBbinder-> transact (CALCULATE_ADD_NUM, data, & reply );
Sum = reply. readInt32 ();
LOGI ("CALCULATE_MUL_NUM value = % d", sum );
Data. writeInt32 (1000 );
Data. writeInt32 (200 );
LOGI ("BpAddService: create remote ()-> transact ()/n ");
TestBbinder-> transact (CALCULATE_SUB_NUM, data, & reply );
Sum = reply. readInt32 ();
LOGI ("CALCULATE_DIV_NUM value = % d", sum );
Return 0;
}
The most important thing here is to get the default sm through defaservicservicemanager, and then get the sp <IBinder> object through getService to operate the interface functions of the corresponding service process. The whole process is quite clear.
Finally, print the test result:
#./TestService
./TestService
# Logcat
Logcat
--------- Beginning of/dev/log/main
I/(1379): testService main is call...
E // (1379): TestA: getAddService 0xa680/n
I/(1379): TestA: getAddService success...
E/(1379): TestB: getAddService 0xa680/n
I/(1379): TestB: getAddService success...
I/(1379): BpAddService: create remote ()-> transact ()/n
I/(1371): serviceTestA: onTransact code = 0
I/(1371): sum mul value = 200000
I/(1379): CALCULATE_MUL_NUM value = 200000
I/(1379): BpAddService: create remote ()-> transact ()/n
I/(1371): serviceTestA: onTransact code = 1
I/(1371): sum div value = 5
I/(1379): CALCULATE_DIV_NUM value = 5
I/(1379): BpAddService: create remote ()-> transact ()/n
I/(1374): serviceTestB: onTransact code = 0
I/(1374): sum add value = 1200
I/(1379): CALCULATE_ADD_NUM value = 1200
I/(1379): BpAddService: create remote ()-> transact ()/n
I/(1374): serviceTestB: onTransact code = 1
I/(1374): sum sub value = 800
I/(1379): CALCULATE_SUB_NUM value = 800
The result indicates that it is completely correct.
From andyhuabing's column