在android下,其实有另外的一类应用程序,他们用Java开发,但却不使用android的应用框架,不包含android应用程序四大组件中的任何一个,几乎就与我们平常在PC机上开发的那些Java应用程序一样。这里,我们来看一下,这样的应用程序要如何实现。

最典型的无android framework的android Java程序就是两个我们经常会用到的工具,一个是monkey,另外一个是am。我们通常用前者来做monkey测试,而常常使用后者,来执行通过命令行启动Activity等操作。这里我们也会以这两个应用程序为例,来研究android下frameworkless Java应用程序的开发方法。

要了解这些app的结构和实现,最简单的方式则是直接来阅读code和Android.mk 文件了。我们来看一下monkey的code,在development/cmds/monkey/monkey下。首先,我们可以先来看一下这个project的目录结构:

.. 01-Nov-2013 4 KiB

Android.mk 01-Nov-2013 423

example_script.txt 01-Nov-2013 731

MODULE_LICENSE_APACHE2 01-Nov-2013 0

monkey 01-Nov-2013 217

NOTICE 01-Nov-2013 10.4 KiB

README.NETWORK.txt 01-Nov-2013 4.1 KiB

src/ 01-Nov-2013 4 KiB

这个project根目录下面的内容不是很多,src/目录存放所有的源代码文件,Android.mk用于编译这个project,一个看上去有点奇怪的名为"monkey"的文件,还有其他一些对于我们了解这样的项目的创建方法而言无关紧要的文件,比如readme,notice和license之类。接着我们来看一下这个project Android.mk 文件的实现:

#Copyright2008TheAndroidOpenSourceProject#LOCAL_PATH:=$(callmy-dir)include$(CLEAR_VARS)LOCAL_SRC_FILES:=$(callall-subdir-java-files)LOCAL_MODULE:=monkeyinclude$(BUILD_JAVA_LIBRARY)################################################################include$(CLEAR_VARS)ALL_PREBUILT+=$(TARGET_OUT)/bin/monkey$(TARGET_OUT)/bin/monkey:$(LOCAL_PATH)/monkey|$(ACP)$(transform-prebuilt-to-target)

这个Android.mk指导编译系统在编译时做了两件事情,一是将project下所有的Java文件编译为一个Java library,LOCAL_MODULE的值为monkey,也就意味着编译的结果将会是一个名为monkey.jar的文件,编译出来的这个jar文件最终将位于设备的/system/framework/目录下。另外,就是将当前目录下那个名为monkey的文件,做一个copy,最终这个文件将位于设备的/system/bin/目录下。

但monkey.jar和那个monkey文件分别是做什麽的,而它们到底又是一种什麽样的关系呢?我们平常下monkey命令时执行的又是哪一个呢?我们来看project根目录下的那个monkey文件:

#Scripttostart"monkey"onthedevice,whichhasaveryrudimentary#shell.#base=/systemexportCLASSPATH=$base/framework/monkey.jartrap""HUPexecapp_process$base/bincom.android.commands.monkey.Monkey$*

哦,原来这是一个shell脚本文件。在这个脚本文件中,就是设置环境变量,然后执行app_process本地应用程序。传给脚本文件的所有参数,也都会直接传递给app_process命令。由此,即是说,当我们执行monkey命令时,所直接执行的其实是这个脚本文件,然后透过脚本文件,再来执行monkey Java应用程序。

app_process大概就像是我们PC平台Java环境中的java命令一样,即是Java虚拟机。我们在设备上直接执行app_process这个命令,可以看到这个app吐出如下的log:

root@cay:/#app_processError:noclassnameor--zygotesupplied.Usage:app_process[java-options]cmd-dirstart-class-name[options]Illegalinstruction(coredumped)

这个即是android下DVM虚拟机,以命令行的方式启动的方法。由这个usage和前面那个shell脚本文件的实现,不难猜测,com.android.commands.monkey.Monkey应该是monkey这个Java app的main class。接着我们来简单看一下这个main class的实现:

