原文网址:http://blog.csdn.net/qiuxiaolong007/article/details/7860481

记于正文前:环境是ubuntu10.10,android 源码是2.0的,在第一次编译源码的时候遇到不少问题,第二次一次make通过。

1)可能用到的文件或库全部安装(sudo apt-get install git-core gnupg flex bison gperf build-essential zip curl zlib1g-dev gcc-multilib g++-multilib libc6-dev-i386 lib32ncurses5-dev ia32-libs x11proto-core-dev libx11-dev lib32readline5-dev lib32z-dev);

2)建议用jdk1.5编译android源码,1.6也是可以编译通过的,不过需要修改一个文件(这里以2.0为例,要修改文件/build/core/main.mk,将文件中的javac_version := $(shell javac -version 2>&1 | head -n 1 | grep '[ "]1\.5[\. "

]') 全部改为javac_version := $(shell javac -version
 2>&1 | head -n 1 | grep '[ "]1\.6[\. "

]'),总共两处)

             Android 源码下利用jni编译自己的项目

我的练习项目实现了一个简单的四则运算,项目的目录层次如下:

AndroidManifest.xml  Android.mk  jni  res   src

资源文件简简单单,一个布局文件,稍后会有demo的下载地址

主要记录备忘的内容如下:

MainActivity.java

  1. public native int add(int x, int y);
  2. public native int substraction(int x, int y);
  3. public native float multiplication(int x, int y);
  4. public native float division(int x, int y);
  5. static{
  6. System.loadLibrary("arithmetic");
  7. }

生成lib的名称为libarithmetic.so.注意load的时候写"arithmetic"

jni 目录下有两个文件,一个是Android.mk,一个是c++源文件long.cpp

jni/Android.mk如下:

  1. LOCAL_PATH:= $(call my-dir)
  2. include $(CLEAR_VARS)
  3. LOCAL_MODULE_TAGS := optional
  4. LOCAL_MODULE:= libarithmetic
  5. LOCAL_SRC_FILES:= \
  6. long.cpp
  7. LOCAL_SHARED_LIBRARIES := \
  8. libutils
  9. LOCAL_STATIC_LIBRARIES :=
  10. LOCAL_C_INCLUDES += \
  11. $(JNI_H_INCLUDE)
  12. LOCAL_CFLAGS +=
  13. LOCAL_PRELINK_MODULE := false
  14. include $(BUILD_SHARED_LIBRARY)

注释:

LOCAL_PATH(必须定义,而且要第一个定义),宏函数‘my-dir’, 由编译系统提供,用于返回当前路径(即包含Android.mk file文件的目录);

include $( CLEAR_VARS),
CLEAR_VARS由编译系统提供,指定让GNU MAKEFILE为你清除许多LOCAL_XXX变量(例如 LOCAL_MODULE, LOCAL_SRC_FILES, LOCAL_STATIC_LIBRARIES, 等等...),除LOCAL_PATH 。这是必要的,因为所有的编译控制文件都在同一个GNU MAKE执行环境中,所有的变量都是全局的;

LOCAL_MODULE_TAGS :=user eng tests optional

user: 指该模块只在user版本下才编译

eng: 指该模块只在eng版本下才编译

tests: 指该模块只在tests版本下才编译

optional:指该模块在所有版本下都编译

LOCAL_MODULE(必须定义),标识你在Android.mk文件中描述的每个模块。名称必须是唯一的,而且不包含任何空格。Note:编译系统会自动产生合适的前缀和后缀,例如:arithmetic编译成功后将生成libarithmetic.so库文件

LOCAL_SRC_FILES 变量必须包含将要编译打包进模块中源代码文件。不用在这里列出头文件和包含文件。

LOCAL_SHARED_LIBRARIES中加入所需要链接的动态库(*.so)的名称

LOCAL_STATIC_LIBRARIES加入所需要链接的静态库(*.a)的名称

LOCAL_CFLAG可选的编译器选项,用法之一是定义宏,例如LOCAL_CFLAGS    := -Werror作用是编译警告也作为错误信息

LOCAL_PRELINK_MODULE:=false,不作prelink处理,默认是要prelink操作的,有可能造成地址空间冲突(这地方目前还不明白)              long.cpp源代码如下:

  1. #define LOG_TAG "LongTest2 long.cpp"
  2. #include <utils/Log.h>
  3. #include <stdio.h>
  4. #include "jni.h"
  5. jint add(JNIEnv *env, jobject thiz, jint x, jint y){
  6. return x + y;
  7. }
  8. jint substraction(JNIEnv *env, jobject thiz, jint x, jint y){
  9. return x - y;
  10. }
  11. jfloat multiplication(JNIEnv *env, jobject thiz, jint x, jint y){
  12. return (float)x * (float)y;
  13. }
  14. jfloat division(JNIEnv *env, jobject thiz, jint x, jint y){
  15. return (float)x/(float)y;
  16. }
  17. static const char *classPathName = "com/inspur/test2/MainActivity";
  18. static JNINativeMethod methods[]= {
  19. {"add", "(II)I", (void*)add},
  20. {"substraction", "(II)I", (void*)substraction},
  21. {"multiplication", "(II)F", (void*)multiplication},
  22. {"division", "(II)F", (void*)division},
  23. };
  24. typedef union{
  25. JNIEnv* env;
  26. void* venv;
  27. }UnionJNIEnvToVoid;
  28. static int registerNativeMethods(JNIEnv* env, const char* className,
  29. JNINativeMethod* gMethods, int numMethods){
  30. jclass clazz;
  31. clazz = env->FindClass(className);
  32. if (clazz == NULL)
  33. return JNI_FALSE;
  34. if (env->RegisterNatives(clazz, gMethods, numMethods)<0)
  35. return JNI_FALSE;
  36. return JNI_TRUE;
  37. }
  38. static int registerNatives(JNIEnv *env){
  39. if (!registerNativeMethods(env, classPathName,
  40. methods, sizeof(methods)/sizeof(methods[0])))
  41. {
  42. return JNI_FALSE;
  43. }
  44. return JNI_TRUE;
  45. }
  46. jint JNI_OnLoad(JavaVM* vm, void* reserved){
  47. UnionJNIEnvToVoid uenv;
  48. uenv.venv = NULL;
  49. jint result = -1;
  50. JNIEnv *env = NULL;
  51. if (vm->GetEnv(&uenv.venv, JNI_VERSION_1_4) != JNI_OK){
  52. goto bail;
  53. }
  54. env = uenv.env;
  55. env = uenv.env;
  56. if (registerNatives(env) != JNI_TRUE){
  57. goto bail;
  58. }
  59. result = JNI_VERSION_1_4;
  60. bail:
  61. return result;
  62. }

