Android JNI使用方法

jopen 12年前發布 | 220K 次閱讀 Android Android開發 移動開發

經過幾天的努力終于搞定了android JNI部分,下面將我的這個小程序和大家分享一下。android JNI是連接android Java部分和C/C++部分的紐帶,完整使用JNI需要Java代碼和C/C++代碼。其中C/C++代碼用于生成庫文件,Java代碼用于引用C /C++庫文件以及調用C/C++方法。

android Java部分代碼:

jnitest.java

package com.hello.jnitest;

import android.app.Activity;

import android.os.Bundle;

public class jnitest extends Activity {

/** Called when the activity is first created. */

@Override

public void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    setContentView(R.layout.main);

    Nadd test = new Nadd();

    setTitle("The Native Add Result is "+String.valueOf(test.nadd(10, 20)));

} 

}

Nadd.java

package com.hello.jnitest;

public class Nadd {

static {

System.loadLibrary("hello_jni");

}

public native int nadd(int a, int b);

}</pre>

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++部分代碼:
#define LOG_TAG "hello-JNI"

include <stdio.h>

include <stdlib.h>

include <unistd.h>

include <sys/types.h>

include <sys/stat.h>

include <fcntl.h>

include <assert.h>

include "jni.h"

include "JNIHelp.h"

include "android_runtime/AndroidRuntime.h"

static jint com_hello_jnitest_jnitest_nadd(JNIEnv env, jobject obj, jint a, jint b) { return (a b); } static JNINativeMethod gMethods[] = { {"nadd", "(II)I", (void )com_hello_jnitest_jnitest_nadd}, }; static int register_android_test_hello(JNIEnv env) { return android::AndroidRuntime::registerNativeMethods(env, "com/hello/jnitest/Nadd", gMethods, NELEM(gMethods)); } jint JNI_OnLoad(JavaVM vm, void reserved) { JNIEnv *env = NULL; if (vm->GetEnv((void **)&env, JNI_VERSION_1_4) != JNI_OK) { printf("Error GetEnv\n"); return -1; } assert(env != NULL); if (register_android_test_hello(env) < 0) { printf("register_android_test_hello error.\n"); return -1; } return JNI_VERSION_1_4; }</pre>

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代碼:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_PRELINK_MODULE := false
LOCAL_SRC_FILES := \
com_hello_jnitest.cpp
LOCAL_SHARED_LIBRARIES := \
libandroid_runtime
LOCAL_MODULE := libhello_jni
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 

</div>

之后在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 

</div>

注意:此時有可能出現Out of Memory的錯誤提示。當出現如上錯誤提示時,需要使用#adb remount重新加載一下就可以了。
另外,也有可能直接使用eclipse啟動android虛擬機時出現上述錯誤且使用#adb remount也出現的情況,此時需要手動啟動android虛擬機,如:#emulator -avd xxx -partition-size 128,之后在使用#adb push就可以了。

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!