NDK使用心得
昨天开始弄NDK编程,做之前觉得很简单,网上的例子和说明也一大堆,但直到今天才搞定,其中遇到的种种问题把它记录下来供以后查看,
1.如何通过NDK编译JNI的so文件供android应用使用?
首先在ndk开发目录的samples文件夹下面建myjni文件夹,在myjni文件夹下建jni文件夹用来放生成so代码的myjni.c文件和android.mk文件,myjni.c文件为编译.so的文件,内容如下
#include <string.h>
#include <stdio.h>
#include <jni.h>
#include <android/log.h> //这个地方需要注意,根据你用的ndk目录而定,有的是android/log.h,有的用utils/log.h
//用前者需要在android.mk中增加LOCAL_LDLIBS += -llog,用后者需要在android.mk中增加 //LOCAL_SHARED_LIBRARIES := libutils .
#define LOG_TAG "MYJNI"
#define LOGI(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__) //__android_log_print的android中a字母一定是小写,我写成大写了,结果编译这个库把我郁闷了半天,老是说找不到__Android_log_print。
static char s_string[] = "My god, I did it!";
jstring Java_com_bbk_myjni_myJNI_stringFromJNI( JNIEnv* env,jobject thiz )
{
LOGI("MyJNI is called!");
return (*env)->NewStringUTF(env, s_string);
}
从上面Java_com_bbk_myjni_myJNI_stringFromJNI函数的命名上我们可以了解到JNI函数的命名规则: Java代码中的函数声明需要添加native关键字;Native的对应函数名要以“Java_”开头,后面依次跟上Java的“package名-com_bbk_myjni”、“class名-myJNI”、“函数名-stringFromJNI”,中间以下划线“_”分割,在package名中的“.”也要改为“_”。此外,关于函数的参数和返回值也有相应的规则。
注意命名的大小写,我出现了类名大小写不对的情况,编译不会出问题,调用的时候会出错。
2.如何方便地生成带so文件的apk包?
可以通过eclipse在刚才建的myjni文件夹下面建android工程,在工程的myJNI.java中用到libmyjni.so文件中的函数需要使用native关键字
使用System.loadLibrary加载so,名字不包括文件前面的lib和后缀so。
public native String stringFromJNI();
static{
System.loadLibrary ( "myjni" );
}
编译时会自动把libmyjni.so打包到apk文件中。
3.为什么无法将apk文件安装到虚拟器里面?
关键要看你用什么架构编译的apk文件,如果你用mips架构的ndk编译,那就会出现安装到arm架构的模拟器上面会失败。