Android通過bin二進(jìn)制程序調(diào)用jar原理
先來看看monkey二進(jìn)程程序的生成.
development\cmds\monkey\Android.mk LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_SRC_FILES := $(call all-subdir-java-files) LOCAL_MODULE := monkeylib LOCAL_MODULE_STEM := monkey include $(BUILD_JAVA_LIBRARY) ################################################################ include $(CLEAR_VARS) LOCAL_MODULE := monkey LOCAL_MODULE_CLASS := EXECUTABLES LOCAL_SRC_FILES := monkey LOCAL_REQUIRED_MODULES := monkeylib include $(BUILD_PREBUILT)
Android.mk分了兩部分,第一部分是編譯生成monkey.jar,第二部分是把monkey這個文件編譯生成monkey的二進(jìn)制程序,看看monkey這個文件。
development\cmds\monkey\monkey base=/system export CLASSPATH=$base/framework/monkey.jar ......... exec app_process $base/bin com.android.commands.monkey.Monkey "$@"
monkey這是一個shell文件,先設(shè)置把monkey.jar添加環(huán)境變量中,然后執(zhí)行app_process這個二進(jìn)制程序,同時傳入monkey jar的路徑和類名。
app_process是在frameworks\base\cmds\路徑下,直接看它的main函數(shù)
frameworks\base\cmds\app_process\app_main.cpp int main(int argc, char* const argv[]) { ......... AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));//創(chuàng)建AndroidRuntime .............. while (i < argc) { const char* arg = argv[i++]; if (strcmp(arg, "--zygote") == 0) { zygote = true; niceName = ZYGOTE_NICE_NAME; } else if (strcmp(arg, "--start-system-server") == 0) { startSystemServer = true; } else if (strcmp(arg, "--application") == 0) { application = true; } else if (strncmp(arg, "--nice-name=", 12) == 0) { niceName.setTo(arg + 12); } else if (strncmp(arg, "--", 2) != 0) {//monkey測試時,傳入的是monkey jar的路徑和包名,所以進(jìn)入這個分支 className.setTo(arg);//className包含com.android.commands.monkey.Monkey break; } else { --i; break; } } Vector<String8> args; if (!className.isEmpty()) { ............... args.add(application ? String8("application") : String8("tool")); runtime.setClassNameAndArgs(className, argc - i, argv + i);//com.android.commands.monkey.Monkey添加到AndroidRuntime中 ............. } else { ............ } 。。。。。。。。。。。。。 if (zygote) { runtime.start("com.android.internal.os.ZygoteInit", args, zygote); } else if (className) {//className為com.android.commands.monkey.Monkey runtime.start("com.android.internal.os.RuntimeInit", args, zygote); } else { fprintf(stderr, "Error: no class name or --zygote supplied.\n"); app_usage(); LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied."); } }
app_process.cpp的main方法先解析argv參數(shù),創(chuàng)建AndroidRuntime的實例,并傳入類名,最后調(diào)用AndroidRuntime.start
framework/base/core/jni/AndroidRuntime.cpp void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote) { ........... //當(dāng)前環(huán)境是否在ANDROID_ROOT、ANDROID_RUNTIME_ROOT、ANDROID_TZDATA_ROOT const char* rootDir = getenv("ANDROID_ROOT"); ............... const char* runtimeRootDir = getenv("ANDROID_RUNTIME_ROOT"); .................. const char* tzdataRootDir = getenv("ANDROID_TZDATA_ROOT"); ............. JniInvocation jni_invocation; jni_invocation.Init(NULL);//jni初始化 JNIEnv* env; if (startVm(&mJavaVM, &env, zygote) != 0) {//啟動java虛擬機 return; } onVmCreated(env);//java虛擬機創(chuàng)建 if (startReg(env) < 0) {//注冊jni ALOGE("Unable to register all android natives\n"); return; } ............................................................................. //jnv的環(huán)境設(shè)置和類型轉(zhuǎn)換 ............................................................................. char* slashClassName = toSlashClassName(className != NULL ? className : "");//className為com.android.internal.os.RuntimeInit jclass startClass = env->FindClass(slashClassName);//得到j(luò)ava類,startClass為com.android.internal.os.RuntimeInit if (startClass == NULL) { ALOGE("JavaVM unable to locate class '%s'\n", slashClassName); /* keep going */ } else { jmethodID startMeth = env->GetStaticMethodID(startClass, "main", "([Ljava/lang/String;)V");//通過類名獲得類名里的main方法 if (startMeth == NULL) { ALOGE("JavaVM unable to find main() in '%s'\n", className); /* keep going */ } else { env->CallStaticVoidMethod(startClass, startMeth, strArray);//由C調(diào)用JAVA,反射調(diào)起com.android.internal.os.RuntimeInit的main方法,進(jìn)入到j(luò)ava世界 } } ............... }
start方法里面首先判斷當(dāng)前環(huán)境是否在ANDROID_ROOT、ANDROID_RUNTIME_ROOT、ANDROID_TZDATA_ROOT,然后調(diào)用startVm,startVm主要是設(shè)置虛擬機的一些參數(shù),onVmCreated是通過jni的環(huán)境檢查類名是否存在,即檢查com.android.internal.os.RuntimeInit是否存在,最后通過反射調(diào)起java的main方法。
我們繼續(xù)看com.android.internal.os.RuntimeInit的main方法
frameworks\base\core\java\com\android\internal\os\RuntimeInit.java public static final void main(String[] argv) { ......... commonInit();//做些log的打印和異常的捕獲 nativeFinishInit();//又進(jìn)入C/C++世界 ............... }
virtual void onStarted() { ............... AndroidRuntime* ar = AndroidRuntime::getRuntime(); ar->callMain(mClassName, mClass, mArgs); ..................... }
framework/base/core/jni/AndroidRuntime.cpp status_t AndroidRuntime::callMain(const String8& className, jclass clazz, const Vector<String8>& args) { ................ methodId = env->GetStaticMethodID(clazz, "main", "([Ljava/lang/String;)V");//通過類名找到靜態(tài)方法名為main的id if (methodId == NULL) { ALOGE("ERROR: could not find method %s.main(String[])\n", className.string()); return UNKNOWN_ERROR; } //args類型轉(zhuǎn)換 const size_t numArgs = args.size(); stringClass = env->FindClass("java/lang/String"); strArray = env->NewObjectArray(numArgs, stringClass, NULL); for (size_t i = 0; i < numArgs; i++) { jstring argStr = env->NewStringUTF(args[i].string()); env->SetObjectArrayElement(strArray, i, argStr); } env->CallStaticVoidMethod(clazz, methodId, strArray);//調(diào)起類名里的main靜態(tài)方法,即com.android.commands.monkey.Monkey的main方法 return NO_ERROR; }
總結(jié):通過命令執(zhí)行monkey時,先設(shè)置monkey.jar的環(huán)境變量,然后執(zhí)行app_process的程序,并傳入monkey二進(jìn)制程序的路徑和monkey的類名,這時就進(jìn)入到了app_process程序。在app_process的main方法里,創(chuàng)建AndroidRuntime的實例,對參數(shù)進(jìn)行校驗,把com.android.internal.os.RuntimeInit包名傳給AndroidRuntime;在AndroidRuntime里做jni的初始化,設(shè)置虛擬機參數(shù),注冊jni,然后反射com.android.internal.os.RuntimeInit的main靜態(tài)方法,最后在AndroidRuntime里通過反射調(diào)起類名里的main方法。
app_process程序還是非常不錯的,利用好它,我們可以仿照monkey程序,開發(fā)出一些特殊的程序。
以上就是Android通過bin二進(jìn)制程序調(diào)用jar原理的詳細(xì)內(nèi)容,更多關(guān)于Android調(diào)用jar的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Ubuntu中為Android系統(tǒng)實現(xiàn)內(nèi)置Java應(yīng)用程序測試Application Frameworks層的硬件服務(wù)
本文主要介紹Ubuntu中為Android系統(tǒng)內(nèi)置應(yīng)用訪問Application Frameworks層的硬件服務(wù),這里提供了詳細(xì)的流程和代碼實例,有興趣的朋友可以參考下2016-08-08Android Studio多渠道打包、自定義打包APK名稱
Android Studio為我們提供了簡便的方法,可以多渠道打包,一次打包所有的渠道包。這篇文章主要介紹了Android Studio多渠道打包、自定義打包APK名稱,需要的朋友可以參考下2018-01-01Android自定義可拖拽的懸浮按鈕DragFloatingActionButton
這篇文章主要介紹了Android自定義可拖拽的懸浮按鈕DragFloatingActionButton,需要的朋友可以參考下2017-06-06安裝android開發(fā)環(huán)境原始版(windows版)
安裝android開發(fā)環(huán)境原始版(windows版)的詳細(xì)步驟2013-03-03

Android編程中Intent實現(xiàn)頁面跳轉(zhuǎn)功能詳解