为什么使用jni
JNI,java native interface(java本地接口),用于在java中调用本地语言,这里的本地语言一般为C/C++。
一般需要在java中使用C的原因有两个:1.java是基于jvm的,因此无法直接驱动硬件,所以当我们需要直接驱动硬件的时候就需要调用本地语言。
2.C代码的执行效率要远远高于java代码,当我们需要提高效率的时候就要用到jni,比如对于图像的处理等待。
怎样使用
这里主要介绍如何在Android Studio中使用jni
1.在java代码中声明本地方法,关键字native
![如何在Android Studio中使用JNI 如何在Android Studio中使用JNI](https://image.shishitao.com:8440/aHR0cHM6Ly9waWFuc2hlbi5jb20vaW1hZ2VzLzkxOS82ODI5ZGI4MjZmNDMzNDFhODk3NjE0NjQ1ZGNkNTlhNy5wbmc%3D.png?w=700&webp=1)
2.配置NDK环境
Tools->Android->SDK Manager->Android SDK->SDK Tools->勾选LLDB和NDK点击OK进行安装
![如何在Android Studio中使用JNI 如何在Android Studio中使用JNI](https://image.shishitao.com:8440/aHR0cHM6Ly9waWFuc2hlbi5jb20vaW1hZ2VzLzc2MC9kZDQ0MmI4YWJiOTljYmNkZDFiZWExMjQxYWQ4YmEzMC5wbmc%3D.png?w=700&webp=1)
![如何在Android Studio中使用JNI 如何在Android Studio中使用JNI](https://image.shishitao.com:8440/aHR0cHM6Ly9waWFuc2hlbi5jb20vaW1hZ2VzLzI5Mi82MTM2ZTM2OWVlMDQyYTViZTRjMDI2YjgxZDA1NTEwYy5wbmc%3D.png?w=700&webp=1)
3.在Android Studio自带的命令行工具Terminal中
先通过cd命令进入到src->main->java目录下
然后通过命令javah -jni生成.h文件
![如何在Android Studio中使用JNI 如何在Android Studio中使用JNI](https://image.shishitao.com:8440/aHR0cHM6Ly9waWFuc2hlbi5jb20vaW1hZ2VzLzEyLzA4YTdiMDY1NWY5ZWIwM2JkYTUwMWNiOTI2NDA5MTA0LnBuZw%3D%3D.png?w=700&webp=1)
如果没问题就会生成一个.h文件
![如何在Android Studio中使用JNI 如何在Android Studio中使用JNI](https://image.shishitao.com:8440/aHR0cHM6Ly9waWFuc2hlbi5jb20vaW1hZ2VzLzU5Ni80MDQxNWMyMTkxNGI0MDFhNDhiNGI4NWZjYzcxZTZhNC5wbmc%3D.png?w=700&webp=1)
这个文件唯一的作用就是帮助我们写C代码中的方法
打开这个文件,最重要的一句话就是
JNIEXPORT jstring JNICALL Java_com_zhuoxin_jnitest_MainActivity_getStrFromJNI (JNIEnv *, jobject);
这句话的作用稍后再说
4.在app目录下创建jni目录
在jni目录下创建C文件和Android.mk文件
![如何在Android Studio中使用JNI 如何在Android Studio中使用JNI](https://image.shishitao.com:8440/aHR0cHM6Ly9waWFuc2hlbi5jb20vaW1hZ2VzLzk5MC8yODUwMTIxNDk2ODc2ODJkNTFhMDkwZWM5MTg0ZTRiNi5wbmc%3D.png?w=700&webp=1)
首先打开demo.c
声明C代码中的函数
#include <jni.h> jstring Java_com_zhuoxin_jnitest_MainActivity_getStrFromJNI(JNIEnv *env,jobject thiz) { return (*env)->NewStringUTF(env, "Hello From jni!!!"); }
其中红色部分就是刚刚生成的.h文件中直接粘贴过来并稍作修改的,至于哪里修改了请仔细看,h文件的作用就是帮助我们写本地方法的名称用的,用完就可以删了。
再打开Android.mk文件
其中代码如下:
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) #清除之前生成的东西 LOCAL_MODULE := demo LOCAL_SRC_FILES := demo.c include $(BUILD_SHARED_LIBRARY)
几个重要配置:
a.gradle.properties中加上一句话:
android.useDeprecatedNdk=true
b.local.properties中配置ndk路径
![如何在Android Studio中使用JNI 如何在Android Studio中使用JNI](https://image.shishitao.com:8440/aHR0cHM6Ly9waWFuc2hlbi5jb20vaW1hZ2VzLzYwNi9iYWYxN2EzMmIxMmNkOWI2MDZkNzkyYjljYjJmMGZiZS5wbmc%3D.png?w=700&webp=1)
c.在app的gradle中的android节点下配置如下;
sourceSets{ main{ jniLibs.srcDirs = ['libs'] } }
![如何在Android Studio中使用JNI 如何在Android Studio中使用JNI](https://image.shishitao.com:8440/aHR0cHM6Ly9waWFuc2hlbi5jb20vaW1hZ2VzLzQ4OC80M2QxYjVhZTgxNjE4NzkwODQ2NGFkMTE1ZWZiYTExOC5wbmc%3D.png?w=700&webp=1)
![如何在Android Studio中使用JNI 如何在Android Studio中使用JNI](https://image.shishitao.com:8440/aHR0cHM6Ly9waWFuc2hlbi5jb20vaW1hZ2VzLzQ4OC80M2QxYjVhZTgxNjE4NzkwODQ2NGFkMTE1ZWZiYTExOC5wbmc%3D.png?w=700&webp=1)
执行效果如上图
此时会生成libs和obj目录
![如何在Android Studio中使用JNI 如何在Android Studio中使用JNI](https://image.shishitao.com:8440/aHR0cHM6Ly9waWFuc2hlbi5jb20vaW1hZ2VzLzYxNS83OTNhMWY4YWNmOTU2NmVhZGNkMDE5ZmYyMDc1MDI5Ny5wbmc%3D.png?w=700&webp=1)
5.在java中调用本地方法
public class MainActivity extends AppCompatActivity { static { System.loadLibrary("demo"); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } //使用native关键字声明本地方法 public native String getStrFromJNI(); public void callCMethod(View view){ String mStrFromJNI = getStrFromJNI(); Toast.makeText(this,mStrFromJNI,Toast.LENGTH_SHORT).show(); } }
这段代码就是调用c中的方法,在界面上弹一个吐司。
效果:
![如何在Android Studio中使用JNI 如何在Android Studio中使用JNI](https://image.shishitao.com:8440/aHR0cHM6Ly9waWFuc2hlbi5jb20vaW1hZ2VzLzg1MS9hZDk4NDdjMmVlNDhmNTI2ZGE4ZmQwYWVkYjQ3YzA1My5wbmc%3D.png?w=700&webp=1)
大功告成!