除了利用     编写native   JAVA类,通过javah生成.h文件,根据.h文件编写.c/cpp文件 方法外(名字像老太太的裹脚步,又臭又长,而且不灵活),Android还可以通过引用JNI_Onload方式实现。jint JNI_onLoad(JavaVM* vm, void* reverced),改方法在so文件被加载时调用。

JNI_OnLoad()有两个重要的作用:

  指定JNI版本:告诉VM该组件使用那一个JNI版本(若未提供JNI_OnLoad()函数,VM会默认该使用最老的JNI 1.1版),如果要使用新版本的JNI,例如JNI 1.4版,则必须由JNI_OnLoad()函数返回常量JNI_VERSION_1_4(该常量定义在jni.h中) 来告知VM。

  初始化设定,当VM执行到System.loadLibrary()函数时,会立即先呼叫JNI_OnLoad()方法,因此在该方法中进行各种资源的初始化操作最为恰当。

  JNI_OnUnload()的作用与JNI_OnLoad()对应,当VM释放JNI组件时会呼叫它,因此在该方法中进行善后清理,资源释放的动作最为合适。

更多更详细内容请参考使用RegisterNatives方法传递和使用Java自定义类

项目根目录下Android.mk文件:

  1. LOCAL_PATH:= $(call my-dir)
  2. include $(CLEAR_VARS)
  3. LOCAL_MODULE_TAGS := optional
  4. LOCAL_SRC_FILES := $(call all-java-files-under, src)
  5. LOCAL_JNI_SHARED_LIBRARIES := libarithmetic
  6. LOCAL_PACKAGE_NAME := LongTest
  7. LOCAL_SHARED_LIBRARIES := \
  8. libutils\
  9. liblog
  10. include $(BUILD_PACKAGE)
  11. include $(LOCAL_PATH)/jni/Android.mk
  12. # Also build all of the sub-targets under this one: the shared library.
  13. include $(call all-makefiles-under,$(LOCAL_PATH))

LOCAL_PACKAGE_NAME:项目名称,即最终生成apk的名字

LOCAL_JNI_SHARED_LIBRARIES := libxxx就是把so文件放到apk文件里的libs/armeabi里

执行BUILD_PACKAGE。它的定义也是在config.mk中定义如下:BUILD_PACKAGE:= $(BUILD_SYSTEM)/package.mk

$(call all-java-files-under, src)编译的源代码文件列表添加src目录下所有的java 源文件

$(call all-makefiles-under, $(LOCAL_PATH))编译器会在编译完当前目录下的文件后再深入子目录编译

如果make过android源码,可以在项目根目录下执行mm命令进行编译。前提是执行过source androidSRC/build/envsetup.sh

或者直接把source androidSRC/build/envsetup.sh添加到~/.bashrc中,会更加方便

示例代码下载

最新文章

  1. php的函数和数组
  2. iostat 命令
  3. 快速上手RaphaelJS--Instant RaphaelJS Starter翻译(二)
  4. openssl 心脏滴血
  5. 全网最详系列之-倍增求LCA
  6. Struts2 Package
  7. codeforces 672C - Recycling Bottles 贪心水题
  8. C#程序员整理的Unity 3D笔记(十):Unity3D的位移、旋转的3D数学模型
  9. halt和shutdown 的区别
  10. 《how to design programs》9.3处理任意长度的表
  11. CodeForces 689D Friends and Subsequences
  12. CentOS7.3安装VirtualBox
  13. mysql中的count()函数
  14. Python之面向对象和正则表达(代数运算和自动更正)
  15. MySQL--Insert Buffer
  16. c/c++ 多态的实现原理分析
  17. vim 多行添加注释,取消注释
  18. linux下使用eclipse打开esp32工程文件,并进行编译下载。
  19. CI框架--数据库Query_Builder中的方法
  20. 阿里云服务器配置免费https服务

热门文章

  1. bzoj 1194
  2. swift 随机数
  3. PyCharm 4.0下载(附keygen)
  4. vue-cli 脚手架总结
  5. sql获取每门课程成绩最好的学生信息
  6. javascript正則表達式 &amp;quot;\b&amp;quot;问题
  7. poj 2041 Unreliable Message 字符串处理
  8. How to build UDK2015?
  9. Linux 常用系统命令-20160504
  10. vsim仿真VHDL输出fsdb格式文件