本文适合于在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入门