436
京東網上商城
android JNI學習
經過幾天的努力終於搞定了android JNI部分,下麵將我的這個小程序和大家分享一下。android JNI是連接android Java部分和C/C++部分的紐帶,完整使用JNI需要Java代碼和C/C++代碼。其中C/C++代碼用於生成庫文件,Java代碼用於引用C /C++庫文件以及調用C/C++方法。
android Java部分代碼:
03 |
package com.hello.jnitest;
|
07 |
import android.app.Activity;
|
09 |
import android.os.Bundle;
|
13 |
public class
jnitest extends
Activity {
|
15 |
/** Called when the activity is first created. */
|
19 |
public
void onCreate(Bundle savedInstanceState) {
|
21 |
super .onCreate(savedInstanceState);
|
23 |
setContentView(R.layout.main);
|
25 |
Nadd test =
new Nadd();
|
27 |
setTitle( "The Native Add Result is " +String.valueOf(test.nadd( 10 ,
20 )));
|
35 |
package com.hello.jnitest;
|
43 |
System.loadLibrary( "hello_jni" );
|
49 |
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++部分代碼:
01 |
#define LOG_TAG "hello-JNI" |
05 |
#include <sys/types.h> |
11 |
#include "android_runtime/AndroidRuntime.h" |
12 |
static
jint com_hello_jnitest_jnitest_nadd(JNIEnv *env, jobject obj, jint a, jint b)
|
16 |
static
JNINativeMethod gMethods[] = {
|
17 |
{ "nadd" ,
"(II)I" , ( void
*)com_hello_jnitest_jnitest_nadd},
|
19 |
static
int register_android_test_hello(JNIEnv *env)
|
21 |
return
android::AndroidRuntime::registerNativeMethods(env, "com/hello/jnitest/Nadd" , gMethods, NELEM(gMethods));
|
23 |
jint JNI_OnLoad(JavaVM *vm, void
*reserved)
|
26 |
if (vm->GetEnv(( void
**)&env, JNI_VERSION_1_4) != JNI_OK) {
|
27 |
printf ( "Error GetEnv\n" );
|
31 |
if (register_android_test_hello(env) < 0) {
|
32 |
printf ( "register_android_test_hello error.\n" );
|
35 |
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代碼:
1 |
LOCAL_PATH := $(call my-dir) |
3 |
LOCAL_PRELINK_MODULE := false
|
6 |
LOCAL_SHARED_LIBRARIES := \ |
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也出現的情況,此時需要手動啟動android虛擬機,如:#emulator -avd xxx -partition-size 128,之後在使用#adb push就可以了。
最後更新:2017-04-03 12:53:47