Address: http://blog.csdn.net/andy_android/article/details/7301814
1. Introduction to Android Service
Android services include Android services and native services.
Android service, also known as Java service, is a server implemented in the framework layer. Android service is written in Java.
Native service, also known as system service, is a server implemented in the runtime layer.
Taking mediaplayer as an example, we can get the relationship between the two services:
The service to be discussed next is the native service, which is different from the Service (Android. App. Service) discussed in application design.
2. Why do we need to write the underlying core services?
(1) because the underlying core service is the closest part of the android framework to Linux/driver. To make full use of the differentiated features of hardware devices, core services are an important channel for upper-layer Java applications to use driver/HW device features.
(2) core services (such as the Chinese Character Input Method) can be started during the boot process, so that many applications can share the service.
(3) Because of sharing, the Java application size can be effectively reduced ).
3. How to implement a core service?
Key points are as follows:
(1) core services are usually executed in an independent process.
(2) The ibinder interface must be provided so that the application can bind and call across processes.
(3) Because of sharing, it is necessary to ensure multi-line secure (thread-safe ).
(4) The object is defined in the C ++ class. With the assistance of SM, the reference value of this object is passed to the iservicemanager: addservice () function and added to the binder driver.
(5) The application can be remotely bound to the core service with the assistance of Sm. At this time, SM will return the ibinder interface to the application.
(6) applications can communicate with core services through the ibinder: transact () function.
Iv. server implementation practices
The following is a small example to illustrate how to implement a server. This instance function is a simple integer addition (ADD) operation. we name it addservice.
Step-1: Write the addservice category in C ++. The complete program code is:
Addservice. h file:
# Ifndef android_guilh_add_service_h
# Define android_guilh_add_service_h
# Include <utils. h>
# Include <utils/refbase. h>
# Include <utils/iinterface. h>
# Include <utils/parcel. h>
Namespace android
{
Class addservice: Public bbinder
{
Mutable mutex mlock;
Int32_t mnextconnid;
Public:
Static int instantiate ();
Addservice ();
Virtual ~ Addservice ();
Virtual status_t ontransact (uint32_t, const parcel &, parcel *, uint32_t );
};
}
# Endif
Addservice. cpp file:
# Include "addservice. H"
# Include <utils/iservicemanager. h>
# Include <utils/ipcthreadstate. h>
Namespace Android {
Static struct sigaction oldact;
Static pthread_key_t sigbuskey;
Int addservice: instantiate (){
LogE ("addservice instantiate ");
Int r = defaservicservicemanager ()-> addservice (
String16 ("guilh. Add"), new addservice ());
LogE ("addservice r = % d/N", R );
Return R;
}
Addservice: addservice ()
{Logv ("addservice created ");
Mnextconnid = 1;
Pthread_key_create (& sigbuskey, null );
}
Addservice ::~ Addservice ()
{Pthread_key_delete (sigbuskey );
Logv ("addservice destroyed ");
}
Status_t addservice: ontransact (
Uint32_t code, const parcel & Data, parcel * reply, uint32_t flags ){
Switch (CODE ){
Case 0 :{
Pid_t pid = data. readint32 ();
Int num = data. readint32 ();
Num = num+ 1000;
Reply-> writeint32 (Num );
Return no_error;
} Break;
Default:
Return bbinder: ontransact (Code, Data, reply, flags );
}
}
};
Android. mk file:
Local_path: = $ (call my-DIR)
Include $ (clear_vars)
Local_src_files: = addservice. cpp
# Local_c_includes: = $ (jni_h_include)
Local_shared_libraries: = libutils
Local_module: = libaddservice
Local_prelink_module: = false
Include $ (build_shared_library)
Step-2: Write an independently executed addserver in C ++. CPP program. Its purpose is to create an addservice Class Object and store the object reference in the binder driver. The content is:
Addserver. cpp file:
# Include <sys/types. h>
# Include <unistd. h>
# Include <GRP. h>
# Include <utils/ipcthreadstate. h>
# Include <utils/processstate. h>
# Include <utils/iservicemanager. h>
# Include <utils/log. h>
# Include <private/android_filesystem_config.h>
# Include "../libaddservice/addservice. H"
Using namespace android;
Int main (INT argc, char ** argv)
{
Sp <processstate> proc (processstate: Self ());
Sp <iservicemanager> Sm = defaultservicemanager ();
Logi ("servicemanager: % P", Sm. Get ());
Addservice: instantiate ();
Processstate: Self ()-> startthreadpool ();
Ipcthreadstate: Self ()-> jointhreadpool ();
}
Android. mk file:
Local_path: = $ (call my-DIR)
Include $ (clear_vars)
Local_src_files: = addserver. cpp
Local_shared_libraries: = libutils libaddservice
Local_module: = addservice
Include $ (build_executable)
Step-3: Compile the above two files to generate libadd. So class library and addserver executable programs respectively. Next, copy libadd. So to/system/lib/of the android simulator, and copy addserver to/system/bin.
Step-4: Run addserver. The command "addserver: instantiate ()" is executed to the "instantiate ()" function of the addserver class. Its content is:
Int addservice: instantiate (){
LogE ("addservice instantiate ");
Int r = defaservicservicemanager ()-> addservice (
String16 ("guilh. Add"), new addservice ());
LogE ("addservice r = % d/N", R );
Return R;
}
First, execute new addserver () to create an addserver category object;
Call the defaservicservicemanager () function to obtain the iservicemanager interface of SM;
Call iservicemanager: addserver () to save the object reference to the binder driver.
Step-5: The addservice service is successfully added to the binder driver. Now you can write an add class to use the addservice core service. Write the add class in C ++. The complete program code is:
Add. h file:
# Ifndef Android _ add_h
# Define Android _ add_h
Namespace Android {
Class add {
Public:
Int setn (int n );
PRIVATE:
Static const void getaddservice ();
};
}; // Namespace
# Endif // Android _ add_h
Add. cpp file:
# Include <utils/iservicemanager. h>
# Include <utils/ipcthreadstate. h>
# Include "Add. H"
Namespace Android {
Sp <ibinder> binder;
Int Add: setn (int n ){
Getaddservice ();
Parcel data, reply;
Data. writeint32 (getpid ());
Data. writeint32 (N );
LogE ("bpaddservice: Create remote ()-> transact ()/n ");
Binder-> transact (0, Data, & reply );
Int I = reply. readint32 ();
Return I;
}
Const void Add: getaddservice (){
Sp <iservicemanager> Sm = defaultservicemanager ();
Binder = Sm-> getservice (string16 ("guilh. Add "));
LogE ("Add: getaddservice % P/N", Sm. Get ());
If (Binder = 0 ){
Logw ("addservice not published, waiting ...");
Return;
}
}
};
Android. mk file:
Local_path: = $ (call my-DIR)
Include $ (clear_vars)
Local_src_files: = Add. cpp
Local_shared_libraries: = libutils libaddservice
Local_module: = libadd
Local_prelink_module: = false
Include $ (build_shared_library)
Step-6: Write a jni native class to use the add class object. Through the JNI native function, you can connect to the Java-layer service.
It is preferred to use the javah command to generate the corresponding header file.
Com_hello_service_myser.h file:
/* Do not edit this file-it is machine generated */
# Include <JNI. h>
/* Header for class com_hello_service_myser */
# Ifndef _ included_com_hello_service_myser
# DEFINE _ included_com_hello_service_myser
# Ifdef _ cplusplus
Extern "C "{
# Endif
/*
* Class: com_hello_service_myser
* Method: intfromjni
* Signature: () I
*/
Jniexport jint jnicall java_com_hello_service_myser_intfromjni
(Jnienv *, jobject );
# Ifdef _ cplusplus
}
# Endif
# Endif
Then implement the corresponding function.
Com_hello_service_myser.cpp file:
# Include <JNI. h>
# Include <jnihelp. h>
# Include "../libadd/Add. H"
# Include "com_hello_service_myser.h"
Jniexport jint jnicall java_com_hello_service_myser_intfromjni (jnienv * ENV, jobject thiz)
{
Android: Add myadd;
Int r = myadd. setn (5 );
Return R;
}
Android. mk file:
Local_path: = $ (call my-DIR)
Include $ (clear_vars)
Local_src_files: = com_hello_service_myser.cpp
Local_c_includes: = $ (jni_h_include)
Local_shared_libraries: = libutils libadd
Local_module: = libjniadd
Local_prelink_module: = false
Include $ (build_shared_library)
All relevant file organizations:
A @ Ubuntu :~ /Work/Android/source_android/development/my_module $ tree service
Service
| -- Addserver
| -- Android. mk
| '-- Addserver. cpp
| -- JNI
| -- Android. mk
| -- Com_hello_service_myser.cpp
| '-- Com_hello_service_myser.h
| -- Libadd
| -- Add. cpp
| -- Add. h
| '-- Android. mk
'-- Libaddservice
| -- Addservice. cpp
| -- Addservice. h
'-- Android. mk
4 directories, 11 files
Create a project in eclipse and use the above add class to use our addservice.
Myser. Java file:
Package com. Hello. Service;
Import Android. App. activity;
Import Android. OS. Bundle;
Import Android. widget. textview;
Public class myser extends activity {
/** Called when the activity is first created .*/
@ Override
Public void oncreate (bundle savedinstancestate ){
Super. oncreate (savedinstancestate );
Int I = intfromjni ();
Textview TV = new textview (this );
TV. settext (string. valueof (I ));
Setcontentview (TV );
}
Public native int intfromjni ();
Static {
System. loadlibrary ("jniadd ");
}
}
V. Service compilation problems
The toolchain used by Android (that is, the cross-compilation tool chain) can be downloaded from the following URL:
Http://android.kernel.org/pub/android-toolchain-20081019.tar.bz2. If you download the complete Android project source code, you can find the cross-compilation tool under the "<your_android>/prebuilt/linux-x86/toolchain/arm-eabi-4.2.1/bin" directory, for example, Android arm-eabi-gcc-4.2.1. We can directly use the source code package for compilation.
Android does not use glibc as the C library, but uses bionic libc developed by Google. Its official toolchain is based on Bionic libc rather than glibc. This makes it difficult to use or port other toolchains for Android: before Google releases the official toolchain for Android, the toolchain used by most Android enthusiasts is a general toolchain downloaded in the http://www.codesourcery.com/gnu_toolchains/arm/download.html, which is used to compile and port android
Linux Kernel is feasible, because the kernel does not need a C library, but it is troublesome to directly use or transplant other toolchains when developing Android applications, applications compiled by other toolchains can only run in the android simulator in the form of static compilation, which is obviously unacceptable in actual development. Currently, we have not seen any documents indicating that other cross compilers have been successfully transplanted to compile Android applications.
Compared with glibc, bionic libc has the following features:
L use BSD license instead of glibc GPL license;
L The size is only about 200 K, half smaller than glibc, and faster than glibc;
L implements a smaller and faster pthread;
L provides important functions required by Android, such as "getprop" and "logi;
L not fully support POSIX standards, such as C ++ exceptions and wide chars;
L libthread_db and libm implementations are not provided
In addition, some other binary tools used in Android are also special:
When loading a dynamic library,/system/bin/linker is used instead of common/lib/lD. So;
Prelink is not a common prelink tool, but a prelink. Its source code is "<your_android>/build/tools/Apriori"
Strip tool does not use commonly used strip, but under the "<your_android>/prebuilt/linux-x86/toolchain/arm-eabi-4.2.1/bin" directory arm-Eabi-strip, instead, it is the soslim tool located in <your_android>/out/host/linux-x86/bin.
The following describes how to compile the service program we just created.
1. Create the my_module directory under the $ (your_android)/Development Directory and copy our server folder to this directory. $ (your_android) indicates the directory where the android source code is located.
# Mkdir $ (your_android)/development/my_module
2. Android. mk: The standard name of the android makefile. Do not change it. For the format and content of the android. mk file, refer to other existing Android. mk files. The content of the android. mk file for the add program is as follows:
Local_path: = $ (call my-DIR)
Include $ (clear_vars)
Local_src_files: = Add. cpp
Local_shared_libraries: = libutils libaddservice
Local_module: = libadd
Local_prelink_module: = false
Include $ (build_shared_library)
Note that the above local_src_files are used to specify the source file. local_module specifies the name of the module to be compiled, which will be used in the next step. include $ (build_shared_library) indicates that the file will be compiled into a dynamic library, if you want to compile an executable file, you can use build_executable, which can be in $ (your_android)/build/CORE/config. mk.
3. Return to the top-level directory of the android source code for compilation:
# Cd $ (your_android) & make libadd
Note that the target name libadd in make libadd is the module name specified by local_module In the android. mk File above.
4. The compiled executable file is stored in the simulator and transmitted to the simulator through "ADB push", and then logged on to the simulator terminal through "ADB shell.
Vi. Problems and Solutions:
(1) The system prompts that Bison is missing. Install bison: sudo apt-Get install bison.
(2) The error frameworks/policies/base/policyconfig. mk: 22: *** no module defined for the given product_policy (Android. policy_phone). Stop. occurs.
Solution:
In row 89th of build/tools/findleaves. Sh,
Find "$ {@: 0: $ nargs}" $ findargs-type F-name "$ FILENAME"-print |
Change to find "$ {@: 1: $ nargs-1}" $ findargs-type F-name "$ FILENAME"-print |