在前面我簡單的描述了Android的啟動過程http://blog.csdn.net/codectq/article/details/7383231,但終究是不夠完善。
現在在工程中遇到了實際的問題,反過來閱讀下代碼,再重新審視一下在kernel啟動之後的ANDROID啟動過程。
在frameworks/base/services/java/com/android/server檔案夾下的SystemServer.cpp檔案。在此檔案中調用了init1()函數,檔案中對次函數的描述為:這個方法是從Zygote中調用來初始化系統。這將引起本地的服務(Surfaceflinger,audioflinger等)開啟。在這些完成之後將回調init2()來開始android服務。
從上面的描述中我們可以得知兩個方面:一是在android的服務中,我們分兩種服務,一種是native服務,另一種是android服務。二是我們的本地服務是在init1()的過程中完成的,而android服務是在init2()的過程中完成的。
從實際的真機的啟動過程的列印資訊我們也能夠看出,在啟動的過程中,我們首先會啟動SurfaceFlinger,AudioFlinger然後開始啟動dalikvm,從而進入對Zygote和System並且通過調用system_init()函數和sysproc來啟動Android runtime 啟動native service。通過回調init2(),Android service\thread pool從而進入systemserver,運行systemserver線程,將註冊到systemserver中的服務啟動。
如果我們想藉助Android本身的架構來完成添加我們的服務的目的的情況下我們不妨就利用這些。
在我們通過使用JNI機制使得上層的java應用能夠調用native service。而具體的實現就是將.cpp檔案放在JNI檔案夾下,而將.java檔案放在java檔案夾下。具體步驟如下:
在上文中,我們說過我們可以藉助Android自身架構的東西來完成我們的JNI服務,而不必每個細節都自己完成。並且我們提到我們會調用AndroidRuntime所以我們可以將服務註冊到AndroidRuntime.cpp檔案中。下面是個經典的例子,此處做個摘抄地址為http://dongyulong.blog.51cto.com/1451604/545496(但是不知道是不是原作者)
frameworks/base/core/jni 路徑下建立例子 android_mytest_hellojni.cpp 檔案,這個檔案就是在 JNI 層實現介面。檔案內容如下:(可參考同一目錄下的 android_debug_JNITest.cpp 檔案編寫)
#define LOG_TAG "HelloJNI" #include "jni.h" #include "nativehelper/JNIHelp.h" #include "utils/Log.h" #include "utils/misc.h"
namespace android { static jstring android_mytest_hellojni_displayString(JNIEnv *env, jclass clazz) { return env->NewStringUTF("Hello from JNI!"); }
/* * JNI registration. */ static JNINativeMethod gMethods[] = { /* name, signature, funcPtr */ { "displayString", "()Ljava/lang/String;", (void*) android_mytest_hellojni_displayString }, }; int register_android_mytest_hellojni(JNIEnv* env) { //此處的目錄結構就是在Javaframework層的檔案目錄,且必須一致
return jniRegisterNativeMethods(env, "android/mytest/hellojni", gMethods, NELEM(gMethods)); } };
|
2. JNI 層:對編譯的修改配置
2.1修改/Android/android-1.6_r2/frameworks/base/core/jni目錄下的Android.mk 檔案,在LOCAL_SRC_FILES:= \ 下面加上
android_mytest_hellojni.cpp \
2.2修改/Android/android-1.6_r2/frameworks/base/core/jni目錄下的AndroidRuntime.cpp 檔案在extern int 後面添加
extern int register_android_mytest_hellojni(JNIEnv* env);
然後在static const RegJNIRec gRegJNI[] = {下面添加
REG_JNI(register_android_mytest_hellojni),
這樣,JNI層的修改就到此為止了。
frameworks/base/core/java/android/ 建立檔案目錄 mytest ,在該目錄下建立檔案 hellojni.java 聲明介面。內容如下:(可以參考 android-1.6_r2/frameworks/base/core/java/android/debug 目錄下的 JNITest.java 檔案編寫)
package android.mytest; public class hellojni{ public hellojni(){} //此處聲明為public所以才可以被application調用
public static native String displayString(); }
|
4 .下面我們要對我們做過更改的 libandroid_runtime.so 和 framework.jar 進行重新編譯。
在原始碼工程目錄下輸入 make libandroid_runtime 重新編譯產生 libandroid_runtime.so
…
target thumb C++: libandroid_runtime <= frameworks/base/core/jni/android_mytest_hellojni.cpp
target thumb C++: libandroid_runtime <= frameworks/base/core/jni/AndroidRuntime.cpp
target SharedLib: libandroid_runtime (out/target/product/generic/obj/SHARED_LIBRARIES/libandroid_runtime_intermediates/LINKED/libandroid_runtime.so)
target Prelink: libandroid_runtime (out/target/product/generic/symbols/system/lib/libandroid_runtime.so)
target Strip: libandroid_runtime (out/target/product/generic/obj/lib/libandroid_runtime.so)
Install: out/target/product/generic/system/lib/libandroid_runtime.so
然後再輸入 make framework 重新編譯產生 framework.jar
…
Install: out/target/product/generic/system/framework/framework.jar