一、什么是JNI
1.Java本地开放接口(java native interface)
2.作用相当于一个桥梁,是java与C之间调用的一种协议
3.通过JNI就可以让java调用C或C++代码,并且可以让C调java代码
4.当java中的某个方法类似涉及大量的数学运算时,java的效率就不如C高了,例如压缩跟解码处理,大多是用C来写的,都很消耗性能(直播、视频处理、图片处理都是用C)
Android系统图:
二、为什么要用JNI
1.native coder执行效率高:大量的运算(极品飞车)、万能解码(FFmpeg)、Opengl(3D渲染)
代码复用:ffmpe,onencv(人脸识别库),7-zip(开源压缩软件)
三、怎么使用JNI
ndk : native develop kits
将C文件编译成so文件
so文件的引用:http://blog.csdn.net/qq_32239767/article/details/54645661
用处范例:增量升级
四、C语言基础
1.这里用Dev-c来写C程序,感觉起来不如VC6.0用着顺手
2.java基本数据类型与C语言的不同点
⑴java中char类型占2个字节,C语言中长度占1个字节
⑵java中long类型占8个字节,C语言中长度占4个字节
⑶C语言中没有boolean类型,C语言中0表示false,非0表示true
C语言中没有bool类型,用特殊色彩标记关键字的功能是编辑器的功能而非编译器的功能,因为C++有bool类型,因此bool会被编辑器标亮,但是C语言编译器是不会认识这个关键字的。Bool是C++里的类型bool是布尔型变量,也就是逻辑型变量的定义符,只有一个字节。
⑷C语言中没有byte
⑸unsigned 无符号 0~255
signed 有符号 -128~127
⑹goto在java中只是保留并没有实际用处
⑺C语言中没有字符串,可以用字符数组表示
⑻C语言中有指针,指针就是内存地址
3.system(“pause”);//保持显示的状态
4.#include
#include<stdio.h>
#include<stdlib.h>
/**
枚举的值递增
默认首元素的值是0
*/
enum WeekDay {
Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday
};
main() {
enum WeekDay day = Wednesday;
printf("%d\n",day);
system("pause");
}
以上代码输出结果为6,但是可以把起始值改掉,例如:
#include<stdio.h>
#include<stdlib.h>
/**
枚举的值递增
默认首元素的值是0
*/
enum WeekDay {
Monday=4,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday
};
main() {
enum WeekDay day = Sunday;
printf("%d\n",day);
system("pause");
}
以上结果输出为10
7.别名typedef:把很长的名字用简写代替
#include <stdio.h>
#include <stdlib.h>
typedef int i;
typedef long l;
typedef float f;
main() {
i m = 10;
l n = 123123123;
f s = 3.1415;
printf("%d\n", m);
printf("%ld\n", n);
printf("%f\n", s);
system("pause");
}
8.结构体
#include<stdio.h>
#include<stdlib.h>
//定义结构
struct student{
int age;//4个字节
float score;//4个字节
char sex; //1个字节
} ;
main(){
//使用结构体
struct student stu = {18,98.9,'W'};
//结构体取值
printf("stu.age==%d\n",stu.age);
printf("stu.score==%.1f\n",stu.score);
printf("stu.sex==%c\n",stu.sex);
//结构体赋值
stu.age = 20;
stu.score = 100;
stu.sex = 'M';
printf("stu.age==%d\n",stu.age);
printf("stu.score==%.1f\n",stu.score);
printf("stu.sex==%c\n",stu.sex);
//结构体的长度
printf("struct student长度==%d\n",sizeof(struct student));
system("pause");
}
9.联合体
#include<stdio.h>
#include<stdlib.h>
//定义一个联合体,特点,所有的字段都是使用同一块内存空间;
union Mix {
long i; //4个字节
int k; //4个字节
char ii;//1个字节
};
main() {
printf("mix:%d\n",sizeof(union Mix));
//实验
union Mix m;
m.k = 123;
m.i = 100;
printf("m.i=%d\n",m.i);
printf("m.k=%d\n",m.k);
system("pause");
}
这里结构体长度大小的求解时要特别注意,时刻记住有个倍数的问题
10.在结构体中(*stuPoint).age 等价于 stuPoint->age
11.#define:
①在用#define定义常量时,行尾一般不能有分号,除非特意这样做
②define前边的#标志着define是一个预处理命令而不是C语句
③符号常量名最好使用大写字符来命名
五、Android Studio下的 NDK 环境配置
**注意:JNI是一个协议,NDK是Google提供的开发JNI的一个工具包
NDK(native develope kit):本地开发工具包
1.NDK随便找个目录放进去就行,但是目录路径中最好不要有中文或者空格
2.NDK各版本下载地址:http://tools.android-studio.org/
3.配置环境变量path
4.让ndk与Android studio进行关联
①在配置好ndk后local.properties中会自己显示ndk.dir=D:\adt-bundle-windows-x86_64-20140702\sdk\ndk-bundle
②在gradle.properties中添加android.useDeprecatedNdk=true//兼容老版本ndk
③编写代码
④在app的build.gradle中添加
ndk{
moduleName "Hello" //so文件: lib+moduleName+.so
abiFilters "armeabi", "armeabi-v7a", "x86" //cpu的类型
}
注:这个ndk代码块不写也可以,不过生成的.so文件的名字会是lib+项目名+.so,并且会把所有支持的CPU架构下的.so文件都编译出来,如果缺少你手机CPU架构的.so文件,程序会报错或者崩溃甚至是不能运行
5.NDK开发流程
①在java里面写native代码
②在main目录下创建jni目录写C代码–生成头文件
③配置动态链接库的名称
④加载动态链接库:针对不同CPU架构的手机它会编译成不同的.so文件
⑤开始使用
6.Java类型对应的JNI别名
最后附几篇关于NDK、JNI的博客链接:
链接1:http://blog.csdn.net/Tongseng/article/details/53005123