还要基于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
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.so
prebuilt目录下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.mk
4、生成动态库:
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.so
5、运行输出运算结果。OK。
再次记录下整个过程。