/***Command-lineentrypoint.**@paramargsThecommand-linearguments*/publicstaticvoidmain(String[]args){//Settheprocessnameshowingin"ps"or"top"Process.setArgV0("com.android.commands.monkey");intresultCode=(newMonkey()).run(args);System.exit(resultCode);}/***Runthecommand!**@paramargsThecommand-linearguments*@returnReturnsaposix-styleresultcode.0fornoerror.*/privateintrun(String[]args){//Super-earlydebuggerwaitfor(Strings:args){if("--wait-dbg".equals(s)){Debug.waitForDebugger();}}//Defaultvaluesforsomecommand-lineoptionsmVerbose=0;mCount=1000;mSeed=0;mThrottle=0;//prepareforcommand-lineprocessingmArgs=args;mNextArg=0;//setapositivevalue,indicatingnoneofthefactorsisprovidedyetfor(inti=0;i<MonkeySourceRandom.FACTORZ_COUNT;i++){mFactors[i]=1.0f;}if(!processOptions()){return-1;}if(!loadPackageLists()){return-1;}//nowsetupadditionaldatainpreparationforlaunchif(mMainCategories.size()==0){mMainCategories.add(Intent.CATEGORY_LAUNCHER);mMainCategories.add(Intent.CATEGORY_MONKEY);}if(mSeed==0){mSeed=System.currentTimeMillis()+System.identityHashCode(this);}

这些就完全是常规Java 应用程序的写法了。不过我们也需要更正一下前面一些提法的错误之处。类似于monkey的这种Java应用程序,不一定完全不会使用到android framework的任何组件,只不过这些应用程序的写法,不同于常规android应用程序的写法,倒是与常规的Java应用程序的写法无异。如果这些应用程序要使用android framework提供的功能,则方法就与使用普通的jar文件无异。

android下am命令的project结构与monkey大同小异,只不过,am这个project的路径为frameworks/base/cmds/am/。am的project结构:

.. 01-Nov-2013 4 KiB

am 01-Nov-2013 210

Android.mk 01-Nov-2013 354

MODULE_LICENSE_APACHE2 01-Nov-2013 0

NOTICE 01-Nov-2013 10.4 KiB

src/ 01-Nov-2013 4 KiB

am project Android.mk文件的实现:

#Copyright2008TheAndroidOpenSourceProject#LOCAL_PATH:=$(callmy-dir)include$(CLEAR_VARS)LOCAL_SRC_FILES:=$(callall-subdir-java-files)LOCAL_MODULE:=aminclude$(BUILD_JAVA_LIBRARY)include$(CLEAR_VARS)LOCAL_MODULE:=amLOCAL_SRC_FILES:=amLOCAL_MODULE_CLASS:=EXECUTABLESLOCAL_MODULE_TAGS:=optionalinclude$(BUILD_PREBUILT)

am脚本文件的实现:

#!/system/bin/sh##Scripttostart"am"onthedevice,whichhasaveryrudimentary#shell.#base=/systemexportCLASSPATH=$base/framework/am.jarexecapp_process$base/bincom.android.commands.am.Am"$@"

Done.

更多相关文章

  1. 【Android】Android(安卓)4.0 无法接收开机广播的问题
  2. Android各种资源详解
  3. android项目中每个文件的作用
  4. Fast File Transfer – 让 Android(安卓)通过 WIFI 传输文件到任
  5. 浅入浅出 Android(安卓)安全:第一章 Android
  6. Xamarin.Android使用教程之创建第一个Android应用程序
  7. Android之Adapter用法总结
  8. Android之Adapter用法总结
  9. android中资源整理

随机推荐

  1. Android(安卓)手机灭屏流程分析详解
  2. 如何去除标题栏title
  3. Android(安卓)RecyclerView和ListView的
  4. Android中的MVP笔记之四: Data Binding 库
  5. 浅析Android(安卓)Service 中 onStartCom
  6. Android多线程——线程池ThreadPoolExecu
  7. android studio中xml文件报错: URI is not
  8. MPAndroidChart中使用 LineChart 踩得坑!
  9. Mac OS X下编译Android源码
  10. 探索Android(安卓)FrameWork底层开发