目录:
一. 吐槽:
每当写一篇教程,我都喜欢对比网上的内容,其中不难发现,写出详细教程的文章太少了,动不动就来个跳跃式,初学者跟了一半跟丢了,所以针对这种情况我特意写了一篇详细的AS下的JNI开发,废话少说,进入正题
二. JNI和NDK的介绍
1.为什么使用AS环境下JNI开发?
AS于2013谷歌大会公布,而且谷歌大爷宣称15年后不再支持eclipse,所以爱着Eclipse的Android娃们,赶紧移情AS吧.
2.JNI是什么?
1.翻译过来就是JAVA Native interface
- java本地接口,它是一种协议,提供一套编程框架,让java和本地语言(c/c++)能相互调用
2.我们好端端的java为什么要用c/c++,要用jni这玩意?
- 1.java是各种平台下都能运行,浪得一逼,编译一次能各地乱窜.
- 2.但浪是要有代价的,就是浪不过本地的,c/c++就是比你高效.
- 3.因为c/c++人家是直接能操作底层硬件了,人家能上山砍柴爬树下水摸鱼,你城里来的java比这方面当然速度没人家快.
- 4.所以Android app需要进行底层操作硬件,要求应用效率高,且安全,就需要jni来实现java和本地c/c++之间的交互调用(java你想吃山货,喊一声c大哥去帮你摘下来).
3.NDK是什么?
全称: Native Development Kit,翻译过来就是本地开发工具,用来构建本地c/c++源程序,生成.so动态库,让Android 程序中的Java文件通过jni调用
说白了就是本地人的砍刀,渔网,火炮,用来上山砍柴打鸟,下水摸鱼,弄成一桌山珍海味,让你们这帮城里来的不会抓鱼的java小青年能尝尝,因为人家本地人c/c++有权这么做.
4.JNI和NDK关系图
三. 开发详细步骤
需求:
- 1.c/c++源文件里的内容是一句话字符串:hello From C
- 2.Android应用中java通过JNI调用本地的这句话,并弹吐司.
步骤:
- 1.新建一个新的项目,创建一个类,就叫JNI吧.(1.要加载动态库,2,定义和本地交互的方法)
package goodjobtome.com.jni_jdk;
public class JNI {
// 本地native方法获得字符串,本地方法由c/c++实现,我们只是调用
public static native String helloFromC();
}
- 2.在MainActivity里面创建的时候就新建JNI类,调用其中的方法获取字符串,弹吐司
public class MainActivity extends Activity {
@Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
JNI jni = new JNI();
Toast.makeText(this, jni.helloFromC(), Toast.LENGTH_SHORT).show();
}
}
- 3.右击你的项目名称,点击新建jni文件夹(如图),就会得到一个jni文件夹
- 4.右击jni文件夹新建c/c++源文件,名称就填:helle-jni,type类型选.c/h
选类型
生成两个文件.c和.h
- 5.点击一下你的项目名,点击菜单栏:Builde->Make Module’你的项目名称’
此时如果运行出现警告错误如图
在gradle.properties加下面一句话就可以解决
运行后通过后:点击进入项目名->builder->intermediates->classes/debug目录下.
右击这个文件夹,复制路径.如上图
然后点击控制台的Terminal窗口,输入:cd 粘贴路径,回车
进入当前文件夹后 编译我们刚刚的JNI类,注意包名要写全
6.点击回车后,你的debuge目录下就会生产一个.h的文件
7.把这个文件复制到你的jni文件夹里,此时就有两个.h和一个.c了
打开这个带着包名的.h文件,复制红色区域这个部分
8.粘贴到我们的hello-jni.c里边,并且在头部哪里添加include,带着包名的.h(如图)
代码如下
JNIEXPORT jstring JNICALL Java_goodjobtome_com_jni_1jdk_JNI_helloFromC
(JNIEnv * env, jclass obj){
char chars[] = "Hello From C,HaHa!";
//把c里的字符串转为java里的String对象
return (*env)->NewStringUTF(env,chars);
}
9.确定好你已经安卓和配置了NDK本地路径
10.在build.gradle的defautConfig添加ndk{}信息
代码如下
ndk { //指定生成模块名字,也就是最终的动态库名hello-jni,相应库文件名libhello-jni.so
moduleName "hello-jni"
// 指定生成哪些处理器架构的动态库文件,如果要运行在x86架构处理器一定需要指定
// abiFilters "armeabi" , "x86"
}
注意有人添加了上面的x86可能导致蓝屏,特别是win8,win10的,你们要装好win8,win10的加速器.
11.在JNI中加载动态库
static {
// 指定库名,为了加载动态库,和build.gradle中指定的库名一致
System.loadLibrary("hello-jni");
}
完整代码如下
package goodjobtome.com.jni_jdk;
public class JNI {
static {
// 指定库名,为了加载动态库,和build.gradle中指定的库名一致
System.loadLibrary("hello-jni");
}
// 本地native方法获得字符串,本地方法由c/c++实现,我们只是调用
public static native String helloFromC();
}
最后,开启虚拟机,看看我们的成功的效果吧: