作者:金良([email protected]) csdn博客:http://blog.csdn.net/u012176591
本工程文件的下载链接:AVIPlayer工程文件
在多个NDK项目之间共享本地模块或者在你的本地模块中引入第三方模块时,你需要懂得NDK_MODULE_PATH的设置与运用:
举个例子,NDK工程目录下的jni文件夹下的Android.mk如下:
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := AVIPlayer LOCAL_SRC_FILES := \ PlayerActivity.cpp # Use AVILib static library LOCAL_STATIC_LIBRARIES += avilib_static include $(BUILD_SHARED_LIBRARY) $(call import-module, transcode-1.1.5/avilib)
第9行表明要用到外来的静态库avilib_static,第13行说明外来的库要去目录transcode-1.1.5/avilib去找。
编译动态库时出现如下错误:
Android NDK: jni/Android.mk: Cannot find module with tag 'transcode-1.1.5/avilib' in import path
Android NDK: Are you sure your NDK_MODULE_PATH variable is properly defined ?
注:transcode-1.1.5/avilib是共享库的目录,在此目录下有源文件和用于编译该共享库的Android.mk文件,需要时可以在该目录下生成共享库。
上面的错误提示表明最上层的Android.mk在编译过程中找不到transcode-1.1.5/avilib路径。
1.
设置方法:
在环境变量里加上一条:
ANDROID_NDK_HOME = D:\ndkWin32\android-ndk-r9d
截图如下:
设置成功后,NDK_MODULE_PATH的默认值为目录%ANDROID_NDK_HOME%/sources,你可以在NDK安装目录下看一下,那儿确实有个叫做sources的文件夹。
前边错误提示是transcode-1.1.5/avilib找不到,那么我们就把文件夹transcode-1.1.5复制到目录%ANDROID_NDK_HOME%/sources下,就能正常编译了。
2.如果你为了便于查看外来的库的内容,需要把外来的库文件加到本工程目录下,可以通过增加NDK_MODULE_PATH来解决。
例如:
仍延续上面的例子,我们把transcode-1.1.5文件夹复制到工程的jni目录下,要让系统在编译时找到它需要我们在上边的Android.mk文件里增加这样一句:
$(call import-add-path,$(LOCAL_PATH))
编辑后的Android.mk内容如下:
LOCAL_PATH := $(call my-dir) $(call import-add-path,$(LOCAL_PATH)) include $(CLEAR_VARS) LOCAL_MODULE := AVIPlayer LOCAL_SRC_FILES := \ PlayerActivity.cpp # Use AVILib static library LOCAL_STATIC_LIBRARIES += avilib_static # Use AVILib static library LOCAL_STATIC_LIBRARIES += avilib_static include $(BUILD_SHARED_LIBRARY)# Import AVILib library module$(call import-module, transcode-1.1.5/avilib)
图中标示为1的文件夹就是我们复制过来的transcode-1.1.5文件夹,而Android.mk就是我们在前头更改的Android.mk文件。
或许你很好奇transcode-1.1.5/avlib里有什么东东,也就是我们引入的内容到底是什么,那么我附图如下:
可以看到transcode-1.1.5/avlib文件夹下有源文件和Android.mk文件,从该目录下的Android.mk文件的内容来看该文件夹下的内容在编译时要生成静态库avilib_static,这个要生成的静态库正是jni目录下的Android.mk文件所需要的,见其第9行:
# Use AVILib static library LOCAL_STATIC_LIBRARIES += avilib_static
另外提一下上边出现的3个逻辑部分(静态库avlib,动态库AVIPlayer,以及Java层)的工作方式,如下图所示
可以看到:1.avlib模块直接与AVIPlayer模块相关联,实际上AVIPlayer对avlib进行了封装,并提供了若干接口;
2.而AVIPlayer直接与Java层相关联,Java曾调入此共享库,并使用其接口;
3.avlib未直接与Java曾相关联,而是以AVIPlayer为联系的中介,AVIPlayer向Java层提供的接口实际上有avlib内的代码来做实际工作。
不过我想到了另一种工作方式,不知可不可行:avlib模块和AVIPlayer模块分别直接与Java层联系,示意图如下:
当然还有另一种基于上一种工作方式的方式,区别在于avlib模块和AVIPlayer模块不但向Java曾提供服务,而且还以平等的地位相关联,即二者互相引用函数。