例1:JNI程序使用libhello-jni.so的符号
libhello-jni.so由hello-jni.c组成。

hello-jni.c如下:

#include<string.h> #include<jni.h> #include<android/log.h>
#defineLOG_TAG"libhello-jni" #defineLOGE(...)__android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
voidJava_com_example_hellojni_HelloJni_functionA(JNIEnv*env,jobjectthiz) { LOGE("SamInfo:EnterNativefunctionA"); return; }
Android.mk如下:
LOCAL_PATH:=$(callmy-dir)
include$(CLEAR_VARS)
LOCAL_MODULE :=hello-jni LOCAL_SRC_FILES:=hello-jni.c LOCAL_LDLIBS:=-llog

include$(BUILD_SHARED_LIBRARY)
../../../ndk-build-BV=1
可以正常编译,再使用Eclipse编译Android工程,可正常运行。





例2:JNI程序使用libhello-jni.so的符号
libhello-jni.so由hello-jni.c,hell-jniB.c,头文件hello-jni.h组成。

hello-jni.h如下:
#ifndef_HELLO_JNI_H #define_HELLO_JNI_H
#include<string.h> #include<jni.h> #include<android/log.h>
#defineLOG_TAG"libhello-jni" #defineLOGE(...)__android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
#endif
hello-jni.c如下:
#include"hello-jni.h"
voidJava_com_example_hellojni_HelloJni_functionA(JNIEnv*env,jobjectthiz) { LOGE("SamInfo:EnterNativefunctionA"); return; }
hell-jniB.c如下:
#include"hello-jni.h"

voidJava_com_example_hellojni_HelloJni_functionB(JNIEnv*env,jobjectthiz) { LOGE("SamInfo:EnterNativefunctionB"); return; }
Android.mk如下:
LOCAL_PATH:=$(callmy-dir)
include$(CLEAR_VARS)
LOCAL_MODULE :=hello-jni LOCAL_SRC_FILES:=hello-jni.chell-jniB.c
LOCAL_LDLIBS:=-llog

include$(BUILD_SHARED_LIBRARY)

注意: LOCAL_SRC_FILES:=hello-jni.chell-jniB.c 此模块hello-jni由两个C文件组成,因为hello-jni.h只是依赖文件,所以不必加入。
又因为hello-jni.h在project/jni目录中,此目录本身为-I,所以也不用再Android.h中指出。



例3:JNI程序使用libhello-jni.so的符号
libhello-jni.so依赖于libB.a.
libhello-jni.so由hello-jni.c,hell-jniB.c,头文件hello-jni.h组成。
libB.a由libstatic/B1.c,libstatic/B2.c头文件libstatic/B.h组成。

B.h如下:
#ifndef_B_H #define_B_H
#include<string.h> #include<jni.h> #include<android/log.h>
intiFunctionB1(); intiFunctionB2();
#defineLOG_TAG"libStatic" #defineLOGI(...)__android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
#endif
B1.c:
#include"B.h"

intiFunctionB1() { LOGI("SamInfo:EnterstaticfunctioniFunctionB1()"); return0; }
B2.c
#include"B.h"

intiFunctionB2() { LOGI("SamInfo:EnterstaticfunctioniFunctionB2()"); return0; }



hello-jni.h:
#ifndef_HELLO_JNI_H #define_HELLO_JNI_H
#include<string.h> #include<jni.h> #include<android/log.h>
#include"libstatic/B.h"
#defineLOG_TAG"libhello-jni" #defineLOGE(...)__android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)

#endif

hello-jni.c:

#include"hello-jni.h"

voidJava_com_example_hellojni_HelloJni_functionA(JNIEnv*env,jobjectthiz) { LOGE("SamInfo:EnterNativefunctionA"); iFunctionB1(); return; }

hell-jniB.c:
#include"hello-jni.h"

voidJava_com_example_hellojni_HelloJni_functionB(JNIEnv*env,jobjectthiz) { LOGE("SamInfo:EnterNativefunctionB"); iFunctionB2(); return; }


Android.mk如下:
LOCAL_PATH:=$(callmy-dir)
include$(CLEAR_VARS)
LOCAL_MODULE:=hello-B LOCAL_SRC_FILES:=libstatic/B1.clibstatic/B2.c
include$(BUILD_STATIC_LIBRARY)
include$(CLEAR_VARS)
LOCAL_MODULE:=hello-jni LOCAL_SRC_FILES:=hello-jni.chell-jniB.c LOCAL_STATIC_LIBRARIES:=hello-B LOCAL_LDLIBS:=-llog

include$(BUILD_SHARED_LIBRARY)
这就是典型的一个Android.mk中包含2个Modules的例子。其中一个是产生静态库,另一个产生动态库。
动态库依赖于静态库。(一定要添加LOCAL_STATIC_LIBRARIES:=hello-B,否则不生成静态库)




例4:JNI程序使用libA.so(由A1.c,A2,c,A.h组成)
libA.so依赖于libB.so(由B1.c,B2.c,B.h组成)


情况分析:
因为libB.so被libA.so使用。所以肯定要加入:
LOCAL_LDLIBS:=-L$(LOCAL_PATH)/../libs/armeabi/ -lhello-B

但请注意:此时libA.so中所用到的libB.so的符号只是一个空穴。并为将实现加进来。

而如果使用:
LOCAL_SHARED_LIBRARIES:=hello-B
也仅仅是将libhello-B.so添加进编译选项。并未将符号添加进去。

在Linux下,此类情况可以将动态库放置于某个目录下,然后使用exportLD_LIBRARY_PATH来解决。但Android下并无此方法。导致运行时会找不到libhello-B.so中的符号。


针对此类情况,有两种方法,但都不是特别好用。分别描述如下:

方法1.

将libhello-B.so放置于/system/lib下。
且Android.mk如下:
LOCAL_PATH:=$(callmy-dir)
include$(CLEAR_VARS)
LOCAL_MODULE:=hello-B LOCAL_SRC_FILES:=libstatic/B1.clibstatic/B2.c LOCAL_LDLIBS:=-llog include$(BUILD_SHARED_LIBRARY)
include$(CLEAR_VARS)
LOCAL_MODULE:=hello-jni LOCAL_SRC_FILES:=hello-jni.chell-jniB.c #LOCAL_SHARED_LIBRARIES:=hello-B LOCAL_LDLIBS:=-llog-L$(LOCAL_PATH)/../libs/armeabi/-lhello-B
include$(BUILD_SHARED_LIBRARY)

此Android.mk有两个模块,分别产生libhello-B.so,libhello-jni.so.后者依赖于前者。

而因为Java层程序使用: System.loadLibrary("hello-jni");
则libhello-jni.so的符号加入到Java应用程序中。而它使用到的libhello-B.so,则能够在/system/lib下找到。


方法2.将libhello-B.so也添加如Java程序中。且放置于hello-jni之前。
System.loadLibrary("hello-B"); System.loadLibrary("hello-jni");

方法3:
可以使用dlopen()方式调用。
据说使用-rpath可以指定应用程序查找库的目录。但Sam觉得理论上并不可能(因为Java无法指定Wl,-rpath).也没有尝试出来。




例5:JNI程序使用libA.so(由A1.cA2.c,A.h组成)
libA.so依赖于libB.so(由B1.c,B2.c,B.h组成)
libB.so依赖于libC.so(由c.c组成)和libD.a(由d.c组成)
libC.so依赖于libD.a(由d.c组成)



Android.mk:
LOCAL_PATH:=$(callmy-dir)
include$(CLEAR_VARS)
LOCAL_MODULE:=hello-B LOCAL_SRC_FILES:=libstatic/B1.clibstatic/B2.c LOCAL_STATIC_LIBRARIES:=D LOCAL_LDLIBS:=-llog-lC-L$(LOCAL_PATH)/../libs/armeabi/ include$(BUILD_SHARED_LIBRARY)

include$(CLEAR_VARS)
LOCAL_MODULE:=hello-jni LOCAL_SRC_FILES:=hello-jni.chell-jniB.c #LOCAL_SHARED_LIBRARIES:=hello-B LOCAL_LDLIBS:=-llog-L$(LOCAL_PATH)/../libs/armeabi/-lhello-B include$(BUILD_SHARED_LIBRARY)

include$(CLEAR_VARS) LOCAL_MODULE:=C LOCAL_SRC_FILES:=c.c LOCAL_LDLIBS:=-llog LOCAL_STATIC_LIBRARIES:=D include$(BUILD_SHARED_LIBRARY)

include$(CLEAR_VARS) LOCAL_MODULE:=D LOCAL_SRC_FILES:=d.c LOCAL_LDLIBS:=-llog include$(BUILD_STATIC_LIBRARY) 请注意:如此写法:则libD.a中的符号分别被:libC.so,libB.so两次引用。



例6:JNI程序使用libA.so(由A1.cA2.c,A.h组成)
并引用外部生成的:libE.so,libF.a.

Sam:经常发生这样的情况,某NDK工程A生成一个动态库,供另一个NDK工程B使用。我们常把此动态库放到B工程的lib/armeabi下。但ndk-build时,它会首先删除lib/armeabi下所有.so文件。
所以可以使用 PREBUILT_SHARED_LIBRARY
Android.mk:
LOCAL_PATH:=$(callmy-dir) include$(CLEAR_VARS)
LOCAL_MODULE :=hello-B LOCAL_SRC_FILES:=libstatic/B1.clibstatic/B2.c LOCAL_SHARED_LIBRARIES:= prelib
LOCAL_LDLIBS:=-llog include$(BUILD_SHARED_LIBRARY) include$(CLEAR_VARS)
LOCAL_MODULE :=hello-jni LOCAL_SRC_FILES:=hello-jni.chell-jniB.c #LOCAL_SHARED_LIBRARIES:=hello-B LOCAL_LDLIBS:=-llog -L$(LOCAL_PATH)/../libs/armeabi/ -lhello-B include$(BUILD_SHARED_LIBRARY)
include$(CLEAR_VARS) LOCAL_MODULE:=prelib LOCAL_SRC_FILES:=libE.so
include$(PREBUILT_SHARED_LIBRARY)

注意:当PREBUILT_SHARED_LIBRARY时,LOCAL_SRC_FILES不再是.c文件,而是动态库。它可以放置在jni下。编译时,它会自动被copy到lib/armaebi下。
请注意模块名。它将被用作LOCAL_SHARED_LIBRARIES


注1:
NDK实用技巧:

1.显示NDKBuild过程中所有编译选项和动作:
../../ndk-buildV=1
这样就可以看到编译时所用编译选项是否我们期望使用的。

2.重新编译:
../../ndk-build-B
或者:
../../ndk-buildclean
../../ndk-build
注意:此处NDK版本为NDKR7C.(不同NDK版本,ndk-build所产生的Makefile并不完全相同)

更多相关文章

  1. Android之动态改变控件大小
  2. android 屏幕测试程序 测试R G B三色 和 全黑, 全白5种状态
  3. android 编写命令行测试程序
  4. 系统命令行运行 android app程序
  5. [置顶] Android(安卓)系统应用调用,intent 的使用方法总结
  6. Android(安卓)Permission中英对照
  7. Android的常用方法(转载)
  8. android应用中调用系统相应用汇总
  9. [转]Android虚拟电源管理驱动

随机推荐

  1. Xml之Linq如何遍历存储的数据
  2. 用Shell脚本生成XML文件实例详解
  3. Server.xml内容详解【Tomcat】
  4. 在服务器端的XSLT过程中出现的编码问题解
  5. 除Web程序员所关注的XML的详细基础介绍
  6. web.xml文件内容详细分析
  7. 气象XML数据源应用程序的详细解析
  8. lxml处理xml时的字符编码问题
  9. 类TransformBinder将xml解析为xhtml的实
  10. XSD与XML的检测示例代码