1.设置NDK路径
选择File -> Project structure,设置NDK路径,如果没有也可以在线下载。
2.新建project
在创建引导界面中,选中support c/c++,此时Android studio会默认使用CMake工具,并在gradle 中进行相关的配置,创建完成后,主要配置的代码如下:
defaultConfig {
applicationId "com.lc.jnitest"
minSdkVersion 17
targetSdkVersion 24
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
externalNativeBuild {
cmake {
cppFlags ""
}
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
externalNativeBuild {
cmake {
path "CMakeLists.txt"
}
}
同时切换到Android 视图,最低部会有一个External Build Files,其中包含了一个CMakeList.txt,这个文件非常重要:
add_library( # Sets the name of the library.
native-lib
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
# Associated headers in the same location as their source
# file are automatically included.
src/main/cpp/native-lib.cpp )
android studio 默认为创建一个JNI的示范程序,上面的“native-lib"指的是生成.so文件后的库名,"SHARED"是否作为一个分享库。
"src/main/cpp/native-lib.cpp"指的是所对应的c/c++文件,之前一般的.cpp或.c文件我们经常会创建一个文件夹”jni",这里android studio为我们创建好了cpp文件夹,专门放置c/c++文件。
在MainActivity中我们可以看到系统加载库以及java本地方法的声明:
public native String stringFromJNI();
// Used to load the 'native-lib' library on application startup.
static {
System.loadLibrary("native-lib");
}
这里设置的库名必须与我们在CMakeList.txt中设置保持一致。
3.开始新建JNIDemo
这里我们首先在包名下创建一个叫util的包,在其中创建一个java类GetSum,代码片段如下:
public class GetSum {
public int number=10;
public ArrayList mArrayList;
public GetSum(){
mArrayList = new ArrayList<>();
mArrayList.add(5);
mArrayList.add(7);
}
public boolean isEqual(ArrayList<Integer> list){
if(list.get(0) == list.get(1))
return true;
else
return false;
}
static {
System.loadLibrary("getSum");
}
public native int sum(int a ,int b);
}
然后开始在cpp目录创建c++文件,源码如下:
#include<iostream>
using namespace std;
int getPart(int a, int b);
int getMin(int a, int b) {
return a > b ? a : b;
}
extern "C"
jint
Java_com_lc_jnitest_util_GetSum_sum(
JNIEnv *env,
jobject /* this */ obj, jint a, jint b) {
jclass getSum = env->GetObjectClass(obj);
jfieldID numberId = env->GetFieldID(getSum, "number", "I");
jint number = env->GetIntField(obj, numberId);
jfieldID listId = env->GetFieldID(getSum, "mArrayList", "Ljava/util/ArrayList;");
jobject list = env->GetObjectField(obj, listId);
jmethodID jmethodID1 = env->GetMethodID(getSum, "isEqual", "(Ljava/util/ArrayList;)Z");
jboolean equal = env->CallBooleanMethod(obj, jmethodID1, list);
jclass listclass = env->GetObjectClass(list);
jmethodID size_methodID = env->GetMethodID(listclass, "size", "()I");
jint num = env->CallIntMethod(list, size_methodID);
int temp = getPart(num, number);
return a + b + number + num + temp + getMin(temp, num);
}
int getPart(int a, int b) {
return a * b;
}`
这里有几点要注意:
1. "jint Java_com_lc_jnitest_util_GetSum_sum(JNIEnv *env,jobject /* this */ obj, jint a, jint b)"该函数名称必须与你所声明的java方法进行对应。
"jint"返回类型,对应上面的"int",函数名则是包名+类名+方法名,函数中的参数除了JNIENv *env,与jobject之外,另外的要与原先的方法保持一致。
至于前两个参数如何使用,文章末尾会有相关的博客的链接方便进行学习。
2. 注意"extern "C""的位置,必须放在该对应函数的前面,否则运行会报错
接下来就需要修改CMakeList.txt的配置,本例配置如下:
target_link_libraries( getSum native-lib ${log-lib} )`
修改完成后,进行rebuild project ,就可以运行。
本例参考链接:
代码编写:http://blog.csdn.net/jiangwei0910410003/article/details/17465457
工具配置:http://m.blog.csdn.net/article/details?id=51927631