您的位置:首页 > 移动开发 > Android开发

Android JNI 学习笔记

2011-11-17 16:32 429 查看

1. JNI 入门

最近学习了下JNI,记录下感受。

JNI(Java NativeInterface), its objective is to call those function which has implemented inlower-level programming language, such as C, C++

Implement steps:

S1. Write the JAVA classwith Native declaration

public classCamcorderProfile{

……

static {

System.loadLibrary("media_jni");

native_init();

}

private staticnative final voidnative_init();

private static native finalCamcorderProfile native_get_camcorder_profile(int cameraId, int quality);

private static native final booleannative_has_camcorder_profile(

int cameraId, int quality);}

声明native方法:如果你想将一个方法做为一个本地方法的话,那么你就必须声明改方法为native的,并且不能实现。其中方法的参数和返回值在后面讲述。

  

   Load动态库:System.loadLibrary("media_jni");加载动态库(我们可以这样理解:我们的方法 native_init()没有实现,但是我们在下面就直接使用了,所以必须在使用之前对它进行初始化)这里一般是以static块进行加载 的。同时需要注意的是System.loadLibrary();的参数“media_jni”是动态库的名字。

S2. 编写本地方法

static void

android_media_MediaScanner_native_init(JNIEnv*env)

static JNINativeMethodgMethodsForCamcorderProfileClass[] = {

{"native_init","()V", (void *)android_media_MediaScanner_native_init },

}

2. JNI 流程



Windows系统上的java体系
java程序中则是jvm通过加载并调用此jni程序来间接地调用目标原生函数。



Jni调用过程示意图

3. Android JNINativeMethod

a .JNINativeMethod

Andoird 中使用了一种不同传统Java JNI的方式来定义其native的函数。其中很重要的区别是Andorid使用了一种Java 和 C 函数的映射表数组,并在其中描述了函数的参数和返回值。这个数组的类型是JNINativeMethod,定义如下:
typedef struct{
const char* name;
const char* signature;
void* fnPtr;
} JNINativeMethod;

第一个变量name是Java中函数的名字。
第二个变量signature,用字符串是描述了函数的参数和返回值
第三个变量fnPtr是函数指针,指向C函数。
其中比较难以理解的是第二个参数,例如
"()V" void Func()

"(II)V" void Func(int, int)

"(Ljava/lang/String;Ljava/lang/String;)V"

具体的每一个字符的对应关系如下

字符 Java类型 C类型 长度

V void void n/a

Z jboolean boolean 8

I jint int 32

J jlong long 64

D jdouble double 64

F jfloat float 32

B jbyte byte 8

C jchar char 16

S jshort short 16

数组则以”[“开始,用两个字符表示

[I jintArray int[]

[F jfloatArray float[]

[B jbyteArray byte[]

[C jcharArray char[]

[S jshortArray short[]

[D jdoubleArray double[]

[J jlongArray long[]

[Z jbooleanArray boolean[]

上面的都是基本类型。如果Java函数的参数是class,则以”L”开头,以”;”结尾中间是用”/” 隔开的包及类名。而其对应的C函数名的参数则为jobject. 一个例外是String类,其对应的类为jstring

Ljava/lang/String; String jstring

static JNINativeMethodgMethodsForCameraProfileClass[] = {
{"native_init","()V",(void *)android_media_MediaProfiles_native_init},
{"native_get_num_image_encoding_quality_levels","(I)I", (void*)android_media_MediaProfiles_native_get_num_image_encoding_quality_levels},
{"native_get_image_encoding_quality_level","(II)I", (void*)android_media_MediaProfiles_native_get_image_encoding_quality_level},
};

b.注册JNI

static const char* const kCamcorderProfileClassPathName ="android/media/CamcorderProfile";

int register_android_media_MediaProfiles(JNIEnv *env)

{ int ret2 = AndroidRuntime::registerNativeMethods(env,

kCamcorderProfileClassPathName,

gMethodsForCamcorderProfileClass,

NELEM(gMethodsForCamcorderProfileClass)),

Return ret2;}

c.JNI_OnLoad

jint JNI_OnLoad(JavaVM* vm, void* reserved) {

JNIEnv* env = NULL;

jint result = -1;

LOGI("JNI_OnLoad");

if (register_android_media_MediaProfiles(env) < 0) {

LOGE("ERROR: MediaProfiles native registration failed");

goto fail;}

/* success -- return valid version number */

result = JNI_VERSION_1_4;

fail:

return result;}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息