android JNI使用方法

通過幾天的努力終於搞定了android JNI部分,下面將個人這個小程序和你們分享一下。android JNI是鏈接android Java部分和C/C++部分的紐帶,完整使用JNI須要Java代碼和C/C++代碼。其中C/C++代碼用於生成庫文件,Java代碼用於引用C/C++庫文件以及調用C/C++方法。java

android Java部分代碼:android

jnitest.java小程序

package com.hello.jnitest;app

 

import android.app.Activity;eclipse

import android.os.Bundle;ide

 

public class jnitest extends Activity {函數

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

    @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);

}

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;
}

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
以後在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也出現的狀況,此時須要手動啓動android虛擬機,如:#emulator -avd xxx -partition-size 128,以後在使用#adb push就能夠了。
相關文章
相關標籤/搜索