还要基于NDK提供的two-libs例子,来实现使用第三方动态库链接生成最终动态库(老感觉有点别扭)。
简单来说就是实现在so文件里面调用第三方的so文件中的方法。
1、建立android工程,编写java对应JNI层的本地接口(这里跟two-libs一样,就多了一个加载第三方库语句)。
package com.example.twolibs; import android.app.Activity; import android.widget.TextView; import android.os.Bundle;public class TwoLibs extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); TextView tv = new TextView(this); int x = 1000; int y = 42; // here, we dynamically load the library at runtime // before calling the native method. // int z = add(x, y); tv.setText( "The sum of " + x + " and " + y + " is " + z ); setContentView(tv); } public native int add(int x, int y); static { System.loadLibrary("twolib-first"); System.loadLibrary("twolib-second"); } }
JNI文件夹下的准备预备文件如下,其中用first.c和Makefile文件是用来生成所谓的第三方动态库文件libtwolib-first.so,具体操作见下:
Android.mk first.c first.h Makefile prebuilt second.c跟之前编写静态库文件方法类似,都是用NDK下的编译器生成的,只不过在这里写到Makefile文件中而已,具体操作见下:
first.h与first.c文件如:
#ifndef FIRST_H #define FIRST_H extern int first(int x, int y); #endif /* FIRST_H */ #include "first.h" int first(int x, int y) { return x + y; }Makefile文件如下:
NDK_PATH = /home/thinker/android/android-ndk-r8e TOOLCHAIN_PATH = $(NDK_PATH)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86/bin CFLAGS = -I$(NDK_PATH)/platforms/android-8/arch-arm/usr/include LDFLAGS = -L$(NDK_PATH)/platforms/android-8/arch-arm/usr/lib CC = $(TOOLCHAIN_PATH)/arm-linux-androideabi-gcc LD = $(TOOLCHAIN_PATH)/arm-linux-androideabi-ld all: $(CC) -O2 -fPIC -c $(CFLAGS) $(LDFLAGS) first.c -o twolib-first.o $(LD) -o libtwolib-first.so twolib-first.o -shared rm -rf twolib-first.o clean: rm -rf libtwolib-first.so跳转到jni目录下,执行make即可生成此libtwolib-first.so这个动态库,即所谓的第三方库。
2、就是编写JNI文件,在其中调用第三方库中的接口int first(int x,int y);具体如下:#include "first.h" #include <jni.h> jint Java_com_example_twolibs_TwoLibs_add( JNIEnv* env, jobject this, jint x, jint y ) { return first(x, y); }3、编写Android.mk文件,就将第三方库链接到此动态库中来。此处有两种写法:
第一种:LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := libtwolib-first LOCAL_SRC_FILES := libtwolib-first.so include $(PREBUILT_SHARED_LIBRARY) include $(CLEAR_VARS) LOCAL_SHARED_LIBRARIES := libtwolib-first LOCAL_MODULE := libtwolib-second LOCAL_SRC_FILES := second.c include $(BUILD_SHARED_LIBRARY)第二种方法,其实就是换种形式而已,都一样。在jni目录下创建一个prebuit文件夹,下面存放一个预处理的Android.mk文件和第三方动态库,如:thinker@fans:~/android/android-ndk-r8e/samples/two-libs/jni/prebuilt$ ls Android.mk libtwolib-first.soprebuilt目录下Android.mk就是申明一个模块的意思,内容如:LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := libtwolib-first LOCAL_SRC_FILES := libtwolib-first.so include $(PREBUILT_SHARED_LIBRARY)此时jni目录下的Android.mk文件不需要声明这个模块了,直接用就Ok了,具体如下:LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := libtwolib-second LOCAL_SRC_FILES := second.c LOCAL_SHARED_LIBRARIES := libtwolib-first include $(BUILD_SHARED_LIBRARY) include $(LOCAL_PATH)/prebuilt/Android.mk4、生成动态库:thinker@fans:~/android/android-ndk-r8e/samples/two-libs/jni$ /home/thinker/android/android-ndk-r8e/ndk-build /home/thinker/android/android-ndk-r8e/build/core/add-application.mk:128: Android NDK: WARNING: APP_PLATFORM android-14 is larger than android:minSdkVersion 3 in /home/thinker/android/android-ndk-r8e/samples/two-libs/AndroidManifest.xml Prebuilt : libtwolib-first.so <= jni/ Install : libtwolib-first.so => libs/armeabi/libtwolib-first.so Compile thumb : twolib-second <= second.c SharedLibrary : libtwolib-second.so Install : libtwolib-second.so => libs/armeabi/libtwolib-second.so5、运行输出运算结果。OK。
再次记录下整个过程。