申明:本人实测通过。顺便鄙视下网上很多人都没测试过乱发。
文件目录结构为:app/src/main/java/com/hd/jni
1.定义java文件接口
package com.hd.jni;
public class JNITest {
public native static String getStringFromJNI();
}
2.进入com/hd/jni文件夹,命令:cd com/hd/jni,里面有一个JNITest.java文件,执行命令:javac JNITest.java,在当前目录下会生成JNITest.class 文件
3.退到包外面(务必退出到包外面,此处是java目录),执行命令:javah -jni com.hd.jni.JNITest必须是全包名,在java目录下生成com_hd_jni_JNITest.h文件,(如果编译不过,出现找不到类之类的问题,请注意是否在正确的文件夹)
4.在main目录下新建jni文件夹,拷贝com_hd_jni_JNITest.h文件到jni目录下,新建一个.c文件,此处为JNITest.c,首先引入刚才编译好的头文件,而后拷贝头文件中对应java中的接口并实现接口,代码如下:
#include "com_hd_jni_JNITest.h"
JNIEXPORT jstring JNICALL Java_com_hd_jni_JNITest_getStringFromJNI(JNIEnv *env , jclass obj)
{
char *str="String from native C";
return (*env)->NewStringUTF(env, str);
}
5.增加app下gradle配置项
sourceSets {
main {
jni.srcDirs = ['src/main/jni']
}
}
在defaultConfig中增加:
ndk {
moduleName "testjni" //生成的so文件名字,调用C程序的代码中会用到该名字
abiFilters "armeabi", "armeabi-v7a", "x86" //输出指定三种平台下的so库
}
gralde.properties最后一行增加代码:android.useDeprecatedNdk=true
systemProp.http.proxyHost=127.0.0.1
systemProp.http.proxyPort=9001
org.gradle.daemon=true
org.gradle.jvmargs=-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005
android.useDeprecatedNdk=true
6.clear工程,rebuild,如果出现下面错误,请注意你的buildToolsVersion版本可能没有对应NDK工具,请查看NDK platform文件夹,修改成有对应的版本的版本号就OK了,重新clear-> rebuild,成功会在app/build/intermediates/ndk/debug/lib下生成对应的so库。
Error:(115) *** Android NDK: Aborting . Stop.
NDK_PROJECT_PATH=null
7.拷贝so库到gradle配置的lib文件夹,我这里配置为src/main/libs
sourceSets {
main {
jni.srcDirs = ['src/main/jni']
jniLibs.srcDirs = ['src/mian/libs']
}
}
8.java代码中引用,注意:生成的.so默认会在我们定义的名字前面加上lib,我们引入的时候不需要带系统加的lib前缀
package com.hd.jni;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.Toast;
import com.hd.studyandtest.R;
import butterknife.ButterKnife;
import butterknife.OnClick;
public class JNITestActivity extends AppCompatActivity {
static {
System.loadLibrary("testjni");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_jnitest);
ButterKnife.bind(this);
}
@OnClick(R.id.jni)
public void onViewClicked() {
String str = JNITest.getStringFromJNI();
Toast.makeText(JNITestActivity.this, str, Toast.LENGTH_LONG).show();
}
}