[转]Android JNI使用办法

本文转自:http://www.open-open.com/lib/view/open1324909652374.html

 

通过几龙的努力终于搞定了android
JNI部分,下面将自之斯小程序与大家大快朵颐一下。android JNI是连接android
Java部分与C/C++部分的关键,完整使用JNI需要Java代码和C/C++代码。其中C/C++代码用于生成库文件,Java代码用于引用C
/C++库文件和调用C/C++方法。

android Java部分代码:

01 jnitest.java
02   
03 package com.hello.jnitest;
04   
05    
06   
07 import android.app.Activity;
08   
09 import android.os.Bundle;
10   
11    
12   
13 public class jnitest extends Activity {
14   
15     /** Called when the activity is first created. */
16   
17     @Override
18   
19     public void onCreate(Bundle savedInstanceState) {
20   
21         super.onCreate(savedInstanceState);
22   
23         setContentView(R.layout.main);
24   
25         Nadd test = new Nadd();
26   
27         setTitle("The Native Add Result is "+String.valueOf(test.nadd(10, 20)));
28   
29     
30   
31 }
32   
33 Nadd.java
34   
35 package com.hello.jnitest;
36   
37    
38   
39 public class Nadd {
40   
41 static {
42   
43 System.loadLibrary("hello_jni");
44   
45 }
46   
47    
48   
49 public native int nadd(int a, int b);
50   
51 }

Java代码说明:

1)jnitest.java是一个activity的切近对象,在此类对象被生成调用JNI函数的接近对象,同时调用JNI方法,最后以JNI方法的结果显示到标题栏上;

2)Nadd.java是一个引用和声明JNI库和函数的接近,其中System.loadLibrary();函数用来引用JNI库,默认JNI库放在
android系统的/system/lib/目录下;public nadd int nadd(int a, int
b);为声明需要以java程序中以的JNI库中的函数;

JNI中java部分的代码到此就得了了,总结一下于java代码中要开片桩事:

1)使用System.loadLibrary()函数来引用JNI库;

2)声明调用JNI库的函数且前添加native关键字;

android C/C++部分代码:

01 #define LOG_TAG "hello-JNI"
02 #include <stdio.h>
03 #include <stdlib.h>
04 #include <unistd.h>
05 #include <sys/types.h>
06 #include <sys/stat.h>
07 #include <fcntl.h>
08 #include <assert.h>
09 #include "jni.h"
10 #include "JNIHelp.h"
11 #include "android_runtime/AndroidRuntime.h"
12 static jint com_hello_jnitest_jnitest_nadd(JNIEnv *env, jobject obj, jint a, jint b)
13 {
14 return (a * b);
15 }
16 static JNINativeMethod gMethods[] = {
17 {"nadd", "(II)I", (void *)com_hello_jnitest_jnitest_nadd},
18 };
19 static int register_android_test_hello(JNIEnv *env)
20 {
21 return android::AndroidRuntime::registerNativeMethods(env, "com/hello/jnitest/Nadd", gMethods, NELEM(gMethods));
22 }
23 jint JNI_OnLoad(JavaVM *vm, void *reserved)
24 {
25 JNIEnv *env = NULL;
26 if (vm->GetEnv((void **)&env, JNI_VERSION_1_4) != JNI_OK) {
27 printf("Error GetEnv\n");
28 return -1;
29 }
30 assert(env != NULL);
31 if (register_android_test_hello(env) < 0) {
32 printf("register_android_test_hello error.\n");
33 return -1;
34 }
35 return JNI_VERSION_1_4;
36 }

JNI C/C++代码说明:

1)JNI_OnLoad()函数。该函数以Java程序调用System.loadLibrary()时,被调用执行,用于向JavaVM注册JNI函数等。在本例中首先通过参数JavaVM(Java虚拟机指南针)获取当前应用程序所于的线程,即:JNIEnv。再经调用
android::AndroidRuntime::registerNativeMethods()注册native实现的函数指针。

2)JNI函数和Java调用函数的照射关系。使用JNINativeMethod将java调用的函数名及JNI实现的函数誉为联系在同;

3)JNI函数实现;

Android.mk代码:

1 LOCAL_PATH := $(call my-dir)
2 include $(CLEAR_VARS)
3 LOCAL_PRELINK_MODULE := false
4 LOCAL_SRC_FILES := \
5 com_hello_jnitest.cpp
6 LOCAL_SHARED_LIBRARIES := \
7 libandroid_runtime
8 LOCAL_MODULE := libhello_jni
9 include $(BUILD_SHARED_LIBRARY)

需要注意的是:

1)JNI
C/C++部分的代码用以android源代码树上进行编译,编译完成后我之做法是直用扭转的.so通过adb
push方法上盛传android虚拟机的/system/lib/目录下;

2)java代码可以在eclipse下直编译且在虚拟机上执行;

编译JNI C/C++部分代码(在android内核源代码根目录下):

#make libhello_jni

自此在out/target/product/generic/system/lib/目录下生成libhello_jni.so

上传libhello_jni.so到android虚拟机:

#adb push out/target/product/generic/system/lib/libhello_jni.so
/system/lib

瞩目:此时来或出现Out of
Memory的荒谬提示。当出现如达到错误提示时,需要用#adb
remount重新加载一下不怕可以了。

另外,也生或直接采用eclipse启动android虚拟机时起上述荒唐都以#adb
remount也应运而生的景况C++,此时待手动启动android虚拟机,如:#emulator -avd
xxx -partition-size 128,之后于动#adb push就得了。