本文适合于在Android Studio使用JNI的新手,也适合于從Eclipse中轉移到Android Studio過來的開發者。
本人見識有限,若有纰漏,歡迎批評指正。極客精神,人人共享~
1. 開發平台:
Operating System:Mac OS X 10.11.3
Software: Android Studio 1.5.1
2. 開始搭建JNI平台:
1)確定本地上已經有NDK:
Android Studio 使用JNI入門
2)建立一個新的Module。
3)修改配置,打開如下圖所示的三個檔案:
Android Studio 使用JNI入門
在build.gradle(Android Studio Tab上顯示為Module的名字)檔案中添加ndk的說明:
Android Studio 使用JNI入門
moduleName是JNI庫的名字,在此處JNI庫的名字是“libmyjnitest.so”。
在gradle.properties檔案的末尾添加“android.useDeprecatedNdk=true”。
在local.properties檔案中注明路徑:
Android Studio 使用JNI入門
4)添加jni目錄:
右擊module,可以直接添加jni,如下圖:
平台基本搭建完成,以下可以開始寫代碼了。
3. 建立一個Java檔案作為具有native方法的測試類。
/**
* Created by zhuozengsi on 3/6/16.
*/
public final class MyJNITest {
public static native String printSomething(String str);
public static native long calFromJNI(int n);
static {
System.loadLibrary("myjnitest");
}
public static long calFromJava(int n){
long sum = 0;
for (int i = 1; i <= n; i++){
sum += i;
}
return sum;
}
}
我建立了一個MyJNITest 類,并在類中聲明了兩個native方法,并在static塊中加載JNI庫,注意:
該處的JNI庫要和第2步中配置的ndk的moduleName相同。
4. Build -> Make Project 或者Build -> Make Module,目的是編譯一下Java檔案,生成class檔案。
此時應該能在build/intermediates/classes/bebug 中看到編譯成功的class檔案,如下圖所示:
Android Studio 使用JNI入門
5. 在terminal中将用cd指令将目錄切換到build/intermediates/classes/bebug,然後執行以下指令:
javah -jni packageName.classFile
packageName是包名稱,classFile是具有native方法的Class檔案,如此處的 MyJNITest應該為:
javah -jni com.sige.test1.MyJNITest
執行成功的話,會在debug目錄下生成一個頭檔案,此處是:com_sige_test1_MyJNITest.h,一般命名都是按照包名加類名來的,如下圖。
Android Studio 使用JNI入門
将頭檔案剪切到建立的jni目錄中。頭檔案的内容為:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_sige_test1_MyJNITest */
#ifndef _Included_com_sige_test1_MyJNITest
#define _Included_com_sige_test1_MyJNITest
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_sige_test1_MyJNITest
* Method: printSomething
* Signature: (Ljava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_sige_test1_MyJNITest_printSomething
(JNIEnv *, jclass, jstring);
/*
* Class: com_sige_test1_MyJNITest
* Method: calFromJNI
* Signature: (I)J
*/
JNIEXPORT jlong JNICALL Java_com_sige_test1_MyJNITest_calFromJNI
(JNIEnv *, jclass, jint);
#ifdef __cplusplus
}
#endif
#endif
6. 在jni目錄中建立C檔案或者建立C++檔案,名字自定,我這裡是:myjnitest.cpp。
将頭檔案中定義的方法複制到C/C++檔案中,實作那些方法:
//
// Created by Zhuozengsi on 3/6/16.
//
#include "com_sige_test1_MyJNITest.h"
#include <stdio.h>
#include "test_cpp.h"
JNIEXPORT jstring JNICALL Java_com_sige_test1_MyJNITest_printSomething
(JNIEnv * env, jclass clazz, jstring str){
printf("Hello, JNI");
//return env->NewString((const jchar *) str, sizeof(str));
return get_string(env);
}
JNIEXPORT jlong JNICALL Java_com_sige_test1_MyJNITest_calFromJNI
(JNIEnv *env, jclass, jint n){
jlong sum = 0;
for (int i = 1; i <= n; ++i) {
sum += n;
}
return sum;
}
可以在該檔案調用其他C/C++代碼,如get_string(env)就是調用自己定義的函數。
7. 可以在其他地方調用native方法了。如在MainActivity中調用:
String strFromJNI = MyJNITest.printSomething("hello");
Log.i("TAG", "message from jni: " + strFromJNI);
輸出結果為:
Android Studio 使用JNI入門