Android jni 实例
1. 编写c模块, 实现动态库
在external 目录下添加新目录hellolib, 并添加hellolib.cpp 和Android.mk文件。 Hellolib.cpp 的内容如下:
#include <jni.h>
#define LOG_TAG "TestLib"
#undef LOG
#include <utils/Log.h>
extern "C" JNIEXPORT void JNICALL Java_com_test_TestHelloLib_printHello(JNIEnv * env, jobject jobj)
{
LOGD("Hello LIB wktwkt wktwkt !/n");
}
extern "C" JNIEXPORT void JNICALL Java_com_test_TestHelloLib_printHelloArg(JNIEnv *env, jobject jobj, jstring s)
{
const char *pathStr = env->GetStringUTFChars(s, NULL);
LOGD("wwwwwwkkkkkkkkkkktttttt : %s/n", pathStr);
env->ReleaseStringUTFChars(s, pathStr);
}
注意这里的函数名需要按照JNI的规范(因此也可以用javah -jni工具来生成头文件,来保证函数名的正确性),Java_com_test_TestHelloLib_printHello的命名对应后面在java代码中,package名字是com.test,类名是TestHelloLib,native函数名是printHello和printHelloArg。
另外,LOGD及#define LOG_TAG "TestLib"等打印log的方式是采用了Android所提供的LOG机制,这样才能通过Android的logcat工具看到log。
用于编译C模块的Android.mk文件内容如下:
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= /
hellolib.cpp
LOCAL_C_INCLUDES := /
$(JNI_H_INCLUDE)
LOCAL_SHARED_LIBRARIES := /
libutils /
libcutils
LOCAL_PRELINK_MODULE := false
LOCAL_MODULE := libhello
include $(BUILD_SHARED_LIBRARY)
该文件中的一些变量分别对应的含义如下:
LOCAL_SRC_FILES – 编译的源文件
LOCAL_C_INCLUDES – 需要包含的头文件目录
LOCAL_SHARED_LIBRARIES – 链接时需要的外部库
LOCAL_PRELINK_MODULE – 是否需要prelink处理
LOCAL_MODULE – 编译的目标对象
BUILD_SHARED_LIBRARY – 指明要编译成动态库
接下来回到Android顶层目录,并执行make libhello来编译:
build/core/product_config.mk:207: WARNING: adding test OTA key
============================================
TARGET_PRODUCT=generic
TARGET_BUILD_VARIANT=eng
TARGET_SIMULATOR=
TARGET_BUILD_TYPE=release
TARGET_ARCH=arm
HOST_ARCH=x86
HOST_OS=linux
HOST_BUILD_TYPE=release
BUILD_ID=
============================================
build/core/main.mk:178: implicitly installing apns-conf_sdk.xml
target thumb C++: libhello <= external/hellolib/hellolib.cpp
target SharedLib: libhello (out/target/product/generic/obj/SHARED_LIBRARIES/libhello_intermediates/LINKED/libhello.so)
target Non-prelinked: libhello (out/target/product/generic/symbols/system/lib/libhello.so)
target Strip: libhello (out/target/product/generic/obj/lib/libhello.so)
Install: out/target/product/generic/system/lib/libhello.so
2. 编写Java模块
具体Eclipse环境的搭建请参考Android SDK文档中的详细说明,及Hello Android程序的创建过程,这里仅给出我们需要修改的TestHelloLib.java文件:
public class TestHelloLib extends Activity {
/**Calledwhentheactivityisfirstcreated.*/
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
System.load("/data/libhello.so");
printHello();
printHelloArg("wktTestTestTest");
}
private native void printHello();
private native void printHelloArg(String arg);
}
3. 集成测试
将TestHelloLib.apk 和libHello.so 部署到手机仿真器上。
Adb install TestHellolib.apk
Adb push libhello.so /data
要验证其效果需要用Android的logcat工具来查看。运行”adb logcat”可以找到下面的log片断:
b: pid=502 uid=10024 gids={}
I/jdwp ( 502): received file descriptor 10 from ADB
D/dalvikvm( 502): Trying to load lib /data/libhello.so 0x4341bf28
D/dalvikvm( 502): Added shared lib /data/libhello.so 0x4341bf28
D/dalvikvm( 502): No JNI_OnLoad found in /data/libhello.so 0x4341bf28
D/dalvikvm( 502): +++ not scanning '/system/lib/libwebcore.so' for 'printHello'
(wrong CL)
D/dalvikvm( 502): +++ not scanning '/system/lib/libmedia_jni.so' for 'printHell
o' (wrong CL)
D/TestLib ( 502): Hello LIB wktwkt wktwkt !
D/dalvikvm( 502): +++ not scanning '/system/lib/libwebcore.so' for 'printHelloA
rg' (wrong CL)
D/dalvikvm( 502): +++ not scanning '/system/lib/libmedia_jni.so' for 'printHell
oArg' (wrong CL)
D/TestLib ( 502): wwwwwwkkkkkkkkkkktttttt : wktTestTestTest
I/ActivityManager( 47): Displayed activity com.test/.TestHelloLib: 426 ms
D/dalvikvm( 89): GC freed 1403 objects / 74632 bytes in 104ms
D/dalvikvm( 83): GC freed 15971 objects / 524400 bytes in 180ms